summaryrefslogtreecommitdiffstats
path: root/tools/Sandcastle/Source/BuildAssembler
diff options
context:
space:
mode:
Diffstat (limited to 'tools/Sandcastle/Source/BuildAssembler')
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildAssembler/BuildAssembler.csproj93
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildAssembler/BuildAssemblerConsole.cs110
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildAssembler/GlobalSuppressions.cs17
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildAssembler/Properties/AssemblyInfo.cs38
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildAssembler.cs320
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildAssemblerLibrary.csproj94
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildComponent.cs82
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildComponentUtilities.cs146
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildContext.cs176
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/GlobalSuppressions.cs45
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/Properties/AssemblyInfo.cs43
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/BuildComponents.csproj155
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/CloneComponent.cs44
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/CodeReference.cs117
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/ComputeHashComponent.cs68
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/CopyFromFileComponent.cs146
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/CopyFromFiles.cs95
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/CopyFromIndexComponent.cs677
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/DisplayComponent.cs46
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/ExampleComponent.cs543
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/ForEachComponent.cs105
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/GlobalSuppressions.cs319
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/HxfGeneratorComponent.cs132
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/IfThenComponent.cs87
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/IndexedFileCache.cs192
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/IntellisenseComponent.cs338
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/IntellisenseComponent2.cs424
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/LiveExampleComponent.cs195
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/MsdnResolver.cs76
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/MsdnService.cs913
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/PlatformsComponent.cs674
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/AssemblyInfo.cs42
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/Settings.Designer.cs26
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/Settings.settings5
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/References.cs340
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveArtLinksComponent.cs195
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveConceptualLinksComponent.cs448
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveReferenceLinksComponent2.cs497
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/SaveComponent.cs149
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/SharedContentComponent.cs380
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/SnippetComponent.cs1223
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/SwitchComponent.cs77
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/SyntaxComponent.cs283
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/TargetCollection.cs2739
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/Targets.cs156
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/TaskGrabberComponent.cs371
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/TransformComponent.cs153
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/ValidateComponent.cs47
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/WdxResolveConceptualLinksComponent.cs299
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/CopyComponents/CopyComponents.csproj80
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/CopyComponents/GlobalSuppressions.cs17
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/CopyComponents/InheritDocumentationComponent.cs373
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/CopyComponents/Properties/AssemblyInfo.cs46
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/AspNetSyntax.cs210
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/CPlusPlusDeclarationSyntax.cs1065
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/CSharpDeclarationSyntax.cs982
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/FSharpDeclarationSyntax.cs988
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/GlobalSuppressions.cs301
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/JScriptDeclarationSyntax.cs475
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/JSharpDeclarationSyntax.cs648
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/Properties/AssemblyInfo.cs42
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/ScriptSharpDeclarationSyntax.cs614
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/SyntaxComponents.csproj105
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/SyntaxGenerators.cs435
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/VisualBasicDeclarationSyntax.cs961
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/VisualBasicUsageSyntax.cs778
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/XamlUsageSyntax.cs953
67 files changed, 23013 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildAssembler/BuildAssembler.csproj b/tools/Sandcastle/Source/BuildAssembler/BuildAssembler/BuildAssembler.csproj
new file mode 100644
index 0000000..0ceafb8
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildAssembler/BuildAssembler.csproj
@@ -0,0 +1,93 @@
+<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>{5BA19924-5A65-46E0-97CD-948595932584}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>BuildAssembler</RootNamespace>
+ <AssemblyName>BuildAssembler</AssemblyName>
+ <SccProjectName>
+ </SccProjectName>
+ <SccLocalPath>
+ </SccLocalPath>
+ <SccAuxPath>
+ </SccAuxPath>
+ <SccProvider>
+ </SccProvider>
+ <SignAssembly>false</SignAssembly>
+ <AssemblyOriginatorKeyFile>../../../key.snk</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>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'WebDocsDebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\WebDocsDebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Sandcastle|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Sandcastle\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BuildAssemblerConsole.cs" />
+ <Compile Include="GlobalSuppressions.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\CommandLine\CommandLine.csproj">
+ <Project>{6CF7CA42-3706-4F6B-A2B4-10EF3F511888}</Project>
+ <Name>CommandLine</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\BuildAssemblerLibrary\BuildAssemblerLibrary.csproj">
+ <Project>{399E78F8-4954-409E-991A-37DA9D0579CC}</Project>
+ <Name>BuildAssemblerLibrary</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/BuildAssembler/BuildAssemblerConsole.cs b/tools/Sandcastle/Source/BuildAssembler/BuildAssembler/BuildAssemblerConsole.cs
new file mode 100644
index 0000000..e4f0528
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildAssembler/BuildAssemblerConsole.cs
@@ -0,0 +1,110 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Reflection;
+using System.Xml;
+using System.Xml.XPath;
+
+using Microsoft.Ddue.Tools.CommandLine;
+
+namespace Microsoft.Ddue.Tools
+{
+ class BuildAssemblerConsole
+ {
+ public static int Main(string[] args)
+ {
+ ConsoleApplication.WriteBanner();
+
+ #region read command line arguments, and setup config
+
+ // specify options
+ OptionCollection options = new OptionCollection();
+ options.Add(new SwitchOption("?", "Show this help page."));
+ options.Add(new StringOption("config", "Specify a configuration file.", "configFilePath"));
+
+ // process options
+ ParseArgumentsResult results = options.ParseArguments(args);
+
+ // process help option
+ if (results.Options["?"].IsPresent)
+ {
+ Console.WriteLine("TocBuilder [options] rootDirectory");
+ options.WriteOptionSummary(Console.Out);
+ return (0);
+ }
+
+ // check for invalid options
+ if (!results.Success)
+ {
+ results.WriteParseErrors(Console.Out);
+ return (1);
+ }
+
+ // check for manifest
+
+ if (results.UnusedArguments.Count != 1)
+ {
+ Console.WriteLine("You must supply exactly one manifest file.");
+ return (1);
+ }
+
+ string manifest = results.UnusedArguments[0];
+
+ // Load the configuration file
+ XPathDocument configuration;
+ try
+ {
+ if (results.Options["config"].IsPresent)
+ {
+ configuration = ConsoleApplication.GetConfigurationFile((string)results.Options["config"].Value);
+ }
+ else
+ {
+ configuration = ConsoleApplication.GetConfigurationFile();
+ }
+ }
+ catch (IOException e)
+ {
+ ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The specified configuration file could not be loaded. The error message is: {0}", e.Message));
+ return (1);
+ }
+ catch (XmlException e)
+ {
+ ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The specified configuration file is not well-formed. The error message is: {0}", e.Message));
+ return (1);
+ }
+
+ #endregion
+
+ // create a BuildAssembler to do the work
+ BuildAssembler buildAssembler = new BuildAssembler();
+
+ try {
+
+ // load the context
+ XPathNavigator contextNode = configuration.CreateNavigator().SelectSingleNode("/configuration/dduetools/builder/context");
+ if (contextNode != null) buildAssembler.Context.Load(contextNode);
+
+ // load the build components
+ XPathNavigator componentsNode = configuration.CreateNavigator().SelectSingleNode("/configuration/dduetools/builder/components");
+ if (componentsNode != null) buildAssembler.AddComponents(componentsNode);
+
+ // proceed thorugh the build manifest, processing all topics named there
+ int count = buildAssembler.Apply(manifest);
+
+ ConsoleApplication.WriteMessage(LogLevel.Info, String.Format("Processed {0} topics", count));
+
+ } finally {
+ buildAssembler.Dispose();
+ }
+
+ return (0);
+ }
+ }
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildAssembler/GlobalSuppressions.cs b/tools/Sandcastle/Source/BuildAssembler/BuildAssembler/GlobalSuppressions.cs
new file mode 100644
index 0000000..88e273a
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildAssembler/GlobalSuppressions.cs
@@ -0,0 +1,17 @@
+// 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.
+
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+//
+// To add a suppression to this file, right-click the message in the
+// Error List, point to "Suppress Message(s)", and click
+// "In Project Suppression File".
+// You do not need to add suppressions to this file manually.
+
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildAssemblerConsole.#Main(System.String[])")]
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildAssembler/Properties/AssemblyInfo.cs b/tools/Sandcastle/Source/BuildAssembler/BuildAssembler/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..a5d12d9
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildAssembler/Properties/AssemblyInfo.cs
@@ -0,0 +1,38 @@
+// 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.
+
+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("BuildAssembler")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("BuildAssembler")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2006")]
+[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("381d8bb3-dbf9-4065-adbd-afebf844414b")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("2.5.10626.00")]
+[assembly: AssemblyFileVersion("2.5.10626.00")]
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildAssembler.cs b/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildAssembler.cs
new file mode 100644
index 0000000..ead3616
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildAssembler.cs
@@ -0,0 +1,320 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Reflection;
+using System.Xml;
+using System.Xml.XPath;
+
+using Microsoft.Ddue.Tools.CommandLine;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class BuildAssembler : IDisposable {
+
+ // the built context
+ public BuildAssembler()
+ {
+ this.handler = BuildAssembler.ConsoleMessageHandler;
+
+ }
+
+ // the built context
+ public BuildAssembler(MessageHandler messageHandler)
+ {
+ if (messageHandler == null) throw new ArgumentNullException("messageHandler");
+ this.handler = messageHandler;
+
+ }
+
+ // private data
+
+ private BuildContext context = new BuildContext();
+
+ private List<BuildComponent> components = new List<BuildComponent>();
+
+ private MessageHandler handler;
+
+ // data accessors
+
+ public BuildContext Context {
+ get {
+ return (context);
+ }
+ }
+
+ public BuildComponent[] BuildComponents {
+ get {
+ return (components.ToArray());
+ }
+ }
+
+ public MessageHandler MessageHandler {
+ get {
+ return (handler);
+ }
+ }
+
+ // component communication mechanism
+
+ public event EventHandler ComponentEvent;
+
+ internal void OnComponentEvent (Object o, EventArgs e) {
+ if (ComponentEvent != null) ComponentEvent(o, e);
+ }
+
+ // operations
+
+ public int Apply(IEnumerable<string> topics)
+ {
+ int count = 0;
+
+ foreach (string topic in topics)
+ {
+
+ // create the document
+ XmlDocument document = new XmlDocument();
+ document.PreserveWhitespace = true;
+
+ // write a log message
+ WriteMessage(MessageLevel.Info, String.Format("Building topic {0}", topic));
+
+ // apply the component stack
+ foreach (BuildComponent component in components)
+ {
+
+ component.Apply(document, topic);
+ }
+
+ count++;
+ }
+
+ return (count);
+ }
+
+ public int Apply (string manifestFile) {
+ return (Apply(new TopicManifest(manifestFile)));
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ foreach (BuildComponent component in components) {
+ ((IDisposable) component).Dispose();
+ }
+ }
+ }
+
+ private class TopicManifest : IEnumerable<string> {
+
+ public TopicManifest (string manifest) {
+ this.manifest = manifest;
+ }
+
+ private string manifest;
+
+ public IEnumerator<string> GetEnumerator () {
+ return (new TopicEnumerator(manifest));
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () {
+ return (GetEnumerator());
+ }
+
+ }
+
+ private class TopicEnumerator : IEnumerator<string> {
+
+ public TopicEnumerator (string manifest) {
+ reader = XmlReader.Create(manifest);
+ reader.MoveToContent();
+ }
+
+ private XmlReader reader;
+
+ public bool MoveNext () {
+ while (reader.Read()) {
+ if ((reader.NodeType == XmlNodeType.Element) && (reader.LocalName == "topic")) return (true);
+ }
+ return (false);
+ }
+
+ public string Current {
+ get {
+ string id = reader.GetAttribute("id");
+ return(id);
+ }
+ }
+
+ Object System.Collections.IEnumerator.Current {
+ get {
+ return (Current);
+ }
+ }
+
+ public void Reset () {
+ throw new InvalidOperationException();
+ }
+
+ public void Dispose () {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ reader.Close();
+ }
+ }
+
+ }
+
+ public IEnumerable<BuildContext> GetFileManifestBuildContextEnumerator(string manifestFilename)
+ {
+ using (XmlReader reader = XmlReader.Create(manifestFilename))
+ {
+ reader.MoveToContent();
+ while (reader.Read())
+ {
+ if ((reader.NodeType == XmlNodeType.Element) && (reader.LocalName == "topic"))
+ {
+ BuildContext thisContext = new BuildContext();
+
+ try
+ {
+ string id = reader.GetAttribute("id");
+
+ while (reader.MoveToNextAttribute())
+ {
+ string name = reader.Name;
+ string value = reader.Value;
+ thisContext.AddVariable(name, value);
+ }
+ }
+ catch (XmlException e)
+ {
+ throw new XmlException(String.Format("The manifest file: '{0}' is not well-formed. The error message is: {1}", manifestFilename, e.Message), e);
+ }
+
+ yield return thisContext;
+ }
+ }
+ }
+ }
+
+ public BuildComponent LoadComponent (XPathNavigator configuration) {
+
+ if (configuration == null) throw new ArgumentNullException("configuration");
+
+ // get the component infomation
+ string assemblyName = configuration.GetAttribute("assembly", String.Empty);
+ if (String.IsNullOrEmpty(assemblyName)) {
+ WriteMessage(MessageLevel.Error, "Each component element must have an assembly attribute that specifys a path to the component assembly.");
+ }
+
+ string typeName = configuration.GetAttribute("type", String.Empty);
+ if (String.IsNullOrEmpty(typeName)) {
+ WriteMessage(MessageLevel.Error, "Each component element must have a type attribute that specifys the fully qualified name of a component type.");
+ }
+
+ // expand environmet variables in path of assembly name
+ assemblyName = Environment.ExpandEnvironmentVariables(assemblyName);
+
+ // load and instantiate the component
+ BuildComponent component = null;
+ try {
+
+ Assembly assembly = Assembly.LoadFrom(assemblyName);
+ component = (BuildComponent) assembly.CreateInstance(typeName, false, BindingFlags.Public | BindingFlags.Instance, null, new Object[2] { this, configuration }, null, null);
+
+ } catch (IOException e) {
+ WriteMessage(MessageLevel.Error, String.Format("A file access error occured while attempting to load the build component assembly '{0}'. The error message is: {1}", assemblyName, e.Message));
+ } catch (BadImageFormatException e) {
+ WriteMessage(MessageLevel.Error, String.Format("The build component assembly '{0}' is not a valid managed assembly. The error message is: {1}", assemblyName, e.Message));
+ } catch (TypeLoadException) {
+ WriteMessage(MessageLevel.Error, String.Format("The build component '{0}' was not found in the assembly '{1}'.", typeName, assemblyName));
+ } catch (MissingMethodException e) {
+ WriteMessage(MessageLevel.Error, String.Format("No appropriate constructor exists for the build component '{0}' in the component assembly '{1}'. The error message is: {1}", typeName, assemblyName, e.Message));
+ } catch (TargetInvocationException e) {
+ WriteMessage(MessageLevel.Error, String.Format("An error occured while initializing the build component '{0}' in the component assembly '{1}'. The error message and stack trace follows: {2}", typeName, assemblyName, e.InnerException.ToString()));
+ } catch (InvalidCastException) {
+ WriteMessage(MessageLevel.Error, String.Format("The type '{0}' in the component assembly '{1}' is not a build component.", typeName, assemblyName));
+ }
+
+ if (component == null) {
+ WriteMessage(MessageLevel.Error, String.Format("The type '{0}' was not found in the component assembly '{1}'.", typeName, assemblyName));
+ }
+
+ return (component);
+
+
+ }
+
+ public BuildComponent[] LoadComponents (XPathNavigator configuration) {
+
+ XPathNodeIterator componentNodes = configuration.Select("component");
+
+ List<BuildComponent> components = new List<BuildComponent>();
+
+ foreach (XPathNavigator componentNode in componentNodes) {
+ components.Add(LoadComponent(componentNode));
+ }
+
+ return(components.ToArray());
+
+ }
+
+ // routines to add and remove components from the
+
+ public void AddComponents (XPathNavigator configuration) {
+ BuildComponent[] componentsToAdd = LoadComponents(configuration);
+ foreach (BuildComponent componentToAdd in componentsToAdd) {
+ components.Add(componentToAdd);
+ }
+ }
+
+ public void ClearComponents () {
+ components.Clear();
+ }
+ private void WriteMessage(MessageLevel level, string message)
+ {
+ handler(this.GetType(), level, message);
+ }
+
+ // the default message handler
+
+ public static MessageHandler ConsoleMessageHandler {
+ get {
+ return (new MessageHandler(WriteComponentMessageToConsole));
+ }
+ }
+
+ private static void WriteComponentMessageToConsole(Type type, MessageLevel level, string message)
+ {
+ string text = String.Format("{0}: {1}", type.Name, message);
+ switch (level)
+ {
+ case MessageLevel.Info:
+ ConsoleApplication.WriteMessage(LogLevel.Info, text);
+ break;
+ case MessageLevel.Warn:
+ ConsoleApplication.WriteMessage(LogLevel.Warn, text);
+ break;
+ case MessageLevel.Error:
+ ConsoleApplication.WriteMessage(LogLevel.Error, text);
+ Environment.Exit(1);
+ break;
+ }
+ }
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildAssemblerLibrary.csproj b/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildAssemblerLibrary.csproj
new file mode 100644
index 0000000..c7acabd
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildAssemblerLibrary.csproj
@@ -0,0 +1,94 @@
+<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>{399E78F8-4954-409E-991A-37DA9D0579CC}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>BuildAssemblerLibrary</RootNamespace>
+ <AssemblyName>BuildAssemblerLibrary</AssemblyName>
+ <SccProjectName>
+ </SccProjectName>
+ <SccLocalPath>
+ </SccLocalPath>
+ <SccAuxPath>
+ </SccAuxPath>
+ <SccProvider>
+ </SccProvider>
+ <SignAssembly>false</SignAssembly>
+ <AssemblyOriginatorKeyFile>../../../key.snk</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>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ </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>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'WebDocsDebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\WebDocsDebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Sandcastle|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Sandcastle\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BuildAssembler.cs" />
+ <Compile Include="BuildComponent.cs" />
+ <Compile Include="BuildComponentUtilities.cs" />
+ <Compile Include="BuildContext.cs" />
+ <Compile Include="GlobalSuppressions.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <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/BuildAssemblerLibrary/BuildComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildComponent.cs
new file mode 100644
index 0000000..04a68ea
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildComponent.cs
@@ -0,0 +1,82 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Reflection;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ public abstract class BuildComponent : IDisposable {
+
+ protected BuildComponent (BuildAssembler assembler, XPathNavigator configuration) {
+ this.assembler = assembler;
+ WriteMessage(MessageLevel.Info, "Instantiating component.");
+ }
+
+ public abstract void Apply (XmlDocument document, string key);
+
+ public virtual void Apply (XmlDocument document) {
+ Apply(document, null);
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose (bool disposing) {
+ }
+
+ // shared data
+
+ private BuildAssembler assembler;
+
+ public BuildAssembler BuildAssembler {
+ get {
+ return(assembler);
+ }
+ }
+
+ //private MessageHandler handler;
+
+ private static Dictionary<string,object> data = new Dictionary<string,object>();
+
+ protected static Dictionary<string,object> Data {
+ get {
+ return(data);
+ }
+ }
+
+ // component messaging facility
+
+ protected void OnComponentEvent (EventArgs e) {
+ assembler.OnComponentEvent(this.GetType(), e);
+ }
+
+ protected void WriteMessage (MessageLevel level, string message) {
+ if (level == MessageLevel.Ignore) return;
+ MessageHandler handler = assembler.MessageHandler;
+ if (handler != null) handler(this.GetType(), level, message);
+ }
+
+ }
+
+ public enum MessageLevel {
+ Ignore, // don't show at all
+ Info, // informational message
+ Warn, // a minor problem occured
+ Error // a major problem occured
+ }
+
+
+ public delegate void MessageHandler (Type component, MessageLevel level, string message);
+
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildComponentUtilities.cs b/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildComponentUtilities.cs
new file mode 100644
index 0000000..0ab709a
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildComponentUtilities.cs
@@ -0,0 +1,146 @@
+// 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.
+
+using System;
+using System.Text;
+using System.Xml;
+using System.Xml.Xsl;
+using System.Xml.XPath;
+using System.Diagnostics;
+using System.Collections.Generic;
+
+namespace Microsoft.Ddue.Tools {
+
+ public static class BuildComponentUtilities {
+
+ // get the message strings from an exception
+
+ public static string GetExceptionMessage (Exception e) {
+ if (e == null) throw new ArgumentNullException("e");
+
+ string message = e.Message;
+
+ XmlException xmlE = e as XmlException;
+ if (xmlE != null) {
+ message = String.Format("{0} (LineNumber: {1}; LinePosition: {2}; SourceUri: '{3}')", message, xmlE.LineNumber, xmlE.LinePosition, xmlE.SourceUri);
+ }
+
+ XsltException xslE = e as XsltException;
+ if (xslE != null) {
+ message = String.Format("{0} (LineNumber: {1}; LinePosition: {2}; SourceUri: '{3}')", message, xslE.LineNumber, xslE.LinePosition, xslE.SourceUri);
+ }
+
+ if (e.InnerException != null) message = String.Format("{0} {1}", message, GetExceptionMessage(e.InnerException));
+
+ return (message);
+ }
+
+ // get InnerXml without changing the spacing
+
+ public static string GetInnerXml (XPathNavigator node) {
+
+ // check for null argument, and clone so we don't change input
+ if (node == null) throw new ArgumentNullException("node");
+ XPathNavigator current = node.Clone();
+
+ // create appropriate settings for the output writer
+ XmlWriterSettings settings = new XmlWriterSettings();
+ settings.ConformanceLevel = ConformanceLevel.Fragment;
+ settings.OmitXmlDeclaration = true;
+
+ // construct a writer for our output
+ StringBuilder builder = new StringBuilder();
+ XmlWriter writer = XmlWriter.Create(builder, settings);
+
+ // write the output
+ bool writing = current.MoveToFirstChild();
+ while (writing) {
+ current.WriteSubtree(writer);
+ writing = current.MoveToNext();
+ }
+
+ // finish up and return the result
+ writer.Close();
+ return(builder.ToString());
+
+ }
+
+ // get an array of nodes matching an XPath expression
+
+ public static XPathNavigator[] ConvertNodeIteratorToArray (XPathNodeIterator iterator) {
+ XPathNavigator[] result = new XPathNavigator[iterator.Count];
+ for (int i = 0; i < result.Length; i++) {
+ iterator.MoveNext();
+ result[i] = iterator.Current.Clone();
+ // clone is required or all entries will equal Current!
+ }
+ return(result);
+ }
+
+
+ /// <summary>
+ /// Returns the string result from evaluating an xpath expression against the given document and context.
+ /// </summary>
+ public static string EvalXPathExpr(IXPathNavigable doc, XPathExpression xpe, CustomContext c) {
+ XPathExpression t = xpe.Clone();
+ t.SetContext(c);
+ return doc.CreateNavigator().Evaluate(t).ToString();
+ }
+
+
+ /// <summary>
+ /// Returns the string result from evaluating an xpath expression against the given document and
+ /// context created from key/value pairs.
+ /// </summary>
+ /// <example>
+ /// string result = BuildComponentUtilities.EvalXPathExpr(doc, "concat($key, '.htm')", "key", "file");
+ /// </example>
+ public static string EvalXPathExpr(IXPathNavigable doc, XPathExpression xpe, params string[] keyValuePairs) {
+ Debug.Assert(keyValuePairs.Length % 2 == 0);
+ CustomContext cc = new CustomContext();
+ for (int i = 0; i < keyValuePairs.Length; i += 2)
+ cc[keyValuePairs[i]] = keyValuePairs[i + 1];
+ return EvalXPathExpr(doc, xpe, cc);
+ }
+
+ /// <summary>
+ /// Returns the path argument adjusted to be relative to the base path. Absolute path names will
+ /// be returned unchanged.
+ /// </summary>
+ /// <example>
+ /// path: "xxx/aaa/target.html"
+ /// basePath: "xxx/bbb/source.html"
+ /// result: "../aaa/target.html"
+ /// </example>
+ public static string GetRelativePath(string path, string basePath) {
+ // ignore absolute path names and an empty basePath
+ if (!string.IsNullOrEmpty(path) && path[0] != '/' && !string.IsNullOrEmpty(basePath)) {
+
+ List<string> pathParts = new List<string>(path.Split('/'));
+ List<string> basePathParts = new List<string>(basePath.Split('/'));
+
+ // remove the base path file name
+ if (basePathParts.Count > 0)
+ basePathParts.RemoveAt(basePathParts.Count - 1);
+
+ // strip common base path bits
+ while (pathParts.Count > 0 && basePathParts.Count > 0 &&
+ string.Equals(pathParts[0], basePathParts[0], StringComparison.CurrentCultureIgnoreCase)) {
+ pathParts.RemoveAt(0);
+ basePathParts.RemoveAt(0);
+ }
+
+ // move up one level for each remaining base path part
+ foreach (string s in basePathParts)
+ pathParts.Insert(0, "..");
+
+ path = string.Join("/", pathParts.ToArray());
+ }
+
+ return path;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildContext.cs b/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildContext.cs
new file mode 100644
index 0000000..8a21675
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/BuildContext.cs
@@ -0,0 +1,176 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class BuildContext {
+
+ private CustomContext context = new CustomContext();
+
+ // Namespace control
+
+ public void AddNamespace (string prefix, string uri) {
+ context.AddNamespace(prefix, uri);
+ }
+
+ public string LookupNamespace (string prefix) {
+ return( context.LookupNamespace(prefix) );
+ }
+
+ public bool RemoveNamespace (string prefix) {
+ string uri = LookupNamespace(prefix);
+ if (uri == null) {
+ return(false);
+ } else {
+ context.RemoveNamespace(prefix, uri);
+ return(true);
+ }
+ }
+
+ public void ClearNamespaces () {
+ }
+
+ // Variable control
+
+ public void AddVariable (string name, string value) {
+ context[name] = value;
+ }
+
+ public string LookupVariable (string name) {
+ return( context[name] );
+ }
+
+ public bool RemoveVariable (string name) {
+ return( context.ClearVariable(name) );
+ }
+
+ public void ClearVariables () {
+ context.ClearVariables();
+ }
+
+ public string this [string name] {
+ get {
+ return(context[name]);
+ }
+ set {
+ context[name] = value;
+ }
+ }
+
+ // Function control
+
+ // The context for use in XPath queries
+
+ public XsltContext XsltContext {
+ get {
+ return(context);
+ }
+ }
+
+ // Load data from config
+
+ public void Load (XPathNavigator configuration) {
+ XPathNodeIterator namespaceNodes = configuration.Select("namespace");
+ foreach (XPathNavigator namespaceNode in namespaceNodes) {
+ string prefixValue = namespaceNode.GetAttribute("prefix", String.Empty);
+ string uriValue = namespaceNode.GetAttribute("uri", String.Empty);
+ AddNamespace(prefixValue, uriValue);
+ }
+ }
+
+ }
+
+ public class CustomContext : XsltContext {
+
+ public CustomContext() : base() {}
+
+ // variable control
+
+ private Dictionary<string, IXsltContextVariable> variables = new Dictionary<string,IXsltContextVariable>();
+
+ public string this [string variable] {
+ get {
+ return(variables[variable].Evaluate(this).ToString());
+ }
+ set {
+ variables[variable] = new CustomVariable(value);
+ }
+ }
+
+ public bool ClearVariable (string name) {
+ return( variables.Remove(name) );
+ }
+
+ public void ClearVariables () {
+ variables.Clear();
+ }
+
+ // Implementation of XsltContext methods
+
+ public override IXsltContextVariable ResolveVariable (string prefix, string name) {
+ return( variables[name] );
+ }
+
+ public override IXsltContextFunction ResolveFunction (string prefix, string name, XPathResultType[] argumentTypes) {
+ throw new NotImplementedException();
+ }
+
+ public override int CompareDocument (string baseUri, string nextBaseUri) {
+ return(0);
+ }
+
+ public override bool Whitespace {
+ get {
+ return(true);
+ }
+ }
+
+ public override bool PreserveWhitespace (XPathNavigator node) {
+ return(true);
+ }
+
+ }
+
+
+ internal struct CustomVariable : IXsltContextVariable {
+
+ public CustomVariable (string value) {
+ this.value = value;
+ }
+
+ private string value;
+
+ public bool IsLocal {
+ get {
+ return(false);
+ }
+ }
+
+ public bool IsParam {
+ get {
+ return(false);
+ }
+ }
+
+ public XPathResultType VariableType {
+ get {
+ return(XPathResultType.String);
+ }
+ }
+
+ public Object Evaluate (XsltContext context) {
+ return(value);
+ }
+
+ }
+
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/GlobalSuppressions.cs b/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/GlobalSuppressions.cs
new file mode 100644
index 0000000..710997a
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/GlobalSuppressions.cs
@@ -0,0 +1,45 @@
+// 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.
+
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+//
+// To add a suppression to this file, right-click the message in the
+// Error List, point to "Suppress Message(s)", and click
+// "In Project Suppression File".
+// You do not need to add suppressions to this file manually.
+
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ddue", Scope = "namespace", Target = "Microsoft.Ddue.Tools")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildAssembler.#Apply(System.Collections.Generic.IEnumerable`1<System.String>)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildAssembler.#BuildComponents")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Filename", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildAssembler.#GetFileManifestBuildContextEnumerator(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildAssembler.#LoadComponent(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildAssembler.#LoadComponent(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildAssembler.#LoadComponent(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "components", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildAssembler.#LoadComponents(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildAssembler.#WriteComponentMessageToConsole(System.Type,Microsoft.Ddue.Tools.MessageLevel,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "configuration", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes", MessageId = "System.Xml.XmlNode", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildComponent.#Apply(System.Xml.XmlDocument)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes", MessageId = "System.Xml.XmlNode", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "e", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildComponentUtilities.#GetExceptionMessage(System.Exception)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildComponentUtilities.#GetExceptionMessage(System.Exception)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object[])", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildComponentUtilities.#GetExceptionMessage(System.Exception)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "s", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildComponentUtilities.#GetRelativePath(System.String,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildContext.#AddNamespace(System.String,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildContext.#ClearNamespaces()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1010:CollectionsShouldImplementGenericInterface", Scope = "type", Target = "Microsoft.Ddue.Tools.CustomContext")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Scope = "type", Target = "Microsoft.Ddue.Tools.CustomContext")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "1#", Scope = "member", Target = "Microsoft.Ddue.Tools.CustomContext.#CompareDocument(System.String,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "2#", Scope = "member", Target = "Microsoft.Ddue.Tools.CustomContext.#ResolveFunction(System.String,System.String,System.Xml.XPath.XPathResultType[])")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Eval", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildComponentUtilities.#EvalXPathExpr(System.Xml.XPath.IXPathNavigable,System.Xml.XPath.XPathExpression,Microsoft.Ddue.Tools.CustomContext)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Expr", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildComponentUtilities.#EvalXPathExpr(System.Xml.XPath.IXPathNavigable,System.Xml.XPath.XPathExpression,Microsoft.Ddue.Tools.CustomContext)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "c", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildComponentUtilities.#EvalXPathExpr(System.Xml.XPath.IXPathNavigable,System.Xml.XPath.XPathExpression,Microsoft.Ddue.Tools.CustomContext)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "xpe", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildComponentUtilities.#EvalXPathExpr(System.Xml.XPath.IXPathNavigable,System.Xml.XPath.XPathExpression,Microsoft.Ddue.Tools.CustomContext)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Eval", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildComponentUtilities.#EvalXPathExpr(System.Xml.XPath.IXPathNavigable,System.Xml.XPath.XPathExpression,System.String[])")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Expr", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildComponentUtilities.#EvalXPathExpr(System.Xml.XPath.IXPathNavigable,System.Xml.XPath.XPathExpression,System.String[])")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "xpe", Scope = "member", Target = "Microsoft.Ddue.Tools.BuildComponentUtilities.#EvalXPathExpr(System.Xml.XPath.IXPathNavigable,System.Xml.XPath.XPathExpression,System.String[])")]
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/Properties/AssemblyInfo.cs b/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e87d8d5
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildAssemblerLibrary/Properties/AssemblyInfo.cs
@@ -0,0 +1,43 @@
+// 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.
+
+using System;
+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("BuildAssemblerLibrary")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("BuildAssemblerLibrary")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2006")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: CLSCompliant(true)]
+
+// 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("8dc79b50-d46d-4e02-b2e6-43abc681e189")]
+
+// 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.5.10626.00")]
+[assembly: AssemblyFileVersion("2.5.10626.00")]
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/BuildComponents.csproj b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/BuildComponents.csproj
new file mode 100644
index 0000000..9e3932f
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/BuildComponents.csproj
@@ -0,0 +1,155 @@
+<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>{30773718-BC7C-4FCC-A9C2-7EE61DF4EC41}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>BuildComponents</RootNamespace>
+ <AssemblyName>BuildComponents</AssemblyName>
+ <SccProjectName>
+ </SccProjectName>
+ <SccLocalPath>
+ </SccLocalPath>
+ <SccAuxPath>
+ </SccAuxPath>
+ <SccProvider>
+ </SccProvider>
+ <SignAssembly>false</SignAssembly>
+ <AssemblyOriginatorKeyFile>../../../key.snk</AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </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>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'WebDocsDebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\WebDocsDebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Sandcastle|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Sandcastle\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Web" />
+ <Reference Include="System.Web.Services" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="GlobalSuppressions.cs" />
+ <Compile Include="HxfGeneratorComponent.cs" />
+ <Compile Include="IntellisenseComponent2.cs" />
+ <Compile Include="MsdnResolver.cs" />
+ <Compile Include="References.cs" />
+ <Compile Include="ResolveReferenceLinksComponent2.cs" />
+ <Compile Include="CloneComponent.cs" />
+ <Compile Include="CodeReference.cs" />
+ <Compile Include="CopyFromFileComponent.cs" />
+ <Compile Include="CopyFromFiles.cs" />
+ <Compile Include="CopyFromIndexComponent.cs" />
+ <Compile Include="DisplayComponent.cs" />
+ <Compile Include="ExampleComponent.cs" />
+ <Compile Include="ForEachComponent.cs" />
+ <Compile Include="IfThenComponent.cs" />
+ <Compile Include="IndexedFileCache.cs" />
+ <Compile Include="IntellisenseComponent.cs" />
+ <Compile Include="LiveExampleComponent.cs" />
+ <Compile Include="MsdnService.cs" />
+ <Compile Include="PlatformsComponent.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ResolveArtLinksComponent.cs" />
+ <Compile Include="ResolveConceptualLinksComponent.cs" />
+ <Compile Include="SaveComponent.cs" />
+ <Compile Include="SharedContentComponent.cs" />
+ <Compile Include="SnippetComponent.cs" />
+ <Compile Include="SwitchComponent.cs" />
+ <Compile Include="SyntaxComponent.cs" />
+ <Compile Include="TargetCollection.cs" />
+ <Compile Include="Targets.cs" />
+ <Compile Include="TaskGrabberComponent.cs" />
+ <Compile Include="TransformComponent.cs" />
+ <Compile Include="ValidateComponent.cs" />
+ <Compile Include="WdxResolveConceptualLinksComponent.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\BuildAssemblerLibrary\BuildAssemblerLibrary.csproj">
+ <Project>{399E78F8-4954-409E-991A-37DA9D0579CC}</Project>
+ <Name>BuildAssemblerLibrary</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ </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/BuildComponents/CloneComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/CloneComponent.cs
new file mode 100644
index 0000000..d22ccf5
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/CloneComponent.cs
@@ -0,0 +1,44 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+using System.Reflection;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class CloneComponent : BuildComponent {
+
+ private List<IEnumerable<BuildComponent>> branches = new List<IEnumerable<BuildComponent>>();
+
+ public CloneComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ XPathNodeIterator branch_nodes = configuration.Select("branch");
+ foreach (XPathNavigator branch_node in branch_nodes) {
+ BuildComponent[] branch = BuildAssembler.LoadComponents(branch_node);
+ branches.Add(branch);
+ }
+
+ }
+
+ public override void Apply (XmlDocument document, string key) {
+
+ foreach (IEnumerable<BuildComponent> branch in branches) {
+ XmlDocument subdocument = document.Clone() as XmlDocument;
+ foreach(BuildComponent component in branch) {
+ component.Apply(subdocument, key);
+ }
+ }
+
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/CodeReference.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/CodeReference.cs
new file mode 100644
index 0000000..c0cbd11
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/CodeReference.cs
@@ -0,0 +1,117 @@
+// 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.
+
+using System;
+using System.Text.RegularExpressions;
+using System.Collections.Generic;
+
+
+namespace Microsoft.Ddue.Tools {
+
+ public enum CodeReferenceType {
+ Invalid, // not initialized, invalid reference string
+ Snippet, // MSDN style snippet for all build targets
+ Msdn, // MSDN style snippet for MSDN build only
+ Run, // runnable code sample with pop-up source browser for WebDocs build
+ View // code sample shown in pop-up source browser for WebDocs build
+ }
+
+ /// <summary>
+ /// The CodeReference class encapsulates DDUE code reference elements and provides easy access
+ /// to individual code reference parts, such as the type, name, title, etc..
+ /// </summary>
+ /// <remarks>
+ /// Examples of valid code reference strings include:
+ /// - SampleName#SnippetNumber
+ /// - SampleName#SnippetNumber1,SnippetNumber2,SnippetNumber3
+ /// - msdn:SampleName#SnippetNumber
+ /// - run:SampleName
+ /// - run:SampleName;title text
+ /// - run:SampleName#startPage.aspx
+ /// - run:SampleName/path/to/startPage.aspx
+ /// - run:SampleName#startPage.aspx;title text
+ /// - run:SampleName/path/to/startPage.aspx;title text
+ /// - view:SampleName
+ /// - view:SampleName#defaultFile
+ /// - view:SampleName/path/to/defaultFile
+ /// - view:SampleName#defaultFile;title text
+ /// - view:SampleName/path/to/defaultFile;title text
+ /// </remarks>
+ public class CodeReference {
+
+ string _ddueCodeReference;
+ public string DdueCodeReference {
+ get { return _ddueCodeReference; }
+ }
+
+ CodeReferenceType _type;
+ public CodeReferenceType Type {
+ get { return _type; }
+ }
+
+ string _exampleName;
+ public string ExampleName {
+ get { return _exampleName; }
+ }
+
+ string _examplePath;
+ public string ExamplePath {
+ get { return _examplePath; }
+ }
+
+ string _snippetId;
+ public string SnippetId {
+ get { return _snippetId; }
+ }
+
+ string _title;
+ public string Title {
+ get { return _title; }
+ }
+
+ public CodeReference(string ddueCodeReference) {
+ _ddueCodeReference = ddueCodeReference;
+ Parse();
+ }
+
+ static Regex codeReferenceRx = new Regex(
+ @"^\s*(" +
+ @"((?<type>msdn|run|view):)?" +
+ @"(?<examplePath>(" +
+ @"(?<exampleName>[\w\.,\-]+)" +
+ @"((#(?<snippetId>[\w,]+))|(([/\\#,\.\w\-]+)?))" +
+ @"))" +
+ @"(;(?<title>.*))?" +
+ @")\s*$",
+ RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase | RegexOptions.Compiled);
+
+ void Parse() {
+ Match m = codeReferenceRx.Match(DdueCodeReference);
+ if (m.Success) {
+ _exampleName = m.Groups["exampleName"].Value;
+ _snippetId = m.Groups["snippetId"].Value;
+ _examplePath = m.Groups["examplePath"].Value;
+ _title = m.Groups["title"].Value;
+ // The default value of _type is CodeReferenceType.Invalid, if it isn't set in the following
+ // block.
+ if (m.Groups["type"].Length > 0) {
+ try {
+ _type = (CodeReferenceType)Enum.Parse(typeof(CodeReferenceType), m.Groups["type"].Value, true);
+ }
+ catch (ArgumentException) {
+ // _type = CodeReferenceType.Invalid
+ }
+ }
+ else if (m.Groups["exampleName"].Length > 0 && m.Groups["snippetId"].Length > 0) {
+ _type = CodeReferenceType.Snippet;
+ }
+ }
+ }
+
+ public override string ToString() {
+ return DdueCodeReference;
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ComputeHashComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ComputeHashComponent.cs
new file mode 100644
index 0000000..37755ab
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ComputeHashComponent.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Security.Cryptography;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+
+
+namespace Microsoft.Ddue.Tools {
+
+ internal class HashComputation {
+
+ public HashComputation (string input, string output) {
+ Input = XPathExpression.Compile(input);
+ Output = XPathExpression.Compile(output);
+ }
+
+ public XPathExpression Input;
+ public XPathExpression Output;
+
+ }
+
+ public class ComputeHashComponent : BuildComponent {
+
+ public ComputeHashComponent (XPathNavigator configuration) : base(configuration) {
+
+ if (configuration == null) throw new ArgumentNullException("configuraton");
+
+ XPathNodeIterator hash_nodes = configuration.Select("hash");
+ foreach (XPathNavigator hash_node in hash_nodes) {
+ string input_xpath = hash_node.GetAttribute("input", String.Empty);
+ string output_xpath = hash_node.GetAttribute("output", String.Empty);
+ computations.Add( new HashComputation(input_xpath, output_xpath) );
+ }
+
+ }
+
+ // A list of the hash computations to do
+
+ private List<HashComputation> computations = new List<HashComputation>();
+
+ // Logic to compute a unique hash of a comment id string
+
+ private static Guid ComputeHash (string key) {
+ byte[] input = Encoding.UTF8.GetBytes(key);
+ byte[] output = md5.ComputeHash(input);
+ return( new Guid(output) );
+ }
+
+ private static HashAlgorithm md5 = new MD5CryptoServiceProvider();
+
+ // The actual action of the component
+
+ public override void Apply (XmlDocument document, string key) {
+
+ Guid id = ComputeHash(key);
+
+ foreach (HashComputation computation in computations) {
+ XPathNavigator output = document.CreateNavigator().SelectSingleNode(computation.Output);
+ if (output == null) continue;
+ output.SetValue(id.ToString());
+ }
+
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/CopyFromFileComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/CopyFromFileComponent.cs
new file mode 100644
index 0000000..2c4eedb
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/CopyFromFileComponent.cs
@@ -0,0 +1,146 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class CopyFromFileComponent : BuildComponent {
+
+ public CopyFromFileComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ if (configuration == null) throw new ArgumentNullException("configuration");
+
+ string data_name = null;
+
+ // get information about the data file
+ XPathNodeIterator data_nodes = configuration.Select("data");
+ foreach (XPathNavigator data_node in data_nodes) {
+ string data_file = data_node.GetAttribute("file", String.Empty);
+ if (String.IsNullOrEmpty(data_file)) WriteMessage(MessageLevel.Error, "Data elements must have a file attribute specifying a file from which to load data.");
+ data_file = Environment.ExpandEnvironmentVariables(data_file);
+
+ data_name = data_node.GetAttribute("name", String.Empty);
+ if (String.IsNullOrEmpty(data_name)) data_name = Guid.NewGuid().ToString();
+
+ // load a schema, if one is specified
+ string schema_file = data_node.GetAttribute("schema", String.Empty);
+ XmlReaderSettings settings = new XmlReaderSettings();
+ if (!String.IsNullOrEmpty(schema_file)) {
+ settings.Schemas.Add(null, schema_file);
+ }
+
+ // load the document
+ WriteMessage(MessageLevel.Info, String.Format("Loading data file '{0}'.", data_file) );
+ using (XmlReader reader = XmlReader.Create(data_file, settings)) {
+ XPathDocument data_document = new XPathDocument(reader);
+ Data.Add(data_name, data_document);
+ }
+ }
+
+
+ // get the source and target expressions for each copy command
+ XPathNodeIterator copy_nodes = configuration.Select("copy");
+ foreach (XPathNavigator copy_node in copy_nodes) {
+ string source_name = copy_node.GetAttribute("name", String.Empty);
+ if (String.IsNullOrEmpty(source_name)) source_name = data_name;
+
+ XPathDocument source_document = (XPathDocument) Data[source_name];
+
+ string source_xpath = copy_node.GetAttribute("source", String.Empty);
+ if (String.IsNullOrEmpty(source_xpath)) throw new ConfigurationErrorsException("When instantiating a CopyFromFile component, you must specify a source xpath format using the source attribute.");
+ string target_xpath = copy_node.GetAttribute("target", String.Empty);
+ if (String.IsNullOrEmpty(target_xpath)) throw new ConfigurationErrorsException("When instantiating a CopyFromFile component, you must specify a target xpath format using the target attribute.");
+ copy_commands.Add( new CopyFromFileCommand(source_document, source_xpath, target_xpath) );
+ }
+
+ }
+
+ // private XPathDocument data_document;
+
+ private List<CopyFromFileCommand> copy_commands = new List<CopyFromFileCommand>();
+
+ private CustomContext context = new CustomContext();
+
+ // the work of the component
+
+ public override void Apply (XmlDocument document, string key) {
+
+ // set the key in the XPath context
+ context["key"] = key;
+
+ // iterate over the copy commands
+ foreach (CopyFromFileCommand copy_command in copy_commands) {
+
+ // extract the target node
+ XPathExpression target_xpath = copy_command.Target.Clone();
+ target_xpath.SetContext(context);
+ XPathNavigator target = document.CreateNavigator().SelectSingleNode(target_xpath);
+
+ // warn if target not found?
+ if (target == null) {
+ continue;
+ }
+
+ // extract the source nodes
+ XPathExpression source_xpath = copy_command.Source.Clone();
+ source_xpath.SetContext(context);
+ XPathNodeIterator sources = copy_command.SourceDocument.CreateNavigator().Select(source_xpath);
+
+ // warn if source not found?
+
+ // append the source nodes to the target node
+ foreach (XPathNavigator source in sources) {
+ target.AppendChild(source);
+ }
+
+ }
+
+ }
+
+ }
+
+
+ // a representation of a copying operation
+
+ internal class CopyFromFileCommand {
+
+ public CopyFromFileCommand (XPathDocument source_document, string source_xpath, string target_xpath) {
+ this.source_document = source_document;
+ source = XPathExpression.Compile(source_xpath);
+ target = XPathExpression.Compile(target_xpath);
+ }
+
+ private XPathDocument source_document;
+
+ private XPathExpression source;
+
+ private XPathExpression target;
+
+ public XPathDocument SourceDocument {
+ get {
+ return(source_document);
+ }
+ }
+
+ public XPathExpression Source {
+ get {
+ return(source);
+ }
+ }
+
+ public XPathExpression Target {
+ get {
+ return(target);
+ }
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/CopyFromFiles.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/CopyFromFiles.cs
new file mode 100644
index 0000000..b05903d
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/CopyFromFiles.cs
@@ -0,0 +1,95 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class CopyFromFilesComponent : BuildComponent {
+
+ public CopyFromFilesComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+ XPathNodeIterator copy_nodes = configuration.Select("copy");
+ foreach (XPathNavigator copy_node in copy_nodes) {
+
+ string root_value = copy_node.GetAttribute("base", String.Empty);
+ if (String.IsNullOrEmpty(root_value)) root_value = Environment.CurrentDirectory;
+ root_value = Environment.ExpandEnvironmentVariables(root_value);
+ if (!Directory.Exists(root_value)) WriteMessage(MessageLevel.Error, String.Format("The base directory '{0}' does not exist.", root_value));
+
+ string file_value = copy_node.GetAttribute("file", String.Empty);
+ if (String.IsNullOrEmpty(file_value)) WriteMessage(MessageLevel.Error, "Each copy element must have a file attribute specifying the file to copy from.");
+
+ string source_value = copy_node.GetAttribute("source", String.Empty);
+ string target_value = copy_node.GetAttribute("target", String.Empty);
+
+ CopyFromFilesCommand copy_command = new CopyFromFilesCommand(root_value, file_value, source_value, target_value);
+ copy_commands.Add(copy_command);
+ }
+
+ WriteMessage(MessageLevel.Info, String.Format("Loaded {0} copy commands.", copy_commands.Count));
+ }
+
+ List<CopyFromFilesCommand> copy_commands = new List<CopyFromFilesCommand>();
+
+ private CustomContext context = new CustomContext();
+
+ public override void Apply (XmlDocument document, string key) {
+ context["key"] = key;
+ foreach (CopyFromFilesCommand copy_command in copy_commands) {
+ copy_command.Apply(document, context);
+ }
+ }
+
+ }
+
+ internal class CopyFromFilesCommand {
+
+ public CopyFromFilesCommand (string root, string file, string source, string target) {
+ root_directory = root;
+ file_expression = XPathExpression.Compile(file);
+ source_expression = XPathExpression.Compile(source);
+ target_expression = XPathExpression.Compile(target);
+ }
+
+ private string root_directory;
+
+ private XPathExpression file_expression;
+
+ private XPathExpression source_expression;
+
+ private XPathExpression target_expression;
+
+ public void Apply (XmlDocument targetDocument, IXmlNamespaceResolver context) {
+
+ XPathExpression local_file_expression = file_expression.Clone();
+ local_file_expression.SetContext(context);
+
+ XPathExpression local_source_expression = source_expression.Clone();
+ local_source_expression.SetContext(context);
+
+ XPathExpression local_target_expression = target_expression.Clone();
+ local_target_expression.SetContext(context);
+
+ string file_name = (string) targetDocument.CreateNavigator().Evaluate(local_file_expression);
+ string file_path = Path.Combine(root_directory, file_name);
+
+ if (!File.Exists(file_path)) return;
+ XPathDocument sourceDocument = new XPathDocument(file_path);
+
+ XPathNavigator target_node = targetDocument.CreateNavigator().SelectSingleNode(local_target_expression);
+ if (target_node == null) return;
+
+ XPathNodeIterator source_nodes = sourceDocument.CreateNavigator().Select(local_source_expression);
+ foreach (XPathNavigator source_node in source_nodes) {
+ target_node.AppendChild(source_node);
+ }
+
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/CopyFromIndexComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/CopyFromIndexComponent.cs
new file mode 100644
index 0000000..bf19dc8
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/CopyFromIndexComponent.cs
@@ -0,0 +1,677 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Xml;
+using System.Xml.XPath;
+using System.Reflection;
+using System.Xml.Xsl; /* for custom context stuff */
+
+namespace Microsoft.Ddue.Tools {
+
+ public class CopyFromIndexComponent : BuildComponent {
+
+ // XPath search patterns
+
+ // List of copy components
+ private List<CopyComponent> components = new List<CopyComponent>();
+
+ // what to copy
+ private List<CopyCommand> copy_commands = new List<CopyCommand>();
+
+ // a context in which to evaluate XPath expressions
+ private CustomContext context = new CustomContext();
+
+ public CopyFromIndexComponent(BuildAssembler assembler, XPathNavigator configuration)
+ : base(assembler, configuration) {
+
+ // set up the context
+ XPathNodeIterator context_nodes = configuration.Select("context");
+ foreach (XPathNavigator context_node in context_nodes) {
+ string prefix = context_node.GetAttribute("prefix", String.Empty);
+ string name = context_node.GetAttribute("name", String.Empty);
+ context.AddNamespace(prefix, name);
+ }
+
+ // set up the indices
+ XPathNodeIterator index_nodes = configuration.Select("index");
+ foreach (XPathNavigator index_node in index_nodes) {
+
+ // get the name of the index
+ string name = index_node.GetAttribute("name", String.Empty);
+ if (String.IsNullOrEmpty(name)) throw new ConfigurationErrorsException("Each index must have a unique name.");
+
+ // get the xpath for value nodes
+ string value_xpath = index_node.GetAttribute("value", String.Empty);
+ if (String.IsNullOrEmpty(value_xpath)) WriteMessage(MessageLevel.Error, "Each index element must have a value attribute containing an XPath that describes index entries.");
+
+ // get the xpath for keys (relative to value nodes)
+ string key_xpath = index_node.GetAttribute("key", String.Empty);
+ if (String.IsNullOrEmpty(key_xpath)) WriteMessage(MessageLevel.Error, "Each index element must have a key attribute containing an XPath (relative to the value XPath) that evaluates to the entry key.");
+
+ // get the cache size
+ int cache = 10;
+ string cache_value = index_node.GetAttribute("cache", String.Empty);
+ if (!String.IsNullOrEmpty(cache_value)) cache = Convert.ToInt32(cache_value);
+
+ // create the index
+ IndexedDocumentCache index = new IndexedDocumentCache(this, key_xpath, value_xpath, context, cache);
+
+ // search the data directories for entries
+ XPathNodeIterator data_nodes = index_node.Select("data");
+ foreach (XPathNavigator data_node in data_nodes) {
+
+ string base_value = data_node.GetAttribute("base", String.Empty);
+ if (!String.IsNullOrEmpty(base_value)) base_value = Environment.ExpandEnvironmentVariables(base_value);
+
+ bool recurse = false;
+ string recurse_value = data_node.GetAttribute("recurse", String.Empty);
+ if (!String.IsNullOrEmpty(recurse_value)) recurse = (bool)Convert.ToBoolean(recurse_value);
+
+ // get the files
+ string files = data_node.GetAttribute("files", String.Empty);
+ if (String.IsNullOrEmpty(files)) WriteMessage(MessageLevel.Error, "Each data element must have a files attribute specifying which files to index.");
+ // if ((files == null) || (files.Length == 0)) throw new ConfigurationErrorsException("When instantiating a CopyFromDirectory component, you must specify a directory path using the files attribute.");
+ files = Environment.ExpandEnvironmentVariables(files);
+
+ WriteMessage(MessageLevel.Info, String.Format("Searching for files that match '{0}'.", files));
+ index.AddDocuments(base_value, files, recurse);
+
+ }
+ WriteMessage(MessageLevel.Info, String.Format("Indexed {0} elements in {1} files.", index.Count, index.DocumentCount));
+
+ Data.Add(name, index);
+
+ }
+
+ // get the copy commands
+ XPathNodeIterator copy_nodes = configuration.Select("copy");
+ foreach (XPathNavigator copy_node in copy_nodes) {
+
+ 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.");
+
+ string key_xpath = copy_node.GetAttribute("key", String.Empty);
+
+ string source_xpath = copy_node.GetAttribute("source", String.Empty);
+ if (String.IsNullOrEmpty(source_xpath)) throw new ConfigurationErrorsException("When instantiating a CopyFromDirectory component, you must specify a source xpath format using the source attribute.");
+
+ string target_xpath = copy_node.GetAttribute("target", String.Empty);
+ if (String.IsNullOrEmpty(target_xpath)) throw new ConfigurationErrorsException("When instantiating a CopyFromDirectory component, you must specify a target xpath format using the target attribute.");
+
+ string attribute_value = copy_node.GetAttribute("attribute", String.Empty);
+
+ string ignoreCase_value = copy_node.GetAttribute("ignoreCase", String.Empty);
+
+ string missingEntryValue = copy_node.GetAttribute("missing-entry", String.Empty);
+ string missingSourceValue = copy_node.GetAttribute("missing-source", String.Empty);
+ string missingTargetValue = copy_node.GetAttribute("missing-target", String.Empty);
+
+ IndexedDocumentCache index = (IndexedDocumentCache)Data[source_name];
+
+ CopyCommand copyCommand = new CopyCommand(index, key_xpath, source_xpath, target_xpath, attribute_value, ignoreCase_value);
+ if (!String.IsNullOrEmpty(missingEntryValue)) {
+ try {
+ copyCommand.MissingEntry = (MessageLevel)Enum.Parse(typeof(MessageLevel), missingEntryValue, true);
+ } catch (ArgumentException) {
+ WriteMessage(MessageLevel.Error, String.Format("'{0}' is not a message level.", missingEntryValue));
+ }
+ }
+ if (!String.IsNullOrEmpty(missingSourceValue)) {
+ try {
+ copyCommand.MissingSource = (MessageLevel)Enum.Parse(typeof(MessageLevel), missingSourceValue, true);
+ } catch (ArgumentException) {
+ WriteMessage(MessageLevel.Error, String.Format("'{0}' is not a message level.", missingSourceValue));
+ }
+ }
+ if (!String.IsNullOrEmpty(missingTargetValue)) {
+ try {
+ copyCommand.MissingTarget = (MessageLevel)Enum.Parse(typeof(MessageLevel), missingTargetValue, true);
+ } catch (ArgumentException) {
+ WriteMessage(MessageLevel.Error, String.Format("'{0}' is not a message level.", missingTargetValue));
+ }
+ }
+
+ copy_commands.Add(copyCommand);
+
+ }
+
+ XPathNodeIterator component_nodes = configuration.Select("components/component");
+ foreach (XPathNavigator component_node in component_nodes) {
+
+ // get the data to load the component
+ string assembly_path = component_node.GetAttribute("assembly", String.Empty);
+ if (String.IsNullOrEmpty(assembly_path)) WriteMessage(MessageLevel.Error, "Each component element must have an assembly attribute.");
+ string type_name = component_node.GetAttribute("type", String.Empty);
+ if (String.IsNullOrEmpty(type_name)) WriteMessage(MessageLevel.Error, "Each component element must have a type attribute.");
+
+ // expand environment variables in the path
+ assembly_path = Environment.ExpandEnvironmentVariables(assembly_path);
+
+ //Console.WriteLine("loading {0} from {1}", type_name, assembly_path);
+ try
+ {
+ Assembly assembly = Assembly.LoadFrom(assembly_path);
+ CopyComponent component = (CopyComponent)assembly.CreateInstance(type_name, false, BindingFlags.Public | BindingFlags.Instance, null, new Object[2] { component_node.Clone(), Data }, null, null);
+
+ if (component == null)
+ {
+ WriteMessage(MessageLevel.Error, String.Format("The type '{0}' does not exist in the assembly '{1}'.", type_name, assembly_path));
+ }
+ else
+ {
+ components.Add(component);
+ }
+
+ }
+ catch (IOException e)
+ {
+ WriteMessage(MessageLevel.Error, String.Format("A file access error occured while attempting to load the build component '{0}'. The error message is: {1}", assembly_path, e.Message));
+ }
+ catch (BadImageFormatException e)
+ {
+ WriteMessage(MessageLevel.Error, String.Format("A syntax generator assembly '{0}' is invalid. The error message is: {1}.", assembly_path, e.Message));
+ }
+ catch (TypeLoadException e)
+ {
+ WriteMessage(MessageLevel.Error, String.Format("The type '{0}' does not exist in the assembly '{1}'. The error message is: {2}", type_name, assembly_path, e.Message));
+ }
+ catch (MissingMethodException e)
+ {
+ WriteMessage(MessageLevel.Error, String.Format("The type '{0}' in the assembly '{1}' does not have an appropriate constructor. The error message is: {2}", type_name, assembly_path, e.Message));
+ }
+ catch (TargetInvocationException e)
+ {
+ WriteMessage(MessageLevel.Error, String.Format("An error occured while attempting to instantiate the type '{0}' in the assembly '{1}'. The error message is: {2}", type_name, assembly_path, e.InnerException.Message));
+ }
+ catch (InvalidCastException)
+ {
+ WriteMessage(MessageLevel.Error, String.Format("The type '{0}' in the assembly '{1}' is not a SyntaxGenerator.", type_name, assembly_path));
+ }
+ }
+
+ WriteMessage(MessageLevel.Info, String.Format("Loaded {0} copy components.", components.Count));
+
+ }
+
+ // the actual work of the component
+
+ public override void Apply(XmlDocument document, string key) {
+
+ // set the key in the XPath context
+ context["key"] = key;
+
+ // perform each copy action
+ foreach (CopyCommand copy_command in copy_commands) {
+
+ // get the source comment
+ XPathExpression key_expression = copy_command.Key.Clone();
+ key_expression.SetContext(context);
+ // Console.WriteLine(key_expression.Expression);
+ string key_value = (string)document.CreateNavigator().Evaluate(key_expression);
+ // Console.WriteLine("got key '{0}'", key_value);
+ XPathNavigator data = copy_command.Index.GetContent(key_value);
+
+ if (data == null && copy_command.IgnoreCase == "true") data = copy_command.Index.GetContent(key_value.ToLower());
+
+ // notify if no entry
+ if (data == null) {
+ WriteMessage(copy_command.MissingEntry, String.Format("No index entry found for key '{0}'.", key_value));
+ continue;
+ }
+
+ // get the target node
+ String target_xpath = copy_command.Target.Clone().ToString();
+ XPathExpression target_expression = XPathExpression.Compile(string.Format(target_xpath, key_value));
+ target_expression.SetContext(context);
+
+ XPathNavigator target = document.CreateNavigator().SelectSingleNode(target_expression);
+
+ // notify if no target found
+ if (target == null) {
+ WriteMessage(copy_command.MissingTarget, String.Format("Target node '{0}' not found.", target_expression.Expression));
+ continue;
+ }
+
+ // get the source nodes
+ XPathExpression source_expression = copy_command.Source.Clone();
+ source_expression.SetContext(context);
+ XPathNodeIterator sources = data.CreateNavigator().Select(source_expression);
+
+ // append the source nodes to the target node
+ int source_count = 0;
+ foreach (XPathNavigator source in sources) {
+ source_count++;
+
+ // If attribute=true, add the source attributes to current target.
+ // Otherwise append source as a child element to target
+ if (copy_command.Attribute == "true" && source.HasAttributes) {
+ string source_name = source.LocalName;
+ XmlWriter attributes = target.CreateAttributes();
+
+ source.MoveToFirstAttribute();
+ string attrFirst = target.GetAttribute(string.Format("{0}_{1}", source_name, source.Name), string.Empty);
+ if (string.IsNullOrEmpty(attrFirst)) attributes.WriteAttributeString(string.Format("{0}_{1}", source_name, source.Name), source.Value);
+
+ while (source.MoveToNextAttribute()) {
+ string attrNext = target.GetAttribute(string.Format("{0}_{1}", source_name, source.Name), string.Empty);
+ if (string.IsNullOrEmpty(attrNext)) attributes.WriteAttributeString(string.Format("{0}_{1}", source_name, source.Name), source.Value);
+ }
+ attributes.Close();
+ }
+ else target.AppendChild(source);
+ }
+
+ // notify if no source found
+ if (source_count == 0) {
+ WriteMessage(copy_command.MissingSource, String.Format("Source node '{0}' not found.", source_expression.Expression));
+ }
+
+ foreach (CopyComponent component in components)
+ {
+ component.Apply(document, key);
+ }
+ }
+ }
+
+ internal void WriteHelperMessage(MessageLevel level, string message) {
+ WriteMessage(level, message);
+ }
+
+ }
+
+ // the storage system
+
+ public class IndexedDocumentCache {
+
+ public IndexedDocumentCache(CopyFromIndexComponent component, string keyXPath, string valueXPath, XmlNamespaceManager context, int cacheSize) {
+
+ if (component == null) throw new ArgumentNullException("component");
+ if (cacheSize < 0) throw new ArgumentOutOfRangeException("cacheSize");
+
+ this.component = component;
+
+ try {
+ keyExpression = XPathExpression.Compile(keyXPath);
+ } catch (XPathException) {
+ component.WriteHelperMessage(MessageLevel.Error, String.Format("The key expression '{0}' is not a valid XPath expression.", keyXPath));
+ }
+ keyExpression.SetContext(context);
+
+ try {
+ valueExpression = XPathExpression.Compile(valueXPath);
+ } catch (XPathException) {
+ component.WriteHelperMessage(MessageLevel.Error, String.Format("The value expression '{0}' is not a valid XPath expression.", valueXPath));
+ }
+ valueExpression.SetContext(context);
+
+ this.cacheSize = cacheSize;
+
+ // set up the cache
+ cache = new Dictionary<string, IndexedDocument>(cacheSize);
+ queue = new Queue<string>(cacheSize);
+ }
+
+ // index component to which the cache belongs
+ private CopyFromIndexComponent component;
+
+ public CopyFromIndexComponent Component {
+ get {
+ return (component);
+ }
+ }
+
+ // search pattern for index values
+ private XPathExpression valueExpression;
+
+ public XPathExpression ValueExpression {
+ get {
+ return (valueExpression);
+ }
+ }
+
+ // search pattern for the index keys (relative to the index value node)
+ private XPathExpression keyExpression;
+
+ public XPathExpression KeyExpression {
+ get {
+ return (keyExpression);
+ }
+ }
+
+ // a index mapping keys to the files that contain them
+ private Dictionary<string, string> index = new Dictionary<string, string>();
+
+ public void AddDocument(string file) {
+
+ // load the document
+ IndexedDocument document = new IndexedDocument(this, file);
+
+ // record the keys
+ string[] keys = document.GetKeys();
+ foreach (string key in keys) {
+ if (index.ContainsKey(key)) {
+ component.WriteHelperMessage(MessageLevel.Warn, String.Format("Entries for the key '{0}' occur in both '{1}' and '{2}'. The last entry will be used.", key, index[key], file));
+ }
+ index[key] = file;
+
+ }
+
+ }
+
+ public void AddDocuments(string wildcardPath) {
+ string directory_part = Path.GetDirectoryName(wildcardPath);
+ if (String.IsNullOrEmpty(directory_part)) directory_part = Environment.CurrentDirectory;
+ directory_part = Path.GetFullPath(directory_part);
+ string file_part = Path.GetFileName(wildcardPath);
+ //Console.WriteLine("{0}::{1}", directory_part, file_part);
+ string[] files = Directory.GetFiles(directory_part, file_part);
+ foreach (string file in files) {
+ AddDocument(file);
+ }
+
+ //Console.WriteLine(files.Length);
+ documentCount += files.Length;
+ }
+
+ public void AddDocuments(string baseDirectory, string wildcardPath, bool recurse) {
+
+ string path;
+ if (String.IsNullOrEmpty(baseDirectory)) {
+ path = wildcardPath;
+ } else {
+ path = Path.Combine(baseDirectory, wildcardPath);
+ }
+
+ AddDocuments(path);
+
+ if (recurse) {
+ string[] subDirectories = Directory.GetDirectories(baseDirectory);
+ foreach (string subDirectory in subDirectories) AddDocuments(subDirectory, wildcardPath, recurse);
+ }
+ }
+
+ private int documentCount;
+
+ public int DocumentCount {
+ get {
+ return (documentCount);
+ }
+ }
+
+ // a simple caching mechanism
+
+ int cacheSize;
+
+ // an improved cache
+
+ // this cache keeps track of the order that files are loaded in, and always unloads the oldest one
+ // this is better, but a document that is often accessed gets no "points", so it will eventualy be
+ // thrown out even if it is used regularly
+
+ private Dictionary<string, IndexedDocument> cache;
+
+ private Queue<string> queue;
+
+ public IndexedDocument GetDocument(string key) {
+
+ // look up the file corresponding to the key
+ string file;
+ if (index.TryGetValue(key, out file)) {
+
+ // now look for that file in the cache
+ IndexedDocument document;
+ if (!cache.TryGetValue(file, out document)) {
+
+ // not in the cache, so load it
+ document = new IndexedDocument(this, file);
+
+ // if the cache is full, remove a document
+ if (cache.Count >= cacheSize) {
+ string fileToUnload = queue.Dequeue();
+ cache.Remove(fileToUnload);
+ }
+
+ // add it to the cache
+ cache.Add(file, document);
+ queue.Enqueue(file);
+
+ }
+
+ // XPathNavigator content = document.GetContent(key);
+ return (document);
+
+ } else {
+ // there is no such key
+ return (null);
+ }
+
+ }
+
+
+ public XPathNavigator GetContent(string key) {
+
+ IndexedDocument document = GetDocument(key);
+ if (document == null) {
+ return (null);
+ } else {
+ return (document.GetContent(key));
+ }
+
+ }
+
+ public int Count {
+ get {
+ return (index.Count);
+ }
+ }
+
+ }
+
+ // a file that we have indexed
+
+ public class IndexedDocument {
+
+ public IndexedDocument(IndexedDocumentCache cache, string file) {
+
+ if (cache == null) throw new ArgumentNullException("cache");
+ if (file == null) throw new ArgumentNullException("file");
+
+ // remember the file
+ this.file = file;
+
+ // load the document
+ try {
+ //XPathDocument document = new XPathDocument(file, XmlSpace.Preserve);
+ XPathDocument document = new XPathDocument(file);
+
+ // search for value nodes
+ XPathNodeIterator valueNodes = document.CreateNavigator().Select(cache.ValueExpression);
+ // Console.WriteLine("found {0} instances of '{1}' (key xpath is '{2}')", valueNodes.Count, valueExpression.Expression, keyExpression.Expression);
+
+ // get the key string for each value node and record it in the index
+ foreach (XPathNavigator valueNode in valueNodes) {
+
+ XPathNavigator keyNode = valueNode.SelectSingleNode(cache.KeyExpression);
+ if (keyNode == null) {
+ // Console.WriteLine("null key");
+ continue;
+ }
+
+ string key = keyNode.Value;
+ index[key] = valueNode;
+ if (!index.ContainsKey(key)) {
+ //index.Add(key, valueNode);
+ } else {
+ // Console.WriteLine("Repeat key '{0}'", key);
+ }
+ }
+
+ } catch (IOException e) {
+ cache.Component.WriteHelperMessage(MessageLevel.Error, String.Format("An access error occured while attempting to load the file '{0}'. The error message is: {1}", file, e.Message));
+ } catch (XmlException e) {
+ cache.Component.WriteHelperMessage(MessageLevel.Error, String.Format("The indexed document '{0}' is not a valid XML document. The error message is: {1}", file, e.Message));
+ }
+ // Console.WriteLine("indexed {0} keys", index.Count);
+
+
+ }
+
+ // the indexed file
+
+ private string file;
+
+ // the index that maps keys to positions in the file
+
+ Dictionary<string, XPathNavigator> index = new Dictionary<string, XPathNavigator>();
+
+ // public methods
+
+ public string File {
+ get {
+ return (file);
+ }
+ }
+
+ public XPathNavigator GetContent(string key) {
+ XPathNavigator value = index[key];
+ if (value == null) {
+ return (null);
+ } else {
+ return (value.Clone());
+ }
+ }
+
+ public string[] GetKeys() {
+ string[] keys = new string[Count];
+ index.Keys.CopyTo(keys, 0);
+ return (keys);
+ }
+
+ public int Count {
+ get {
+ return (index.Count);
+ }
+ }
+
+ }
+
+ internal class CopyCommand {
+
+ public CopyCommand(IndexedDocumentCache source_index, string key_xpath, string source_xpath, string target_xpath, string attribute_value, string ignoreCase_value) {
+ this.cache = source_index;
+ if (String.IsNullOrEmpty(key_xpath)) {
+ // Console.WriteLine("null key xpath");
+ key = XPathExpression.Compile("string($key)");
+ } else {
+ // Console.WriteLine("compiling key xpath '{0}'", key_xpath);
+ key = XPathExpression.Compile(key_xpath);
+ }
+ source = XPathExpression.Compile(source_xpath);
+ target = target_xpath;
+ attribute = attribute_value;
+ ignoreCase = ignoreCase_value;
+ }
+
+ private IndexedDocumentCache cache;
+
+ private XPathExpression key;
+
+ private XPathExpression source;
+
+ private String target;
+
+ private String attribute;
+
+ private String ignoreCase;
+
+ private MessageLevel missingEntry = MessageLevel.Ignore;
+
+ private MessageLevel missingSource = MessageLevel.Ignore;
+
+ private MessageLevel missingTarget = MessageLevel.Ignore;
+
+ public IndexedDocumentCache Index {
+ get {
+ return (cache);
+ }
+ }
+
+ public XPathExpression Key {
+ get {
+ return (key);
+ }
+ }
+
+ public XPathExpression Source {
+ get {
+ return (source);
+ }
+ }
+
+ public String Target {
+ get {
+ return (target);
+ }
+ }
+
+ public String Attribute
+ {
+ get
+ {
+ return (attribute);
+ }
+ }
+
+ public String IgnoreCase
+ {
+ get
+ {
+ return (ignoreCase);
+ }
+ }
+
+ public MessageLevel MissingEntry {
+ get {
+ return (missingEntry);
+ }
+ set {
+ missingEntry = value;
+ }
+ }
+
+ public MessageLevel MissingSource {
+ get {
+ return (missingSource);
+ }
+ set {
+ missingSource = value;
+ }
+ }
+
+ public MessageLevel MissingTarget {
+ get {
+ return (missingTarget);
+ }
+ set {
+ missingTarget = value;
+ }
+ }
+
+ }
+
+ // the abstract CopyComponent
+ public abstract class CopyComponent
+ {
+
+ public CopyComponent(XPathNavigator configuration, Dictionary<string, object> data) { }
+
+ public abstract void Apply(XmlDocument document, string key);
+
+ }
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/DisplayComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/DisplayComponent.cs
new file mode 100644
index 0000000..33f0934
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/DisplayComponent.cs
@@ -0,0 +1,46 @@
+// 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.
+
+using System;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+
+ public class DisplayComponent : BuildComponent {
+
+ private string xpath_format = "/";
+
+ public DisplayComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+ XPathNavigator xpath_format_node = configuration.SelectSingleNode("xpath");
+ if (xpath_format_node != null) xpath_format = xpath_format_node.Value;
+ }
+
+ public override void Apply (XmlDocument document, string key) {
+ string xpath = String.Format(xpath_format, key);
+
+ Object result = document.CreateNavigator().Evaluate(xpath);
+
+ if (result == null) {
+ Console.WriteLine("null result");
+ return;
+ }
+
+ XPathNodeIterator nodes = result as XPathNodeIterator;
+ if (nodes != null) {
+ foreach (XPathNavigator node in nodes) {
+ Console.WriteLine(node.OuterXml);
+ }
+ return;
+ }
+
+ Console.WriteLine(result.ToString());
+
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ExampleComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ExampleComponent.cs
new file mode 100644
index 0000000..9ab0be7
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ExampleComponent.cs
@@ -0,0 +1,543 @@
+// 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.
+
+using System;
+using System.Configuration;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ // a component to replace code references with snippets from a file
+
+ public class ExampleComponent : BuildComponent {
+
+ // instantiation logic
+
+ public ExampleComponent(BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ XPathNodeIterator contentNodes = configuration.Select("examples");
+ foreach (XPathNavigator contentNode in contentNodes) {
+ string file = contentNode.GetAttribute("file", String.Empty);
+ file = Environment.ExpandEnvironmentVariables(file);
+ if (String.IsNullOrEmpty(file)) WriteMessage(MessageLevel.Error, String.Format("Each examples element must contain a file attribute."));
+ LoadContent(file);
+ }
+
+ WriteMessage(MessageLevel.Info, String.Format("Loaded {0} code snippets", snippets.Count));
+
+ XPathNodeIterator colorsNodes = configuration.Select("colors");
+ foreach (XPathNavigator colorsNode in colorsNodes) {
+ string language = colorsNode.GetAttribute("language", String.Empty);
+ List<ColorizationRule> rules = new List<ColorizationRule>();
+
+ XPathNodeIterator colorNodes = colorsNode.Select("color");
+ foreach (XPathNavigator colorNode in colorNodes) {
+ string pattern = colorNode.GetAttribute("pattern", String.Empty);
+ string region = colorNode.GetAttribute("region", String.Empty);
+ string name = colorNode.GetAttribute("class", String.Empty);
+ if (String.IsNullOrEmpty(region)) {
+ rules.Add( new ColorizationRule(pattern, name) );
+ } else {
+ rules.Add( new ColorizationRule(pattern, region, name) );
+ }
+ }
+
+ colorization[language] = rules;
+ WriteMessage(MessageLevel.Info, String.Format("Loaded {0} colorization rules for the language '{1}'.", rules.Count, language));
+ }
+
+ context.AddNamespace("ddue", "http://ddue.schemas.microsoft.com/authoring/2003/5");
+
+ selector = XPathExpression.Compile("//ddue:codeReference");
+ selector.SetContext(context);
+ }
+
+ // snippet loading logic
+
+ private void LoadContent(string file) {
+
+ SnippetIdentifier key = new SnippetIdentifier();
+ string language;
+
+ WriteMessage(MessageLevel.Info, String.Format("Loading code snippet file '{0}'.", file));
+ try {
+ XmlReaderSettings settings = new XmlReaderSettings();
+ settings.CheckCharacters = false;
+ XmlReader reader = XmlReader.Create(file, settings);
+
+ try {
+ reader.MoveToContent();
+ while (!reader.EOF) {
+ if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "item")) {
+ key = new SnippetIdentifier(reader.GetAttribute("id"));
+ reader.Read();
+ } else if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "sampleCode")) {
+ language = reader.GetAttribute("language");
+
+ string content = reader.ReadString();
+
+ // If the element is empty, ReadString does not advance the reader, so we must do it manually
+ if (String.IsNullOrEmpty(content)) reader.Read();
+
+ if (!IsLegalXmlText(content)) {
+ Console.WriteLine("Snippet '{0}' language '{1}' contains illegal characters.", key, language);
+ throw new InvalidOperationException();
+ }
+
+ content = StripLeadingSpaces(content);
+
+ StoredSnippet snippet = new StoredSnippet(content, language);
+ List<StoredSnippet> values;
+ if (!snippets.TryGetValue(key, out values)) {
+ values = new List<StoredSnippet>();
+ snippets.Add(key, values);
+ }
+ values.Add(snippet);
+ } else {
+ reader.Read();
+ }
+ }
+ } catch (XmlException e) {
+ WriteMessage(MessageLevel.Warn, String.Format("The contents of the snippet file '{0}' are not well-formed XML. The error message is: {1}. Some snippets may be lost.", file, e.Message));
+ } finally {
+ reader.Close();
+ }
+
+ } catch (IOException e) {
+ WriteMessage(MessageLevel.Error, String.Format("An access error occured while attempting to read the snippet file '{0}'. The error message is: {1}", file, e.Message));
+ }
+
+ }
+
+ // logic for checking XML
+
+ private bool IsLegalXmlCharacter (char c) {
+ if (c < 0x20) {
+ return ( (c == 0x09) || (c == 0x0A) || (c == 0x0D) );
+ } else {
+ if (c < 0xD800) {
+ return(true);
+ } else {
+ return( (c >= 0xE000) && (c <= 0xFFFD) );
+ }
+ }
+ }
+
+ private bool IsLegalXmlText (string text) {
+ foreach (char c in text) {
+ if (!IsLegalXmlCharacter(c)) return (false);
+ }
+ return (true);
+ }
+
+ // the snippet store
+
+ private Dictionary<SnippetIdentifier,List<StoredSnippet>> snippets = new Dictionary<SnippetIdentifier,List<StoredSnippet>>();
+
+ // the actual work of the component
+
+ public override void Apply(XmlDocument document, string key) {
+ XPathNodeIterator nodesIterator = document.CreateNavigator().Select(selector);
+ XPathNavigator[] nodes = BuildComponentUtilities.ConvertNodeIteratorToArray(nodesIterator);
+ foreach (XPathNavigator node in nodes) {
+
+ string reference = node.Value;
+
+ // check for validity of reference
+ if (validSnippetReference.IsMatch(reference)) {
+
+
+ SnippetIdentifier[] identifiers = SnippetIdentifier.ParseReference(reference);
+
+ if (identifiers.Length == 1) {
+ // one snippet referenced
+
+ SnippetIdentifier identifier = identifiers[0];
+ List<StoredSnippet> values;
+ if (snippets.TryGetValue(identifier, out values)) {
+
+ XmlWriter writer = node.InsertAfter();
+ writer.WriteStartElement("snippets");
+ writer.WriteAttributeString("reference", reference);
+
+ foreach (StoredSnippet value in values) {
+ writer.WriteStartElement("snippet");
+ writer.WriteAttributeString("language", value.Language);
+
+ if (colorization.ContainsKey(value.Language)) {
+ WriteColorizedSnippet(ColorizeSnippet(value.Text, colorization[value.Language]), writer);
+
+ } else {
+ writer.WriteString(value.Text);
+ //writer.WriteString(System.Web.HttpUtility.HtmlDecode(value.Text));
+ }
+ writer.WriteEndElement();
+ }
+
+ writer.WriteEndElement();
+ writer.Close();
+
+ } else {
+ WriteMessage(MessageLevel.Warn, String.Format("No snippet with identifier '{0}' was found.", identifier));
+ }
+ } else {
+ // multiple snippets referenced
+
+ // create structure that maps language -> snippets
+ Dictionary<string,List<StoredSnippet>> map = new Dictionary<string,List<StoredSnippet>>();
+ foreach (SnippetIdentifier identifier in identifiers) {
+ List<StoredSnippet> values;
+ if (snippets.TryGetValue(identifier, out values)) {
+ foreach (StoredSnippet value in values) {
+ List<StoredSnippet> pieces;
+ if (!map.TryGetValue(value.Language, out pieces)) {
+ pieces = new List<StoredSnippet>();
+ map.Add(value.Language, pieces);
+ }
+ pieces.Add(value);
+ }
+ }
+ }
+
+ XmlWriter writer = node.InsertAfter();
+ writer.WriteStartElement("snippets");
+ writer.WriteAttributeString("reference", reference);
+
+ foreach (KeyValuePair<string,List<StoredSnippet>> entry in map) {
+ writer.WriteStartElement("snippet");
+ writer.WriteAttributeString("language", entry.Key);
+
+ List<StoredSnippet> values = entry.Value;
+ for (int i=0; i<values.Count; i++) {
+ if (i>0) writer.WriteString("\n...\n\n\n");
+ writer.WriteString(values[i].Text);
+ // writer.WriteString(System.Web.HttpUtility.HtmlDecode(values[i].Text));
+ }
+
+ writer.WriteEndElement();
+ }
+
+ writer.WriteEndElement();
+ writer.Close();
+
+ }
+
+ } else {
+ WriteMessage(MessageLevel.Warn, String.Format("The code reference '{0}' is not well-formed", reference));
+ }
+
+ node.DeleteSelf();
+
+ }
+ }
+
+ private XPathExpression selector;
+
+ private XmlNamespaceManager context = new CustomContext();
+
+ private static Regex validSnippetReference = new Regex(@"^[^#\a\b\f\n\r\t\v]+#(\w+,)*\w+$", RegexOptions.Compiled);
+
+ // colorization logic
+
+ private Dictionary<string,List<ColorizationRule>> colorization = new Dictionary<string,List<ColorizationRule>>();
+
+ private static ICollection<Region> ColorizeSnippet (string text, List<ColorizationRule> rules) {
+
+ // Console.WriteLine("colorizing: '{0}'", text);
+
+ // create a linked list consiting entirely of one uncolored region
+ LinkedList<Region> regions = new LinkedList<Region>();
+ regions.AddFirst( new Region(text) );
+
+ // loop over colorization rules
+ foreach (ColorizationRule rule in rules) {
+
+ // loop over regions
+
+ LinkedListNode<Region> node = regions.First;
+ while(node != null) {
+
+ // only try to colorize uncolored regions
+ if (node.Value.ClassName != null) {
+ node = node.Next;
+ continue;
+ }
+
+ // find matches in the region
+ string regionText = node.Value.Text;
+ Capture[] matches = rule.Apply(regionText);
+
+ // if no matches were found, continue to the next region
+ if (matches.Length == 0) {
+ node = node.Next;
+ continue;
+ }
+
+ // we found matches; break the region into colored and uncolered subregions
+
+ // index is where we are looking from; index-1 is the end of the last match
+ int index = 0;
+
+ LinkedListNode<Region> referenceNode = node;
+
+ foreach (Capture match in matches) {
+
+ // create a leading uncolored region
+ if (match.Index > index) {
+ //Console.WriteLine("uncolored: {0} '{1}' -> {2} '{3}'", index, regionText[index], match.Index - 1, regionText[match.Index - 1]);
+ Region uncoloredRegion = new Region(regionText.Substring(index, match.Index-index));
+ referenceNode = regions.AddAfter(referenceNode, uncoloredRegion);
+ }
+
+ // create a colored region
+ // Console.WriteLine("name = {0}", rule.ClassName);
+ //Console.WriteLine("colored: {0} '{1}' -> {2} '{3}'", match.Index, regionText[match.Index], match.Index + match.Length - 1, regionText[match.Index + match.Length - 1]);
+ Region coloredRegion = new Region(rule.ClassName, regionText.Substring(match.Index, match.Length));
+ referenceNode = regions.AddAfter(referenceNode, coloredRegion);
+
+ index = match.Index + match.Length;
+
+ }
+
+ // create a trailing uncolored region
+ if (index < regionText.Length) {
+ Region uncoloredRegion = new Region(regionText.Substring(index));
+ referenceNode = regions.AddAfter(referenceNode, uncoloredRegion);
+ }
+
+ // remove the original node
+ regions.Remove(node);
+
+ node = referenceNode.Next;
+ }
+
+
+ }
+ return(regions);
+
+ }
+
+ private static void WriteColorizedSnippet (ICollection<Region> regions, XmlWriter writer) {
+ foreach (Region region in regions) {
+ // Console.WriteLine("writing {0}", region.ClassName);
+ if (region.ClassName == null) {
+ writer.WriteString(region.Text);
+ } else {
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", region.ClassName);
+ writer.WriteString(region.Text);
+ writer.WriteEndElement();
+ }
+ }
+ }
+
+ private static string StripLeadingSpaces (string text) {
+
+ if (text == null) throw new ArgumentNullException("text");
+
+ // Console.WriteLine("BEFORE:");
+ // Console.WriteLine(text);
+
+ // split the text into lines
+ string[] lines = text.Split('\n');
+
+ // no need to do this if there is only one line
+ if (lines.Length == 1) return(lines[0]);
+
+ // figure out how many leading spaces to delete
+ int spaces = Int32.MaxValue;
+ for (int i=0; i<lines.Length; i++) {
+
+ string line = lines[i];
+
+ // skip empty lines
+ if (line.Length == 0) continue;
+
+ // determine the number of leading spaces
+ int index = 0;
+ while (index < line.Length) {
+ if (line[index] != ' ') break;
+ index++;
+ }
+
+ if (index == line.Length) {
+ // lines that are all spaces should just be treated as empty
+ lines[i] = String.Empty;
+ } else {
+ // otherwise, keep track of the minimum number of leading spaces
+ if (index < spaces) spaces = index;
+ }
+
+ }
+
+ // Console.WriteLine("SPACES = {0}", spaces);
+
+ // re-form the string with leading spaces deleted
+ StringBuilder result = new StringBuilder();
+ foreach (string line in lines) {
+ if (line.Length == 0) {
+ result.AppendLine();
+ } else {
+ result.AppendLine(line.Substring(spaces));
+ }
+ }
+ // Console.WriteLine("AFTER:");
+ // Console.WriteLine(result.ToString());
+ return(result.ToString());
+
+ }
+
+ }
+
+ internal struct SnippetIdentifier {
+
+ public SnippetIdentifier (string exampleId, string snippetId) {
+ this.exampleId = exampleId.ToLower();
+ this.snippetId = snippetId.ToLower();
+ }
+
+ public SnippetIdentifier (string identifier) {
+ int index = identifier.LastIndexOf('#');
+ exampleId = identifier.Substring(0,index).ToLower();
+ snippetId = identifier.Substring(index+1).ToLower();
+ }
+
+ private string exampleId;
+
+ private string snippetId;
+
+ public string Example {
+ get {
+ return(exampleId);
+ }
+ }
+
+ public string Snippet {
+ get {
+ return(snippetId);
+ }
+ }
+
+ public override string ToString() {
+ return(String.Format("{0}#{1}", exampleId, snippetId));
+ }
+
+ public static SnippetIdentifier[] ParseReference (string reference) {
+
+ int index = reference.IndexOf('#');
+ if (index < 0) return(new SnippetIdentifier[0]);
+
+ string example = reference.Substring(0,index);
+ string[] snippets = reference.Substring(index+1).Split(',');
+
+ SnippetIdentifier[] identifiers = new SnippetIdentifier[snippets.Length];
+ for (int i=0; i<snippets.Length; i++) {
+ identifiers[i] = new SnippetIdentifier(example, snippets[i]);
+ }
+ return(identifiers);
+
+ }
+
+ }
+
+ internal class StoredSnippet {
+
+ public StoredSnippet (string text, string language) {
+ this.text = text;
+ this.language = language;
+ }
+
+ private string text;
+
+ private string language;
+
+ public string Text {
+ get {
+ return(text);
+ }
+ }
+
+ public string Language {
+ get {
+ return(language);
+ }
+ }
+ }
+
+ internal class ColorizationRule {
+
+ public ColorizationRule (string pattern, string className) : this(pattern, null, className) {}
+
+ public ColorizationRule (string pattern, string region, string className) {
+ this.pattern = new Regex(pattern, RegexOptions.Compiled|RegexOptions.Multiline);
+ this.region = region;
+ this.className = className;
+ }
+
+ private Regex pattern;
+
+ private string region;
+
+ private string className;
+
+ public string ClassName {
+ get {
+ return(className);
+ }
+ }
+
+ public Capture[] Apply (string text) {
+
+ MatchCollection matches = pattern.Matches(text);
+ Capture[] captures = new Capture[matches.Count];
+
+ if (region == null) {
+ matches.CopyTo(captures, 0);
+ return(captures);
+ } else {
+ for (int i=0; i<captures.Length; i++) {
+ captures[i] = matches[i].Groups[region];
+ }
+ return(captures);
+ }
+
+ }
+
+ }
+
+ internal struct Region {
+
+ public Region (string text) : this(null, text) {}
+
+ public Region (string className, string text) {
+ this.className = className;
+ this.text = text;
+ }
+
+ private string className;
+
+ private string text;
+
+
+ public string ClassName {
+ get {
+ return(className);
+ }
+ }
+
+ public string Text {
+ get {
+ return(text);
+ }
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ForEachComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ForEachComponent.cs
new file mode 100644
index 0000000..06705e8
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ForEachComponent.cs
@@ -0,0 +1,105 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class ForEachComponent : BuildComponent {
+
+ public ForEachComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ // set up the context
+ XPathNodeIterator context_nodes = configuration.Select("context");
+ foreach (XPathNavigator context_node in context_nodes)
+ {
+ string prefix = context_node.GetAttribute("prefix", String.Empty);
+ string name = context_node.GetAttribute("name", String.Empty);
+ context.AddNamespace(prefix, name);
+ }
+
+ // load the expression format
+ XPathNavigator variable_node = configuration.SelectSingleNode("variable");
+ if (variable_node == null) throw new ConfigurationErrorsException("When instantiating a ForEach component, you must specify a variable using the <variable> element.");
+ string xpath_format = variable_node.GetAttribute("expression", String.Empty);
+ if ((xpath_format == null) || (xpath_format.Length == 0)) throw new ConfigurationErrorsException("When instantiating a ForEach component, you must specify a variable expression using the expression attribute");
+ xpath = XPathExpression.Compile(xpath_format);
+
+ // load the subcomponents
+ WriteMessage(MessageLevel.Info, "Loading subcomponents.");
+ XPathNavigator components_node = configuration.SelectSingleNode("components");
+ if (components_node == null) throw new ConfigurationErrorsException("When instantiating a ForEach component, you must specify subcomponents using the <components> element.");
+
+ components = BuildAssembler.LoadComponents(components_node);
+
+ WriteMessage(MessageLevel.Info, String.Format("Loaded {0} subcomponents.", components.Count));
+
+ }
+
+ // the format string for the variable expression
+ private XPathExpression xpath;
+
+ // the xpath context
+ private CustomContext context = new CustomContext();
+
+ // the subcomponents
+ private ICollection<BuildComponent> components;
+
+ // the work of the component
+
+ public override void Apply (XmlDocument document, string key) {
+
+ // adjust the context
+ context["key"] = key;
+
+ // evaluate the condition
+ XPathExpression xpath_local = xpath.Clone();
+ xpath_local.SetContext(context);
+
+ Object result = document.CreateNavigator().Evaluate(xpath_local);
+
+ // try to intrepret the result as a node set
+ XPathNodeIterator result_node_iterator = result as XPathNodeIterator;
+
+ if (result_node_iterator != null) {
+ XPathNavigator[] result_nodes = BuildComponentUtilities.ConvertNodeIteratorToArray(result_node_iterator);
+ //Console.WriteLine("{0} node-set result", result_nodes.Length);
+ // if it is, apply the child components to each node value
+ foreach (XPathNavigator result_node in result_nodes) {
+ // Console.WriteLine(result_node.Value);
+ ApplyComponents(document, result_node.Value);
+ }
+ } else {
+ //Console.WriteLine("non-node-set result");
+ // if it isn't, apply the child components to the string value of the result
+ ApplyComponents(document, result.ToString());
+
+ }
+
+
+ }
+
+ private void ApplyComponents (XmlDocument document, string key) {
+ foreach (BuildComponent component in components) {
+ component.Apply(document, key);
+ }
+ }
+
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ foreach (BuildComponent component in components) {
+ component.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/GlobalSuppressions.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/GlobalSuppressions.cs
new file mode 100644
index 0000000..3fd693e
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/GlobalSuppressions.cs
@@ -0,0 +1,319 @@
+// 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.
+
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+//
+// To add a suppression to this file, right-click the message in the
+// Error List, point to "Suppress Message(s)", and click
+// "In Project Suppression File".
+// You do not need to add suppressions to this file manually.
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ddue", Scope = "namespace", Target = "Microsoft.Ddue.Tools")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "BuildComponents.ArrayTypeReference.#Create(System.Xml.XmlReader)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "apidata", Scope = "member", Target = "BuildComponents.NamespaceTarget.#Create(System.Xml.XmlReader)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "BuildComponents.Reference.#referenceApiExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Refered", Scope = "member", Target = "BuildComponents.ReferenceTypeReference.#ReferedToType")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "BuildComponents.SimpleMemberReference.#.ctor(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "BuildComponents.Target.#apiNameExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "BuildComponents.TemplateTypeReference.#.ctor(BuildComponents.ISimpleReference,System.Int32)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily", Scope = "member", Target = "BuildComponents.TemplateTypeReference.#.ctor(System.String,System.Int32)")]
+
+// TODO: revisit
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "BuildComponents.TemplateTypeReference.#.ctor(System.String,System.Int32)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "templateId", Scope = "member", Target = "BuildComponents.TemplateTypeReference.#.ctor(System.String,System.Int32)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Scope = "member", Target = "BuildComponents.TemplateTypeReference.#position")]
+
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "BuildComponents.TypeReference.#Create(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "BuildComponents.TypeReference.#Create(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "BuildComponents.TypeTarget.#containingAssembly")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "BuildComponents.TypeTarget.#containingNamespace")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "BuildComponents.TypeTarget.#containingType")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "BuildComponents.TypeTarget.#subgroup")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Scope = "member", Target = "Microsoft.Ddue.Tools.ArtTarget.#Id")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "ddue", Scope = "member", Target = "Microsoft.Ddue.Tools.CodeReference.#.ctor(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ddue", Scope = "member", Target = "Microsoft.Ddue.Tools.CodeReference.#DdueCodeReference")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Scope = "member", Target = "Microsoft.Ddue.Tools.CodeReference.#Type")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.ConceptualLinkInfo.#.ctor()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.ConceptualLinkInfo.#ShowText")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.ConstructorTarget.#Parameters")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1012:AbstractTypesShouldNotHaveConstructors", Scope = "type", Target = "Microsoft.Ddue.Tools.CopyComponent")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "configuration", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyComponent.#.ctor(System.Xml.XPath.XPathNavigator,System.Collections.Generic.Dictionary`2<System.String,System.Object>)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "data", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyComponent.#.ctor(System.Xml.XPath.XPathNavigator,System.Collections.Generic.Dictionary`2<System.String,System.Object>)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes", MessageId = "System.Xml.XmlNode", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyFromFileComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyFromFilesComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyFromIndexComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyFromIndexComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyFromIndexComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyFromIndexComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyFromIndexComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyFromIndexComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyFromIndexComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyFromIndexComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyFromIndexComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.CopyFromIndexComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.CopySet.#.ctor(Microsoft.Ddue.Tools.IndexedFileCache,System.String,System.String,System.Xml.XmlNamespaceManager)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.CopySet.#FileCache")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.CopySet.#GetTargetExpression(System.Xml.XPath.XPathNavigator,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.DisplayComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ExampleComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ExampleComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object[])", Scope = "member", Target = "Microsoft.Ddue.Tools.ExampleComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ExampleComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.ExampleComponent.#IsLegalXmlCharacter(System.Char)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ExampleComponent.#LoadContent(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ExampleComponent.#LoadContent(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "hxf", Scope = "member", Target = "Microsoft.Ddue.Tools.FileCreatedEventArgs.#.ctor(System.String,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Hxf", Scope = "member", Target = "Microsoft.Ddue.Tools.FileCreatedEventArgs.#HxfPath")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ForEachComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Hxf", Scope = "type", Target = "Microsoft.Ddue.Tools.HxfGeneratorComponent")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.HxfGeneratorComponent.#WriteFile(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1012:AbstractTypesShouldNotHaveConstructors", Scope = "type", Target = "Microsoft.Ddue.Tools.InclusionFilter")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.InclusionFilter.#apiNameExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.InclusionFilter.#apiParameterNodesExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.InclusionFilter.#apiParameterTemplateNameExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.InclusionFilter.#apiParameterTypeNameExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.Ddue.Tools.InclusionFilter.#sourceFiles")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists", Scope = "member", Target = "Microsoft.Ddue.Tools.InclusionFilter.#sourceFiles")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.IndexedDocument.#.ctor(Microsoft.Ddue.Tools.IndexedDocumentCache,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.IndexedDocumentCache.#.ctor(Microsoft.Ddue.Tools.CopyFromIndexComponent,System.String,System.String,System.Xml.XmlNamespaceManager,System.Int32)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.IndexedDocumentCache.#AddDocument(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.IndexedFile.#.ctor(System.String,System.Xml.XPath.XPathExpression,System.Xml.XPath.XPathExpression)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.IndexedFile.#GetContent(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.IndexedFile.#ListNode")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.IndexedFile.#ListNode")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.IndexedFileCache")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.Compare(System.String,System.String,System.Boolean)", Scope = "member", Target = "Microsoft.Ddue.Tools.ReferenceLinkInfo2.#Create(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.Compare(System.String,System.String,System.Boolean)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveReferenceLinksComponent2.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.Compare(System.String,System.String,System.Boolean)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveReferenceLinksComponent2.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveArtLinksComponent.#AddTargets(System.String,System.String,System.String,System.Xml.XPath.XPathExpression,System.String,System.Xml.XPath.XPathExpression,System.Xml.XPath.XPathExpression)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveArtLinksComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveConceptualLinksComponent.#ResolveConceptualLinks(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#LoadContent(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#ResolveContent(System.Xml.XmlDocument,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetIdentifier.#.ctor(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetIdentifier.#.ctor(System.String,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberFilter.#AddMemberNode(System.Xml.XmlReader,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberFilter.#.ctor(System.Xml.XmlReader,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.NamespaceFilter.#AddNamespaceNode(System.Xml.XmlReader,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.NamespaceFilter.#.ctor(System.Xml.XmlReader,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.OverloadFilter.#.ctor(System.Xml.XmlReader,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveConceptualLinksComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.SaveComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.TransformComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.TypeFilter.#AddTypeNode(System.Xml.XmlReader,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.TypeFilter.#.ctor(System.Xml.XmlReader,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.VersionFilter.#AddPlatformNode(System.Xml.XmlReader,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.WdxResolveConceptualLinksComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#CreateTypeReference(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.XmlTargetCollectionUtilities.#CreateTypeReference(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Int32.ToString", Scope = "member", Target = "Microsoft.Ddue.Tools.LinkTextResolver.#WriteArrayType(Microsoft.Ddue.Tools.ArrayTypeReference,Microsoft.Ddue.Tools.DisplayOptions,System.Xml.XmlWriter,System.Collections.Generic.Dictionary`2<Microsoft.Ddue.Tools.IndexedTemplateTypeReference,Microsoft.Ddue.Tools.TypeReference>)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent.#ReadInputFile(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent2.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent2.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent2.#ReadInputFile(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.LinkTextResolver.#GetTypeTemplateName(Microsoft.Ddue.Tools.SimpleTypeReference,System.Int32)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.LiveExampleComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.LiveExampleComponent.#LoadApprovedFile(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.PlatformsComponent.#ParseDocuments(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveArtLinksComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveArtLinksComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveConceptualLinksComponent.#BrokenLinkDisplayText(System.String,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveConceptualLinksComponent.#ResolveConceptualLinks(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveConceptualLinksComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveReferenceLinksComponent2.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveReferenceLinksComponent2.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#LoadContent(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#ParseDocuments(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#CreateSpecializedTypeReference(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#FindMatchingEndBracket(System.String,System.Int32)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#.cctor()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ValidateComponent.#LogValidationError(System.Object,System.Xml.Schema.ValidationEventArgs)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.WdxResolveConceptualLinksComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.WdxResolveConceptualLinksComponent+TargetSet.#Lookup(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.WdxResolveConceptualLinksComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.XmlTargetCollectionUtilities.#CreateEnumerationTarget(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.LinkType2)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.XmlTargetCollectionUtilities.#CreateTarget(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.LinkType2)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.XmlTargetCollectionUtilities.#CreateTypeReference(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent.#ReadInputFile(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent2.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent2.#ReadInputFile(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.LiveExampleComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.LiveExampleComponent.#LoadApprovedFile(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.MsdnResolver.#GetMsdnUrl(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.PlatformsComponent.#ParseDocuments(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveArtLinksComponent.#AddTargets(System.String,System.String,System.String,System.Xml.XPath.XPathExpression,System.String,System.Xml.XPath.XPathExpression,System.Xml.XPath.XPathExpression)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveArtLinksComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveConceptualLinksComponent.#CompileXPathExpression(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveReferenceLinksComponent2.#AddTargets(System.String,Microsoft.Ddue.Tools.LinkType2)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveReferenceLinksComponent2.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SaveComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#GetContent(System.String,System.String[])")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#LoadContent(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#ParseDocuments(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#ResolveContent(System.Xml.XmlDocument,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetIdentifier.#ToString()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#FindMatchingEndBracket(System.String,System.Int32)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#.cctor()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.TransformComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.WdxResolveConceptualLinksComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.WdxResolveConceptualLinksComponent.#CompileXPathExpression(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.LiveExampleComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#ParseDocument(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#CreateMemberReference(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#.cctor()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object[])", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#GetContent(System.String,System.String[])")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object[])", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#.cctor()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object[])", Scope = "member", Target = "Microsoft.Ddue.Tools.TransformComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveReferenceLinksComponent2.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.IndexOf(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent.#CopyContent(System.Xml.XmlReader,System.Xml.XmlWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.StartsWith(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent.#CopyContent(System.Xml.XmlReader,System.Xml.XmlWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.Compare(System.String,System.String,System.Boolean)", Scope = "member", Target = "Microsoft.Ddue.Tools.ReferenceLinkInfo2.#Create(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.Compare(System.String,System.String,System.Boolean)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveReferenceLinksComponent2.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.Compare(System.String,System.String,System.Boolean)", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveReferenceLinksComponent2.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.StartsWith(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#CreateTypeReference(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.IndexOf(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Param", Scope = "member", Target = "Microsoft.Ddue.Tools.OverloadFilter.#ParamNames")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Param", Scope = "member", Target = "Microsoft.Ddue.Tools.OverloadFilter.#ParamTypes")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Refered", Scope = "member", Target = "Microsoft.Ddue.Tools.ReferenceTypeReference.#ReferedToType")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wdx", Scope = "type", Target = "Microsoft.Ddue.Tools.WdxResolveConceptualLinksComponent")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "dict", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#AddValueToListDictionary`2(System.Collections.Generic.Dictionary`2<!!0,System.Collections.Generic.List`1<!!1>>,!!0,!!1)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "cer", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#SetGenericContext(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "xpath", Scope = "member", Target = "Microsoft.Ddue.Tools.WdxResolveConceptualLinksComponent.#CompileXPathExpression(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "K", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#AddValueToListDictionary`2(System.Collections.Generic.Dictionary`2<!!0,System.Collections.Generic.List`1<!!1>>,!!0,!!1)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "V", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#AddValueToListDictionary`2(System.Collections.Generic.Dictionary`2<!!0,System.Collections.Generic.List`1<!!1>>,!!0,!!1)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Scope = "type", Target = "Microsoft.Ddue.Tools.TargetCollection")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1715:IdentifiersShouldHaveCorrectPrefix", MessageId = "T", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#AddValueToListDictionary`2(System.Collections.Generic.Dictionary`2<!!0,System.Collections.Generic.List`1<!!1>>,!!0,!!1)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberTarget.#Type")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Scope = "member", Target = "Microsoft.Ddue.Tools.Parameter.#Type")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "1#", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "1#", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveArtLinksComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "1#", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent2.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "configuration", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGenerator.#.ctor(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "key", Scope = "member", Target = "Microsoft.Ddue.Tools.NamespaceFilter.#IsIncludedType(System.Xml.XPath.XPathNavigator,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "location", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxWriter.#.ctor(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "options", Scope = "member", Target = "Microsoft.Ddue.Tools.LinkTextResolver.#WriteInvalid(Microsoft.Ddue.Tools.InvalidReference,Microsoft.Ddue.Tools.DisplayOptions,System.Xml.XmlWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "options", Scope = "member", Target = "Microsoft.Ddue.Tools.LinkTextResolver.#WriteNamespaceTarget(Microsoft.Ddue.Tools.NamespaceTarget,Microsoft.Ddue.Tools.DisplayOptions,System.Xml.XmlWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "options", Scope = "member", Target = "Microsoft.Ddue.Tools.LinkTextResolver.#WriteProcedureName(Microsoft.Ddue.Tools.ProcedureTarget,Microsoft.Ddue.Tools.DisplayOptions,System.Xml.XmlWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "options", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#WriteNamespaceReference(Microsoft.Ddue.Tools.NamespaceReference,Microsoft.Ddue.Tools.DisplayOptions,System.Xml.XmlWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "key", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveConceptualLinksComponent.#ResolveConceptualLinks(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetIdentifier.#Example")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetIdentifier.#Snippet")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent.#CopyContent(System.Xml.XmlReader,System.Xml.XmlWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent.#namespaceAssemblyExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent2.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.IntellisenseComponent2.#CopyContent(System.Xml.XmlReader,System.Xml.XmlWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "Microsoft.Ddue.Tools.LiveExampleComponent.#LoadApprovedFile(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings", Scope = "member", Target = "Microsoft.Ddue.Tools.MsdnResolver.#GetMsdnUrl(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "Microsoft.Ddue.Tools.PlatformsComponent.#AddPlatformVersionFilter(System.String,System.String,System.Xml.XPath.XPathNavigator,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "Microsoft.Ddue.Tools.PlatformsComponent.#ParseDocument(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.LinkTextResolver.#WriteNamespaceTarget(Microsoft.Ddue.Tools.NamespaceTarget,Microsoft.Ddue.Tools.DisplayOptions,System.Xml.XmlWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.LinkTextResolver.#WriteTemplateType(Microsoft.Ddue.Tools.TemplateTypeReference,Microsoft.Ddue.Tools.DisplayOptions,System.Xml.XmlWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedSyntaxWriter.#.ctor(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.MethodTarget.#Parameters")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.MethodTarget.#Templates")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.MethodTemplateTypeReference.#.ctor(Microsoft.Ddue.Tools.MemberReference,System.Int32)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable", Scope = "type", Target = "Microsoft.Ddue.Tools.MsdnResolver")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.ProcedureTarget.#.ctor()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.PropertyTarget.#Parameters")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.ReferenceLinkInfo2.#.ctor()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveConceptualLinksComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "filesValue", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveConceptualLinksComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Ddue.Tools.ResolveReferenceLinksComponent2.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.SaveComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "doctype", Scope = "member", Target = "Microsoft.Ddue.Tools.SaveComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "item_expression", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "path_expresion", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#DetectLoops()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#DetectLoops()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "content", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentComponent.#ResolveContent(System.Xml.XmlDocument,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentElement.#.ctor(System.String,System.String,System.String,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.SharedContentElement.#IsAttribute")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.Specialization.#Arguments")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.SpecializedMemberWithParametersReference.#ParameterTypes")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Scope = "member", Target = "Microsoft.Ddue.Tools.SpecializedTypeReference.#GetSpecializationDictionary()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.SpecializedTypeReference.#Specializations")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.TargetDirectory.#.ctor(System.String,Microsoft.Ddue.Tools.LinkType)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.TargetDirectory.#Directory")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.TargetDirectory.#GetTargetInfo(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.CustomContext)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.TargetDirectory.#LinkType")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.TargetDirectory.#TextExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.TargetDirectory.#UrlExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.TargetDirectoryCollection.#GetTargetInfo(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.CustomContext)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#AddValueToListDictionary`2(System.Collections.Generic.Dictionary`2<!!0,System.Collections.Generic.List`1<!!1>>,!!0,!!1)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1820:TestForEmptyStringsUsingStringLength", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#GetDocument(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#ParseDocument(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Scope = "member", Target = "Microsoft.Ddue.Tools.TaskGrabberComponent.#xpathFromConfig")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1053:StaticHolderTypesShouldNotHaveConstructors", Scope = "type", Target = "Microsoft.Ddue.Tools.Test")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#.cctor()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#.cctor()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "baseTypePattern", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#.cctor()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#CreateReference(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#genericMemberContext")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#tr")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Scope = "member", Target = "Microsoft.Ddue.Tools.TextReferenceUtilities.#ValidTest")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.TypeTarget.#Templates")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.TypeTemplateTypeReference.#.ctor(Microsoft.Ddue.Tools.SimpleTypeReference,System.Int32)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Scope = "member", Target = "Microsoft.Ddue.Tools.XmlTargetCollectionUtilities.#apiSubsubgroupExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Scope = "member", Target = "Microsoft.Ddue.Tools.XmlTargetCollectionUtilities.#topicGroupExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Scope = "member", Target = "Microsoft.Ddue.Tools.MethodTarget.#returnType")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Scope = "member", Target = "Microsoft.Ddue.Tools.PropertyTarget.#returnType")]
+
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.ExtensionMethodReference.#Parameters")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.ExtensionMethodReference.#TemplateArgs")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.HxfGeneratorComponent.#FileCreatedHandler(System.Object,System.EventArgs)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Scope = "member", Target = "Microsoft.Ddue.Tools.IndexedExample.#isApprovedUnit(System.IO.DirectoryInfo)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.IndexedExample.#IsLegalXmlCharacter(System.Char)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.IndexedExample.#ParseFile(System.IO.FileInfo,System.String,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.IndexedExample.#ParseUnit(System.IO.DirectoryInfo)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.Language.#Extension")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "extension", Scope = "member", Target = "Microsoft.Ddue.Tools.Language.#IsMatch(System.String,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "languageId", Scope = "member", Target = "Microsoft.Ddue.Tools.Language.#IsMatch(System.String,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "parameters", Scope = "member", Target = "Microsoft.Ddue.Tools.LinkTextResolver.#WriteExtensionMethod(Microsoft.Ddue.Tools.ExtensionMethodReference,Microsoft.Ddue.Tools.DisplayOptions,System.Xml.XmlWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.LinkTextResolver.#WriteMemberTarget(Microsoft.Ddue.Tools.MemberTarget,Microsoft.Ddue.Tools.DisplayOptions,System.Xml.XmlWriter,System.Collections.Generic.Dictionary`2<Microsoft.Ddue.Tools.IndexedTemplateTypeReference,Microsoft.Ddue.Tools.TypeReference>)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Microsoft.Ddue.Tools.LinkTextResolver.#WriteNamespaceTarget(Microsoft.Ddue.Tools.NamespaceTarget,Microsoft.Ddue.Tools.DisplayOptions,System.Xml.XmlWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "overloadId", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberFilter.#AddMemberNode(System.Xml.XmlReader,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "paramNames", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberFilter.#AddMemberNode(System.Xml.XmlReader,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "key", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberFilter.#IsIncludedMember(System.Xml.XPath.XPathNavigator,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.MethodTarget.#TemplateArgs")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#.ctor(Microsoft.Ddue.Tools.BuildAssembler,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#Apply(System.Xml.XmlDocument,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#loadExamples(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#loadExamples(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#parseApprovalLogFiles(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#parseApprovalLogFiles(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#parseApprovalLogFiles(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "identifier", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#writeSnippetContent(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SnippetIdentifier,System.Collections.Generic.List`1<Microsoft.Ddue.Tools.Snippet>)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#writeSnippetContent(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SnippetIdentifier,System.Collections.Generic.List`1<Microsoft.Ddue.Tools.Snippet>)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.SnippetComponent.#WriteSnippetText(Microsoft.Ddue.Tools.Snippet,System.Xml.XmlWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1708:IdentifiersShouldDifferByMoreThanCase", Scope = "type", Target = "Microsoft.Ddue.Tools.Specialization")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.Ddue.Tools.Specialization.#arguments")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Microsoft.Ddue.Tools.XmlTargetCollectionUtilities.#CreateTypeReference(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.LinkTextResolver.#WriteConversionOperator(Microsoft.Ddue.Tools.ProcedureTarget,System.Xml.XmlWriter)")]
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/HxfGeneratorComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/HxfGeneratorComponent.cs
new file mode 100644
index 0000000..176ce97
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/HxfGeneratorComponent.cs
@@ -0,0 +1,132 @@
+// 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.
+
+using System;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Collections.Generic;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class FileCreatedEventArgs : EventArgs {
+
+ private string filePath;
+ private string hxfPath;
+
+ public FileCreatedEventArgs(string filePath, string hxfPath) {
+ this.filePath = filePath;
+ this.hxfPath = hxfPath;
+ }
+
+ public string FilePath {
+ get {
+ return(filePath);
+ }
+ }
+
+ public string HxfPath {
+ get {
+ return (hxfPath);
+ }
+ }
+
+ }
+
+ public class HxfGeneratorComponent : BuildComponent {
+
+ public HxfGeneratorComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ // get configuration data
+ inputValue = configuration.GetAttribute("input", String.Empty);
+ if (!String.IsNullOrEmpty(inputValue)) inputValue = Environment.ExpandEnvironmentVariables(inputValue);
+ outputValue = configuration.GetAttribute("output", String.Empty);
+ if (!String.IsNullOrEmpty(outputValue)) outputValue = Environment.ExpandEnvironmentVariables(outputValue);
+
+ // subscribe to component events
+ assembler.ComponentEvent += new EventHandler(FileCreatedHandler);
+ }
+
+ private string inputValue;
+
+ private string outputValue;
+
+ private XmlWriter writer;
+
+ private Dictionary<string, XmlWriter> writers = new Dictionary<string, XmlWriter>();
+
+ private void FileCreatedHandler (Object o, EventArgs e) {
+ FileCreatedEventArgs fe = e as FileCreatedEventArgs;
+ if (fe == null) return;
+
+ string path = Path.Combine(fe.HxfPath, outputValue).ToLower();
+
+ XmlWriter tempWriter;
+ if (!writers.TryGetValue(path, out tempWriter)) {
+ if (writer != null) {
+ writer.WriteEndDocument();
+ writer.Close();
+ }
+ WriteFile(path);
+ }
+
+ WriteFileElement(fe.FilePath);
+
+ }
+
+ private void WriteFileElement (string url) {
+ writer.WriteStartElement("File");
+ writer.WriteAttributeString("Url", url);
+ writer.WriteEndElement();
+ }
+
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ writer.WriteEndDocument();
+ writer.Close();
+ }
+ base.Dispose(disposing);
+ }
+
+ public void WriteFile(string path) {
+ XmlWriterSettings writerSettings = new XmlWriterSettings();
+ writerSettings.Indent = true;
+ writer = XmlWriter.Create(path);
+ writer.WriteStartDocument();
+ writer.WriteStartElement("HelpFileList");
+ writer.WriteAttributeString("DTDVersion", "1.0");
+
+ // use the input to seed the output
+ if (!String.IsNullOrEmpty(inputValue)) {
+
+ try {
+ TextReader reader = File.OpenText(inputValue);
+
+ try {
+ while (true) {
+ string line = reader.ReadLine();
+ if (line == null) break;
+ WriteFileElement(line);
+ }
+ }
+ finally {
+ reader.Close();
+ }
+ }
+ catch (IOException ex) {
+ WriteMessage(MessageLevel.Error, String.Format("An access error occured while attempting to copy the input HxF data. The error message is:", ex.Message));
+ }
+ }
+
+ writers.Add(path, writer);
+ }
+
+ // don't do anything for individual files
+ public override void Apply (XmlDocument document, string key) {}
+
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/IfThenComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/IfThenComponent.cs
new file mode 100644
index 0000000..e44c0f2
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/IfThenComponent.cs
@@ -0,0 +1,87 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+using System.Reflection;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class IfThenComponent : BuildComponent {
+
+ private XPathExpression condition;
+
+ private IEnumerable<BuildComponent> true_branch = new List<BuildComponent>();
+
+ private IEnumerable<BuildComponent> false_branch = new List<BuildComponent>();
+
+ public IfThenComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ // get the condition
+ XPathNavigator if_node = configuration.SelectSingleNode("if");
+ if (if_node == null) throw new ConfigurationErrorsException("You must specify a condition using the <if> element.");
+ string condition_xpath = if_node.GetAttribute("condition", String.Empty);
+ if (String.IsNullOrEmpty(condition_xpath)) throw new ConfigurationErrorsException();
+ condition = XPathExpression.Compile(condition_xpath);
+
+ // construct the true branch
+ XPathNavigator then_node = configuration.SelectSingleNode("then");
+ if (then_node != null) true_branch = BuildAssembler.LoadComponents(then_node);
+
+ // construct the false branch
+ XPathNavigator else_node = configuration.SelectSingleNode("else");
+ if (else_node != null) false_branch = BuildAssembler.LoadComponents(else_node);
+
+ // keep a pointer to the context for future use
+ context = assembler.Context;
+
+ }
+
+ private BuildContext context;
+
+ public override void Apply (XmlDocument document, string key) {
+
+ // set up the test
+ context["key"] = key;
+ XPathExpression test = condition.Clone();
+ test.SetContext(context.XsltContext);
+
+ // evaluate the condition
+ bool result = (bool) document.CreateNavigator().Evaluate(test);
+
+ // on the basis of the condition, execute either the true or the false branch
+ if (result) {
+ foreach (BuildComponent component in true_branch) {
+ component.Apply(document, key);
+ }
+ } else {
+ foreach (BuildComponent component in false_branch) {
+ component.Apply(document, key);
+ }
+ }
+
+ }
+
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ foreach (BuildComponent component in true_branch) {
+ component.Dispose();
+ }
+ foreach (BuildComponent component in false_branch) {
+ component.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ }
+
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/IndexedFileCache.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/IndexedFileCache.cs
new file mode 100644
index 0000000..3fadba3
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/IndexedFileCache.cs
@@ -0,0 +1,192 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools
+{
+ // the storage system
+
+ internal class IndexedFileCache
+ {
+
+ public IndexedFileCache(string keyXPath, string valueXPath, int cacheSize)
+ {
+ valueExpression = XPathExpression.Compile(valueXPath);
+
+ keyExpression = XPathExpression.Compile(keyXPath);
+
+ _cacheSize = cacheSize;
+
+ cache = new Dictionary<string, IndexedFile>(_cacheSize);
+
+ lruLinkedList = new LinkedList<string>();
+ }
+
+ // search pattern for value nodes to be mapped
+ private XPathExpression valueExpression;
+
+ // search pattern for the key identifier (relative to the value node)
+ private XPathExpression keyExpression;
+
+ // an index mapping topic IDs to files
+ private Dictionary<string, string> idToFileMap = new Dictionary<string, string>();
+
+ public int ParseDocuments(string wildcardPath)
+ {
+ string directoryPart = Path.GetDirectoryName(wildcardPath);
+ if (String.IsNullOrEmpty(directoryPart)) directoryPart = Environment.CurrentDirectory;
+ directoryPart = Path.GetFullPath(directoryPart);
+ string filePart = Path.GetFileName(wildcardPath);
+ string[] files = Directory.GetFiles(directoryPart, filePart);
+ // WriteMessage(MessageLevel.Info, String.Format("Found {0} files.", files.Length) );
+ foreach (string file in files)
+ {
+ ParseDocument(file);
+ }
+ return (files.Length);
+ }
+
+ private void ParseDocument(string file)
+ {
+ try
+ {
+ XPathDocument document = new XPathDocument(file);
+ XPathNodeIterator valueNodes = document.CreateNavigator().Select(valueExpression);
+ foreach (XPathNavigator valueNode in valueNodes)
+ {
+ XPathNavigator keyNode = valueNode.SelectSingleNode(keyExpression);
+ if (keyNode == null) continue;
+ string key = keyNode.Value;
+
+ // log multiple occurences of a single id
+ if (idToFileMap.ContainsKey(key))
+ {
+ // WriteMessage(MessageLevel.Warn, String.Format("Entries for the key '{0}' occur in both '{1}' and '{2}'. The first entry will be used.", key, idToFileMap[key], file));
+ }
+ else
+ {
+ idToFileMap[key] = file;
+ }
+ }
+ }
+ catch (XmlException)
+ {
+ // WriteMessage(MessageLevel.Error, e.Message);
+ }
+ }
+
+ // a simple document caching mechanism
+
+ private int _cacheSize = 10;
+
+ private LinkedList<String> lruLinkedList;
+
+ private Dictionary<string, IndexedFile> cache;
+
+
+ private IndexedFile GetCachedDocument(string identifier)
+ {
+ string file;
+ if (idToFileMap.TryGetValue(identifier, out file))
+ {
+ IndexedFile document;
+ if (cache.TryGetValue(file, out document))
+ {
+ // move the file from its current position to the head of the lru linked list
+ lruLinkedList.Remove(document.ListNode);
+ lruLinkedList.AddFirst(document.ListNode);
+ }
+ else
+ {
+ // not in the cache, so load and index a new source file
+ document = new IndexedFile(file, valueExpression, keyExpression);
+ if (cache.Count >= _cacheSize)
+ {
+ // the cache is full
+ // the last node in the linked list has the path of the next file to remove from the cache
+ if (lruLinkedList.Last != null)
+ {
+ cache.Remove(lruLinkedList.Last.Value);
+ lruLinkedList.RemoveLast();
+ }
+ }
+ // add the new file to the cache and to the head of the lru linked list
+ cache.Add(file, document);
+ document.ListNode = lruLinkedList.AddFirst(file);
+ }
+ return (document);
+ }
+ else
+ {
+ return (null);
+ }
+ }
+
+ public XPathNavigator GetContent(string identifier)
+ {
+
+ // get the document containing the identifier
+ IndexedFile document = GetCachedDocument(identifier);
+ if (document == null) return (null);
+
+ // select the comment part of the document
+ return document.GetContent(identifier);
+ }
+
+ public int Count
+ {
+ get
+ {
+ return (idToFileMap.Count);
+ }
+ }
+
+ }
+
+ internal class IndexedFile
+ {
+ Dictionary<string, XPathNavigator> valueIndex = new Dictionary<string, XPathNavigator>();
+
+ public IndexedFile(string filepath, XPathExpression valueExpression, XPathExpression keyExpression)
+ {
+ XPathDocument xpDoc = new XPathDocument(filepath);
+ XPathNodeIterator valueNodes = xpDoc.CreateNavigator().Select(valueExpression);
+ foreach (XPathNavigator valueNode in valueNodes)
+ {
+ XPathNavigator keyNode = valueNode.SelectSingleNode(keyExpression);
+ if (keyNode == null)
+ continue;
+ string key = keyNode.Value;
+ if (!valueIndex.ContainsKey(key))
+ valueIndex.Add(key, valueNode);
+ }
+ }
+
+ public XPathNavigator GetContent(string key)
+ {
+ return valueIndex[key];
+ }
+
+ private LinkedListNode<string> listNode;
+ public LinkedListNode<string> ListNode
+ {
+ get
+ {
+ return (listNode);
+ }
+ set
+ {
+ listNode = value;
+ }
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/IntellisenseComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/IntellisenseComponent.cs
new file mode 100644
index 0000000..1fd72a8
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/IntellisenseComponent.cs
@@ -0,0 +1,338 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class IntellisenseComponent : BuildComponent {
+
+ public IntellisenseComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ XPathNavigator output_node = configuration.SelectSingleNode("output");
+ if (output_node != null) {
+
+ string directory_value = output_node.GetAttribute("directory", String.Empty);
+ if (!String.IsNullOrEmpty(directory_value)) {
+ directory = Environment.ExpandEnvironmentVariables(directory_value);
+ if (!Directory.Exists(directory)) WriteMessage(MessageLevel.Error, String.Format("The output directory '{0}' does not exist.", directory));
+ }
+ }
+
+ // a way to get additional information into the intellisense file
+ XPathNodeIterator input_nodes = configuration.Select("input");
+ foreach (XPathNavigator input_node in input_nodes) {
+ string file_value = input_node.GetAttribute("file", String.Empty);
+ if (!String.IsNullOrEmpty(file_value)) {
+ string file = Environment.ExpandEnvironmentVariables(file_value);
+ ReadInputFile(file);
+ }
+ }
+
+ context.AddNamespace("ddue", "http://ddue.schemas.microsoft.com/authoring/2003/5");
+
+ summaryExpression.SetContext(context);
+ memberSummaryExpression.SetContext(context);
+ returnsExpression.SetContext(context);
+ parametersExpression.SetContext(context);
+ parameterNameExpression.SetContext(context);
+ templatesExpression.SetContext(context);
+ templateNameExpression.SetContext(context);
+ exceptionExpression.SetContext(context);
+ exceptionCrefExpression.SetContext(context);
+ }
+
+ // input content store
+
+ private void ReadInputFile (string file) {
+ try {
+ XPathDocument document = new XPathDocument(file);
+
+ XPathNodeIterator member_nodes = document.CreateNavigator().Select("/metadata/topic[@id]");
+ foreach (XPathNavigator member_node in member_nodes) {
+ string id = member_node.GetAttribute("id", String.Empty);
+ content[id] = member_node.Clone();
+ }
+
+ WriteMessage(MessageLevel.Info, String.Format("Read {0} input content nodes.", member_nodes.Count));
+
+ } catch (XmlException e) {
+ WriteMessage(MessageLevel.Error, String.Format("The input file '{0}' is not a well-formed XML file. The error message is: {1}", file, e.Message));
+ } catch (IOException e) {
+ WriteMessage(MessageLevel.Error, String.Format("An error occured while attempting to access the fileThe input file '{0}'. The error message is: {1}", file, e.Message));
+ }
+
+
+ }
+ private Dictionary<string, XPathNavigator> content = new Dictionary<string, XPathNavigator>();
+
+ // the action of the component
+
+ public override void Apply (XmlDocument document, string id) {
+
+ // only generate intellisense if id corresponds to an allowed intellisense ID
+ if (id.Length < 2) return;
+ if (id[1] != ':') return;
+ if (!((id[0] == 'T') || (id[0] == 'M') || (id[0] == 'P') || (id[0] == 'F') || (id[0] == 'E') || (id[0] == 'N'))) return;
+
+ XPathNavigator root = document.CreateNavigator().SelectSingleNode("/document/comments");
+
+ string assembly;
+
+ if ((string)root.Evaluate(groupExpression) == "namespace") {
+ // get the assembly for the namespace
+ //assembly = (string) root.Evaluate(namespaceAssemblyExpression);
+ // Assign general name for namespace assemblies since they do not belong to any specific assembly
+ assembly = "namespaces";
+ } else {
+ // get the assembly for the API
+ assembly = (string) root.Evaluate(assemblyExpression);
+ }
+
+ if (String.IsNullOrEmpty(assembly)) return;
+
+ // try/catch block for capturing errors
+ try {
+
+ // get the writer for the assembly
+ XmlWriter writer;
+ if (!writers.TryGetValue(assembly, out writer)) {
+
+ // create a writer for the assembly
+ string name = Path.Combine(directory, assembly + ".xml");
+ // Console.WriteLine("creating {0}", name);
+
+ XmlWriterSettings settings = new XmlWriterSettings();
+ settings.Indent = true;
+
+ try {
+ writer = XmlWriter.Create(name, settings);
+ } catch (IOException e) {
+ WriteMessage(MessageLevel.Error, String.Format("An access error occured while attempting to create the intellisense output file '{0}'. The error message is: {1}", name, e.Message));
+ }
+
+
+ writers.Add(assembly, writer);
+
+ // write out the initial data
+ writer.WriteStartDocument();
+ writer.WriteStartElement("doc");
+ //do not generate assembly nodes for namespace topics
+ if ((string)root.Evaluate(groupExpression) != "namespace")
+ {
+ writer.WriteStartElement("assembly");
+ writer.WriteElementString("name", assembly);
+ writer.WriteEndElement();
+ }
+ writer.WriteStartElement("members");
+ }
+
+ writer.WriteStartElement("member");
+ writer.WriteAttributeString("name", id);
+
+ // summary
+ WriteSummary(root, summaryExpression, writer);
+
+ // return value
+ XPathNavigator returns = root.SelectSingleNode(returnsExpression);
+ if (returns != null) {
+ writer.WriteStartElement("returns");
+
+ XmlReader reader = returns.ReadSubtree();
+ CopyContent(reader, writer);
+ reader.Close();
+
+ writer.WriteEndElement();
+ }
+
+ // parameters
+ XPathNodeIterator parameters = root.Select(parametersExpression);
+ foreach (XPathNavigator parameter in parameters) {
+
+ string name = (string)parameter.Evaluate(parameterNameExpression);
+
+ XmlReader reader = parameter.ReadSubtree();
+
+ writer.WriteStartElement("param");
+ writer.WriteAttributeString("name", name);
+ CopyContent(reader, writer);
+ writer.WriteEndElement();
+
+ reader.Close();
+ }
+
+ // templates
+ XPathNodeIterator templates = root.Select(templatesExpression);
+ foreach (XPathNavigator template in templates) {
+
+ string name = (string)template.Evaluate(templateNameExpression);
+
+ XmlReader reader = template.ReadSubtree();
+
+ writer.WriteStartElement("typeparam");
+ writer.WriteAttributeString("name", name);
+ CopyContent(reader, writer);
+ writer.WriteEndElement();
+
+ reader.Close();
+ }
+
+ // exceptions
+ XPathNodeIterator exceptions = root.Select(exceptionExpression);
+ foreach (XPathNavigator exception in exceptions) {
+
+ string exceptionCref = (string)exception.Evaluate(exceptionCrefExpression);
+
+ XmlReader reader = exception.ReadSubtree();
+
+ writer.WriteStartElement("exception");
+ writer.WriteAttributeString("cref", exceptionCref);
+ CopyContent(reader, writer);
+ writer.WriteEndElement();
+
+ reader.Close();
+ }
+
+ // stored contents
+ XPathNavigator input;
+ if (content.TryGetValue(id, out input)) {
+ XPathNodeIterator input_nodes = input.SelectChildren(XPathNodeType.Element);
+ foreach (XPathNavigator input_node in input_nodes) {
+ input_node.WriteSubtree(writer);
+ }
+ }
+
+ writer.WriteFullEndElement();
+
+ // enumeration members
+ string subgroup = (string)root.Evaluate(subgroupExpression);
+ if (subgroup == "enumeration") {
+
+ XPathNodeIterator elements = (XPathNodeIterator)root.Evaluate(elementsExpression);
+ foreach (XPathNavigator element in elements) {
+
+ string api = (string)element.GetAttribute("api", string.Empty);
+ writer.WriteStartElement("member");
+ writer.WriteAttributeString("name", api);
+
+ //summary
+ WriteSummary(element, memberSummaryExpression, writer);
+
+ writer.WriteFullEndElement();
+ }
+ }
+
+
+ } catch (IOException e) {
+ WriteMessage(MessageLevel.Error, String.Format("An access error occured while attempting to write intellisense data. The error message is: {0}", e.Message));
+ } catch (XmlException e) {
+ WriteMessage(MessageLevel.Error, String.Format("Intellisense data was not valid XML. The error message is: {0}", e.Message));
+ }
+
+ }
+
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ foreach (XmlWriter writer in writers.Values) {
+ writer.WriteEndDocument();
+ writer.Close();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ private void WriteSummary(XPathNavigator node, XPathExpression expression, XmlWriter writer) {
+ XPathNavigator summary = node.SelectSingleNode(expression);
+ if (summary != null) {
+ writer.WriteStartElement("summary");
+
+ XmlReader reader = summary.ReadSubtree();
+ CopyContent(reader, writer);
+ reader.Close();
+
+ writer.WriteEndElement();
+ }
+ else {
+ // Console.WriteLine("no summary");
+ }
+ }
+
+ private void CopyContent (XmlReader reader, XmlWriter writer) {
+ reader.MoveToContent();
+ while (true) {
+
+ //Console.WriteLine("{0} {1}", reader.ReadState, reader.NodeType);
+
+ if (reader.NodeType == XmlNodeType.Text) {
+ writer.WriteString(reader.ReadString());
+ } else if (reader.NodeType == XmlNodeType.Element) {
+ //Console.WriteLine(reader.LocalName);
+ if (reader.LocalName == "codeEntityReference") {
+ writer.WriteStartElement("see");
+ writer.WriteAttributeString("cref", reader.ReadElementString());
+ writer.WriteEndElement();
+ } else if (reader.LocalName == "parameterReference") {
+ writer.WriteStartElement("paramref");
+ writer.WriteAttributeString("name", reader.ReadElementString());
+ writer.WriteEndElement();
+ } else if (reader.LocalName == "link") {
+ string displayText = reader.ReadElementString();
+ if (displayText.StartsWith("GTMT#")) {
+ writer.WriteString(displayText.Substring(displayText.IndexOf("#") + 1));
+ } else {
+ writer.WriteString(displayText);
+ }
+ } else {
+ reader.Read();
+ }
+ } else {
+ if (!reader.Read()) break;
+ }
+
+ }
+
+ }
+
+ private string directory = String.Empty;
+
+ private Dictionary<string,XmlWriter> writers = new Dictionary<string,XmlWriter>();
+
+ private XPathExpression assemblyExpression = XPathExpression.Compile("string(/document/reference/containers/library/@assembly)");
+
+ private XPathExpression namespaceAssemblyExpression = XPathExpression.Compile("string(/document/reference/elements/element/containers/library/@assembly)");
+
+ private XPathExpression summaryExpression = XPathExpression.Compile("ddue:dduexml/ddue:summary");
+
+ private XPathExpression returnsExpression = XPathExpression.Compile("ddue:dduexml/ddue:returnValue");
+
+ private XPathExpression parametersExpression = XPathExpression.Compile("ddue:dduexml/ddue:parameters/ddue:parameter/ddue:content");
+
+ private XPathExpression parameterNameExpression = XPathExpression.Compile("string(../ddue:parameterReference)");
+
+ private XPathExpression templatesExpression = XPathExpression.Compile("ddue:dduexml/ddue:genericParameters/ddue:genericParameter/ddue:content");
+
+ private XPathExpression templateNameExpression = XPathExpression.Compile("string(../ddue:parameterReference)");
+
+ private XPathExpression exceptionExpression = XPathExpression.Compile("ddue:dduexml/ddue:exceptions/ddue:exception/ddue:content");
+
+ private XPathExpression exceptionCrefExpression = XPathExpression.Compile("string(../ddue:codeEntityReference)");
+
+ private XPathExpression subgroupExpression = XPathExpression.Compile("string(/document/reference/apidata/@subgroup)");
+
+ private XPathExpression groupExpression = XPathExpression.Compile("string(/document/reference/apidata/@group)");
+
+ private XPathExpression elementsExpression = XPathExpression.Compile("/document/reference/elements/element");
+
+ private XPathExpression memberSummaryExpression = XPathExpression.Compile("ddue:summary");
+
+ private XmlNamespaceManager context = new CustomContext();
+
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/IntellisenseComponent2.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/IntellisenseComponent2.cs
new file mode 100644
index 0000000..3405ddb
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/IntellisenseComponent2.cs
@@ -0,0 +1,424 @@
+// 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.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class IntellisenseComponent2 : BuildComponent {
+
+ public IntellisenseComponent2 (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ XPathNavigator output_node = configuration.SelectSingleNode("output");
+ if (output_node != null) {
+
+ string directory_value = output_node.GetAttribute("directory", String.Empty);
+ if (!String.IsNullOrEmpty(directory_value)) {
+ directory = Environment.ExpandEnvironmentVariables(directory_value);
+ if (!Directory.Exists(directory)) WriteMessage(MessageLevel.Error, String.Format("The output directory '{0}' does not exist.", directory));
+ }
+ }
+
+ XPathNavigator expression_node = configuration.SelectSingleNode("expressions");
+ if (expression_node != null) {
+
+ string root = expression_node.GetAttribute("root", string.Empty);
+ try {
+ rootExpression = XPathExpression.Compile(root);
+ } catch (XPathException) {
+ WriteMessage(MessageLevel.Error, String.Format("The expression '{0}' is not a valid XPath expression.", root));
+ }
+
+ string assembly = expression_node.GetAttribute("assembly", string.Empty);
+ try {
+ assemblyExpression = XPathExpression.Compile(assembly);
+ } catch (XPathException) {
+ WriteMessage(MessageLevel.Error, String.Format("The expression '{0}' is not a valid XPath expression.", assembly));
+ }
+
+ string summary = expression_node.GetAttribute("summary", string.Empty);
+ try {
+ summaryExpression = XPathExpression.Compile(summary);
+ } catch (XPathException) {
+ WriteMessage(MessageLevel.Error, String.Format("The expression '{0}' is not a valid XPath expression.", summary));
+ }
+
+ string parameters = expression_node.GetAttribute("parameters", string.Empty);
+ try {
+ parametersExpression = XPathExpression.Compile(parameters);
+ } catch (XPathException) {
+ WriteMessage(MessageLevel.Error, String.Format("The expression '{0}' is not a valid XPath expression.", parameters));
+ }
+
+ string parameterContent = expression_node.GetAttribute("parameterContent", string.Empty);
+ try {
+ parameterContentExpression = XPathExpression.Compile(parameterContent);
+ } catch (XPathException ) {
+ WriteMessage(MessageLevel.Error, String.Format("The expression '{0}' is not a valid XPath expression.", parameterContent));
+ }
+
+ string templates = expression_node.GetAttribute("templates", string.Empty);
+ try {
+ templatesExpression = XPathExpression.Compile(templates);
+ } catch (XPathException) {
+ WriteMessage(MessageLevel.Error, String.Format("The expression '{0}' is not a valid XPath expression.", templates));
+ }
+
+ string templateContent = expression_node.GetAttribute("templateContent", string.Empty);
+ try {
+ templateContentExpression = XPathExpression.Compile(templateContent);
+ } catch (XPathException) {
+ WriteMessage(MessageLevel.Error, String.Format("The expression '{0}' is not a valid XPath expression.", templateContent));
+ }
+
+ string returns = expression_node.GetAttribute("returns", string.Empty);
+ try {
+ returnsExpression = XPathExpression.Compile(returns);
+ } catch (XPathException) {
+ WriteMessage(MessageLevel.Error, String.Format("The expression '{0}' is not a valid XPath expression.", returns));
+ }
+
+ string exception = expression_node.GetAttribute("exception", string.Empty);
+ try {
+ exceptionExpression = XPathExpression.Compile(exception);
+ } catch (XPathException) {
+ WriteMessage(MessageLevel.Error, String.Format("The expression '{0}' is not a valid XPath expression.", exception));
+ }
+
+ string exceptionCref = expression_node.GetAttribute("exceptionCref", string.Empty);
+ try {
+ exceptionCrefExpression = XPathExpression.Compile(exceptionCref);
+ } catch (XPathException) {
+ WriteMessage(MessageLevel.Error, String.Format("The expression '{0}' is not a valid XPath expression.", exceptionCref));
+ }
+
+ string enumeration = expression_node.GetAttribute("enumeration", string.Empty);
+ try {
+ enumerationExpression = XPathExpression.Compile(enumeration);
+ } catch (XPathException) {
+ WriteMessage(MessageLevel.Error, String.Format("The expression '{0}' is not a valid XPath expression.", enumeration));
+ }
+
+ string enumerationApi = expression_node.GetAttribute("enumerationApi", string.Empty);
+ try {
+ enumerationApiExpression = XPathExpression.Compile(enumerationApi);
+ } catch (XPathException) {
+ WriteMessage(MessageLevel.Error, String.Format("The expression '{0}' is not a valid XPath expression.", enumerationApi));
+ }
+
+ string memberSummary = expression_node.GetAttribute("memberSummary", string.Empty);
+ try {
+ memberSummaryExpression = XPathExpression.Compile(memberSummary);
+ } catch (XPathException) {
+ WriteMessage(MessageLevel.Error, String.Format("The expression '{0}' is not a valid XPath expression.", memberSummary));
+ }
+
+ }
+
+ // a way to get additional information into the intellisense file
+ XPathNodeIterator input_nodes = configuration.Select("input");
+ foreach (XPathNavigator input_node in input_nodes) {
+ string file_value = input_node.GetAttribute("file", String.Empty);
+ if (!String.IsNullOrEmpty(file_value)) {
+ string file = Environment.ExpandEnvironmentVariables(file_value);
+ ReadInputFile(file);
+ }
+ }
+ }
+
+ // input content store
+
+ private void ReadInputFile (string file) {
+ try {
+ XPathDocument document = new XPathDocument(file);
+
+ XPathNodeIterator member_nodes = document.CreateNavigator().Select("/metadata/topic[@id]");
+ foreach (XPathNavigator member_node in member_nodes) {
+ string id = member_node.GetAttribute("id", String.Empty);
+ content[id] = member_node.Clone();
+ }
+
+ WriteMessage(MessageLevel.Info, String.Format("Read {0} input content nodes.", member_nodes.Count));
+
+ } catch (XmlException e) {
+ WriteMessage(MessageLevel.Error, String.Format("The input file '{0}' is not a well-formed XML file. The error message is: {1}", file, e.Message));
+ } catch (IOException e) {
+ WriteMessage(MessageLevel.Error, String.Format("An error occured while attempting to access the fileThe input file '{0}'. The error message is: {1}", file, e.Message));
+ }
+
+
+ }
+ private Dictionary<string, XPathNavigator> content = new Dictionary<string, XPathNavigator>();
+
+ // the action of the component
+
+ public override void Apply (XmlDocument document, string id) {
+
+ // only generate intellisense if id corresponds to an allowed intellisense ID
+ if (id.Length < 2) return;
+ if (id[1] != ':') return;
+ if (!((id[0] == 'T') || (id[0] == 'M') || (id[0] == 'P') || (id[0] == 'F') || (id[0] == 'E') || (id[0] == 'N'))) return;
+
+ XPathNavigator root = document.CreateNavigator().SelectSingleNode(rootExpression);
+
+ // get the assembly information
+ string assembly = (string) root.Evaluate(assemblyExpression);
+
+ if (String.IsNullOrEmpty(assembly)) {
+ assembly = "namespaces";
+ }
+
+ // try/catch block for capturing errors
+ try {
+
+ // get the writer for the assembly
+ XmlWriter writer;
+ if (!writers.TryGetValue(assembly, out writer)) {
+
+ // create a writer for the assembly
+ string name = Path.Combine(directory, assembly + ".xml");
+ // Console.WriteLine("creating {0}", name);
+
+ XmlWriterSettings settings = new XmlWriterSettings();
+ settings.Indent = true;
+
+ try {
+ writer = XmlWriter.Create(name, settings);
+ } catch (IOException e) {
+ WriteMessage(MessageLevel.Error, String.Format("An access error occured while attempting to create the intellisense output file '{0}'. The error message is: {1}", name, e.Message));
+ }
+
+ writers.Add(assembly, writer);
+
+ // write out the initial data
+ writer.WriteStartDocument();
+ writer.WriteStartElement("doc");
+ //do not generate assembly nodes for namespace topics
+ if (assembly != "namespaces")
+ {
+ writer.WriteStartElement("assembly");
+ writer.WriteElementString("name", assembly);
+ writer.WriteEndElement();
+ }
+ writer.WriteStartElement("members");
+ }
+
+ writer.WriteStartElement("member");
+ writer.WriteAttributeString("name", id);
+
+ // summary
+ WriteSummary(root, summaryExpression, writer);
+
+ // return value
+ XPathNavigator returns = root.SelectSingleNode(returnsExpression);
+ if (returns != null) {
+ writer.WriteStartElement("returns");
+ XmlReader reader = returns.ReadSubtree();
+
+ CopyContent(reader, writer);
+ reader.Close();
+
+ writer.WriteEndElement();
+ }
+
+ // parameters
+ XPathNodeIterator parameters = root.Select(parametersExpression);
+ foreach (XPathNavigator parameter in parameters) {
+
+ string name = (string)parameter.GetAttribute("paramName", string.Empty);
+
+ XPathNavigator parameterContent = parameter.SelectSingleNode(parameterContentExpression);
+
+ if (parameterContent == null) continue;
+
+ XmlReader reader = parameterContent.ReadSubtree();
+
+ writer.WriteStartElement("param");
+ writer.WriteAttributeString("name", name);
+ CopyContent(reader, writer);
+ writer.WriteFullEndElement();
+
+ reader.Close();
+ }
+
+ // templates
+ XPathNodeIterator templates = root.Select(templatesExpression);
+ foreach (XPathNavigator template in templates) {
+
+ string name = (string)template.GetAttribute("paramName", string.Empty);
+
+ XPathNavigator templateContent = template.SelectSingleNode(templateContentExpression);
+
+ if (templateContent == null) continue;
+
+ XmlReader reader = templateContent.ReadSubtree();
+
+ writer.WriteStartElement("typeparam");
+ writer.WriteAttributeString("name", name);
+ CopyContent(reader, writer);
+ writer.WriteFullEndElement();
+
+ reader.Close();
+ }
+
+ // exceptions
+ XPathNodeIterator exceptions = root.Select(exceptionExpression);
+ foreach (XPathNavigator exception in exceptions) {
+
+ XPathNavigator exceptionCref = exception.SelectSingleNode(exceptionCrefExpression);
+
+ if (exceptionCref == null) continue;
+
+ string cref = exceptionCref.GetAttribute("target", string.Empty);
+ XmlReader reader = exception.ReadSubtree();
+
+ writer.WriteStartElement("exception");
+ writer.WriteAttributeString("cref", cref);
+ CopyContent(reader, writer);
+ writer.WriteFullEndElement();
+
+ reader.Close();
+ }
+
+ // stored contents
+ XPathNavigator input;
+ if (content.TryGetValue(id, out input)) {
+ XPathNodeIterator input_nodes = input.SelectChildren(XPathNodeType.Element);
+ foreach (XPathNavigator input_node in input_nodes) {
+ input_node.WriteSubtree(writer);
+ }
+ }
+
+ writer.WriteFullEndElement();
+
+ // enumeration members
+ XPathNodeIterator enumerationIterator = root.Select(enumerationExpression);
+
+ foreach (XPathNavigator enumeration in enumerationIterator) {
+
+ XPathNavigator enumApi = enumeration.SelectSingleNode(enumerationApiExpression);
+
+ if (enumApi == null) continue;
+
+ string api = (string)enumApi.GetAttribute("target", string.Empty);
+ writer.WriteStartElement("member");
+ writer.WriteAttributeString("name", api);
+
+ //summary
+ WriteSummary(enumeration, memberSummaryExpression, writer);
+
+ writer.WriteFullEndElement();
+ }
+ } catch (IOException e) {
+ WriteMessage(MessageLevel.Error, String.Format("An access error occured while attempting to write intellisense data. The error message is: {0}", e.Message));
+ } catch (XmlException e) {
+ WriteMessage(MessageLevel.Error, String.Format("Intellisense data was not valid XML. The error message is: {0}", e.Message));
+ }
+
+ }
+
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ foreach (XmlWriter writer in writers.Values) {
+ writer.WriteEndDocument();
+ writer.Close();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ private void WriteSummary(XPathNavigator node, XPathExpression expression, XmlWriter writer) {
+
+ XPathNavigator summary = node.SelectSingleNode(expression);
+ if (summary != null) {
+ writer.WriteStartElement("summary");
+
+ XmlReader reader = summary.ReadSubtree();
+
+ CopyContent(reader, writer);
+ reader.Close();
+
+ writer.WriteEndElement();
+ } else {
+ // Console.WriteLine("no summary");
+ }
+ }
+
+ private void CopyContent (XmlReader reader, XmlWriter writer) {
+ reader.MoveToContent();
+ while (true) {
+
+ if (reader.NodeType == XmlNodeType.Text) {
+ writer.WriteString(reader.ReadString());
+ } else if (reader.NodeType == XmlNodeType.Element) {
+ if (reader.LocalName == "span" && (reader.GetAttribute("sdata",string.Empty) == "cer")) {
+ writer.WriteStartElement("see");
+ writer.WriteAttributeString("cref", reader.GetAttribute("target", string.Empty));
+ writer.WriteEndElement();
+ reader.Skip();
+ }
+ else if (reader.LocalName == "span" && (reader.GetAttribute("sdata", string.Empty) == "paramReference"))
+ {
+ writer.WriteStartElement("paramref");
+ writer.WriteAttributeString("name", reader.ReadElementString());
+ writer.WriteEndElement();
+ } else if (reader.LocalName == "span" && (reader.GetAttribute("sdata",string.Empty) == "link")) {
+ writer.WriteString(reader.ReadElementString());
+ }
+ else if (reader.LocalName == "span" && (reader.GetAttribute("sdata", string.Empty) == "langKeyword"))
+ {
+ string keyword = reader.GetAttribute("value", string.Empty);
+ writer.WriteString(keyword);
+ reader.Skip();
+ }
+ else {
+ reader.Read();
+ }
+ } else {
+ if (!reader.Read()) break;
+ }
+
+ }
+
+ }
+
+ private string directory = String.Empty;
+
+ private Dictionary<string,XmlWriter> writers = new Dictionary<string,XmlWriter>();
+
+ private XPathExpression rootExpression;
+
+ private XPathExpression assemblyExpression;
+
+ private XPathExpression summaryExpression;
+
+ private XPathExpression parametersExpression;
+
+ private XPathExpression parameterContentExpression;
+
+ private XPathExpression templatesExpression;
+
+ private XPathExpression templateContentExpression;
+
+ private XPathExpression returnsExpression;
+
+ private XPathExpression exceptionExpression;
+
+ private XPathExpression exceptionCrefExpression;
+
+ private XPathExpression enumerationExpression;
+
+ private XPathExpression enumerationApiExpression;
+
+ private XPathExpression memberSummaryExpression;
+
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/LiveExampleComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/LiveExampleComponent.cs
new file mode 100644
index 0000000..43d76ba
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/LiveExampleComponent.cs
@@ -0,0 +1,195 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml;
+using System.Xml.XPath;
+
+
+namespace Microsoft.Ddue.Tools {
+
+ /// <summary>
+ /// The LiveExampleComponent replaces ddue:CodeReference elements with links to runnable code samples,
+ /// if the type is "run" or "view". All other kinds of code samples are passed through to the
+ /// standard example component, except that the type prefix is removed. A Parsnip "approval" file can
+ /// be used to omit code samples that did not pass validation, or to replace broken samples with a message
+ /// to that effect.
+ /// </summary>
+ public class LiveExampleComponent : BuildComponent {
+
+ readonly string wdxNamespace = "http://temp.uri/wdx";
+ readonly string wdxPrefix = "wdx";
+
+ XPathExpression selector;
+ XmlNamespaceManager context;
+
+ bool omitBadExamples;
+ //bool runBadExamples;
+
+ Dictionary<string, SampleInfo> sampleInfoTable;
+
+ public LiveExampleComponent(BuildAssembler assembler, XPathNavigator configuration)
+ : base(assembler, configuration) {
+
+ XPathNavigator parsnip_node = configuration.SelectSingleNode("parsnip");
+ string approvedFile = null;
+ if (parsnip_node != null) {
+ approvedFile = parsnip_node.GetAttribute("approved-file", String.Empty);
+
+ string omitBadExamplesValue = parsnip_node.GetAttribute("omit-bad-examples", String.Empty);
+ if (!string.IsNullOrEmpty(omitBadExamplesValue))
+ omitBadExamples = Boolean.Parse(omitBadExamplesValue);
+
+ //string runBadExamplesValue = parsnip_node.GetAttribute("run-bad-examples", String.Empty);
+ //if (!string.IsNullOrEmpty(runBadExamplesValue))
+ // runBadExamples = Boolean.Parse(runBadExamplesValue);
+ }
+
+ if (string.IsNullOrEmpty(approvedFile))
+ WriteMessage(MessageLevel.Warn, "No approved samples file specified; all available samples will be included.");
+ else
+ LoadApprovedFile(approvedFile);
+
+ context = new CustomContext();
+ context.AddNamespace("ddue", "http://ddue.schemas.microsoft.com/authoring/2003/5");
+
+ selector = XPathExpression.Compile("//ddue:codeReference");
+ selector.SetContext(context);
+ }
+
+ static XPathNavigator[] ConvertIteratorToArray(XPathNodeIterator iterator) {
+ XPathNavigator[] result = new XPathNavigator[iterator.Count];
+ for (int i = 0; i < result.Length; i++) {
+ iterator.MoveNext();
+ result[i] = iterator.Current.Clone();
+ }
+ return (result);
+ }
+
+ public override void Apply(XmlDocument document, string key) {
+ XPathNodeIterator nodesIterator = document.CreateNavigator().Select(selector);
+ XPathNavigator[] nodes = ConvertIteratorToArray(nodesIterator);
+
+ foreach (XPathNavigator node in nodes) {
+ CodeReference cref = new CodeReference(node.Value);
+
+ SampleInfo si = null;
+ if (sampleInfoTable != null && cref.ExampleName != null)
+ sampleInfoTable.TryGetValue(cref.ExampleName, out si);
+
+ WriteMessage(MessageLevel.Info, string.Format("*** codeReference={0}; approved={1}; type={2}",
+ node.Value, (si == null) ? false : si.IsApproved("CS"), cref.Type));
+
+
+ switch (cref.Type) {
+ case CodeReferenceType.Msdn:
+ // TODO: remove "msdn:" from code reference and let ExampleComponent handle the snippet.
+ // We'll either pass this through to the regular ExampleComponent or delete the node.
+ WriteMessage(MessageLevel.Warn, "MSDN-only links not implemented yet.");
+ break;
+
+ case CodeReferenceType.Run:
+ case CodeReferenceType.View:
+ if (si != null || !omitBadExamples) {
+ WriteMessage(MessageLevel.Info, string.Format("+ LiveCode: Kind={0}, SampleName={1}", cref.Type.ToString(), cref.ExamplePath));
+ XmlWriter writer = node.InsertAfter();
+ writer.WriteStartElement(wdxPrefix, "LiveCode", wdxNamespace);
+ writer.WriteAttributeString("Kind", cref.Type.ToString());
+ writer.WriteAttributeString("SampleName", cref.ExamplePath);
+ writer.WriteAttributeString("runat", "server");
+ writer.WriteEndElement();
+ writer.Close();
+ node.DeleteSelf();
+ }
+ break;
+
+ case CodeReferenceType.Snippet:
+ // Ignore; let ExampleComponent handle the snippet.
+ break;
+
+ default:
+ WriteMessage(MessageLevel.Warn, string.Format("Invalid code example reference ignored: '{0}'", node.Value));
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// LoadApprovedFile reads the Parsnip approval file into a memory structure for easy lookup. We're assuming that the
+ /// content of this file is well formed and valid. Semantic errors will be silently ignored. Only samples with
+ /// approved units will be added to the lookup table.
+ /// </summary>
+ void LoadApprovedFile(string pathName) {
+ WriteMessage(MessageLevel.Info, string.Format("Loading Parsnip 'Approved' file: {0}", pathName));
+ sampleInfoTable = new Dictionary<string, SampleInfo>();
+ using (XmlReader reader = XmlReader.Create(pathName)) {
+ SampleInfo si = null;
+ string sample_name = null;
+ while (reader.Read()) {
+ switch (reader.NodeType) {
+ case XmlNodeType.Element:
+ if (reader.Name == "Sample") {
+ sample_name = reader.GetAttribute("name");
+ if (!string.IsNullOrEmpty(sample_name))
+ si = new SampleInfo(sample_name);
+ }
+ else if (si != null && reader.Name == "Unit") {
+ if (reader.GetAttribute("include") == "true")
+ si.AddApprovedUnit(reader.GetAttribute("name"));
+ }
+ break;
+ case XmlNodeType.EndElement:
+ if (reader.Name == "Sample") {
+ if (si != null) {
+ try {
+ if (si.ApprovedUnitsCount > 0)
+ sampleInfoTable.Add(si.Name, si);
+ }
+ catch (Exception x) {
+ WriteMessage(MessageLevel.Warn, string.Format("Sample {0} cannot be loaded {1}", si.Name, x.Message));
+ }
+ }
+ si = null;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ internal class SampleInfo {
+ string _name;
+ internal string Name {
+ get { return _name; }
+ }
+
+ List<string> _approvedUnits;
+
+ internal SampleInfo(string name) {
+ _name = name;
+ }
+
+ internal void AddApprovedUnit(string unit_name) {
+ if (_approvedUnits == null)
+ _approvedUnits = new List<string>();
+ _approvedUnits.Add(unit_name);
+ }
+
+ internal bool IsApproved(string unit_name) {
+ return (_approvedUnits == null) ? false : _approvedUnits.Contains(unit_name);
+ }
+
+ internal int ApprovedUnitsCount {
+ get { return (_approvedUnits == null) ? 0 : _approvedUnits.Count; }
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/MsdnResolver.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/MsdnResolver.cs
new file mode 100644
index 0000000..84a43f1
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/MsdnResolver.cs
@@ -0,0 +1,76 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Web.Services.Protocols;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class MsdnResolver {
+
+ public MsdnResolver () {
+ msdnService = new ContentService();
+ msdnService.appIdValue = new appId();
+ msdnService.appIdValue.value = "Sandcastle";
+ msdnService.SoapVersion = SoapProtocolVersion.Soap11;
+ }
+
+ public bool IsDisabled {
+ get {
+ return ((msdnService == null));
+ }
+ }
+
+ public string Locale {
+ get {
+ return (locale);
+ }
+ set {
+ locale = value;
+ }
+ }
+
+ public string GetMsdnUrl (string id) {
+
+ if (cachedMsdnUrls.ContainsKey(id)) return (String.Format(urlFormat, locale, cachedMsdnUrls[id]));
+
+ if (msdnService == null) return(null);
+
+ getContentRequest msdnRequest = new getContentRequest();
+ msdnRequest.contentIdentifier = "AssetId:" + id;
+ msdnRequest.locale = locale;
+
+ string endpoint = null;
+ try {
+ getContentResponse msdnResponse = msdnService.GetContent(msdnRequest);
+ endpoint = msdnResponse.contentId;
+ } catch (WebException) {
+ msdnService = null;
+ } catch (SoapException) {
+ // lookup failed
+ }
+
+ cachedMsdnUrls[id] = endpoint;
+
+ if (String.IsNullOrEmpty(endpoint)) {
+ return (null);
+ } else {
+ return (String.Format(urlFormat, locale, endpoint));
+ }
+ }
+
+ private ContentService msdnService;
+
+ private string locale = "en-us";
+
+ private static string urlFormat = "http://msdn2.microsoft.com/{0}/library/{1}";
+
+ private Dictionary<string, string> cachedMsdnUrls = new Dictionary<string, string>();
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/MsdnService.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/MsdnService.cs
new file mode 100644
index 0000000..e935faf
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/MsdnService.cs
@@ -0,0 +1,913 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.832
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Web.Services;
+using System.Web.Services.Protocols;
+using System.Xml.Serialization;
+
+//
+// This source code was auto-generated by wsdl, Version=2.0.50727.42.
+//
+
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Web.Services.WebServiceBindingAttribute(Name="ContentServiceBinding", Namespace="urn:msdn-com:public-content-syndication")]
+[System.Xml.Serialization.XmlIncludeAttribute(typeof(requestedDocument[]))]
+[System.Xml.Serialization.XmlIncludeAttribute(typeof(primary[]))]
+[System.Xml.Serialization.XmlIncludeAttribute(typeof(image[]))]
+[System.Xml.Serialization.XmlIncludeAttribute(typeof(common[]))]
+[System.Xml.Serialization.XmlIncludeAttribute(typeof(feature[]))]
+public partial class ContentService : System.Web.Services.Protocols.SoapHttpClientProtocol {
+
+ private appId appIdValueField;
+
+ private System.Threading.SendOrPostCallback GetContentOperationCompleted;
+
+ private System.Threading.SendOrPostCallback GetNavigationPathsOperationCompleted;
+
+ /// <remarks/>
+ public ContentService() {
+ this.Url = "http://services.msdn.microsoft.com/ContentServices/ContentService.asmx";
+ }
+
+ public appId appIdValue {
+ get {
+ return this.appIdValueField;
+ }
+ set {
+ this.appIdValueField = value;
+ }
+ }
+
+ /// <remarks/>
+ public event GetContentCompletedEventHandler GetContentCompleted;
+
+ /// <remarks/>
+ public event GetNavigationPathsCompletedEventHandler GetNavigationPathsCompleted;
+
+ /// <remarks/>
+ [System.Web.Services.Protocols.SoapHeaderAttribute("appIdValue")]
+ [System.Web.Services.Protocols.SoapDocumentMethodAttribute("urn:msdn-com:public-content-syndication/GetContent", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]
+ [return: System.Xml.Serialization.XmlElementAttribute("getContentResponse", Namespace="urn:msdn-com:public-content-syndication")]
+ public getContentResponse GetContent([System.Xml.Serialization.XmlElementAttribute(Namespace="urn:msdn-com:public-content-syndication")] getContentRequest getContentRequest) {
+ object[] results = this.Invoke("GetContent", new object[] {
+ getContentRequest});
+ return ((getContentResponse)(results[0]));
+ }
+
+ /// <remarks/>
+ public System.IAsyncResult BeginGetContent(getContentRequest getContentRequest, System.AsyncCallback callback, object asyncState) {
+ return this.BeginInvoke("GetContent", new object[] {
+ getContentRequest}, callback, asyncState);
+ }
+
+ /// <remarks/>
+ public getContentResponse EndGetContent(System.IAsyncResult asyncResult) {
+ object[] results = this.EndInvoke(asyncResult);
+ return ((getContentResponse)(results[0]));
+ }
+
+ /// <remarks/>
+ public void GetContentAsync(getContentRequest getContentRequest) {
+ this.GetContentAsync(getContentRequest, null);
+ }
+
+ /// <remarks/>
+ public void GetContentAsync(getContentRequest getContentRequest, object userState) {
+ if ((this.GetContentOperationCompleted == null)) {
+ this.GetContentOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetContentOperationCompleted);
+ }
+ this.InvokeAsync("GetContent", new object[] {
+ getContentRequest}, this.GetContentOperationCompleted, userState);
+ }
+
+ private void OnGetContentOperationCompleted(object arg) {
+ if ((this.GetContentCompleted != null)) {
+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
+ this.GetContentCompleted(this, new GetContentCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
+ }
+ }
+
+ /// <remarks/>
+ [System.Web.Services.Protocols.SoapHeaderAttribute("appIdValue")]
+ [System.Web.Services.Protocols.SoapDocumentMethodAttribute("urn:msdn-com:public-content-syndication/GetNavigationPaths", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]
+ [return: System.Xml.Serialization.XmlElementAttribute("getNavigationPathsResponse", Namespace="urn:msdn-com:public-content-syndication")]
+ public getNavigationPathsResponse GetNavigationPaths([System.Xml.Serialization.XmlElementAttribute(Namespace="urn:msdn-com:public-content-syndication")] getNavigationPathsRequest getNavigationPathsRequest) {
+ object[] results = this.Invoke("GetNavigationPaths", new object[] {
+ getNavigationPathsRequest});
+ return ((getNavigationPathsResponse)(results[0]));
+ }
+
+ /// <remarks/>
+ public System.IAsyncResult BeginGetNavigationPaths(getNavigationPathsRequest getNavigationPathsRequest, System.AsyncCallback callback, object asyncState) {
+ return this.BeginInvoke("GetNavigationPaths", new object[] {
+ getNavigationPathsRequest}, callback, asyncState);
+ }
+
+ /// <remarks/>
+ public getNavigationPathsResponse EndGetNavigationPaths(System.IAsyncResult asyncResult) {
+ object[] results = this.EndInvoke(asyncResult);
+ return ((getNavigationPathsResponse)(results[0]));
+ }
+
+ /// <remarks/>
+ public void GetNavigationPathsAsync(getNavigationPathsRequest getNavigationPathsRequest) {
+ this.GetNavigationPathsAsync(getNavigationPathsRequest, null);
+ }
+
+ /// <remarks/>
+ public void GetNavigationPathsAsync(getNavigationPathsRequest getNavigationPathsRequest, object userState) {
+ if ((this.GetNavigationPathsOperationCompleted == null)) {
+ this.GetNavigationPathsOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetNavigationPathsOperationCompleted);
+ }
+ this.InvokeAsync("GetNavigationPaths", new object[] {
+ getNavigationPathsRequest}, this.GetNavigationPathsOperationCompleted, userState);
+ }
+
+ private void OnGetNavigationPathsOperationCompleted(object arg) {
+ if ((this.GetNavigationPathsCompleted != null)) {
+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
+ this.GetNavigationPathsCompleted(this, new GetNavigationPathsCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
+ }
+ }
+
+ /// <remarks/>
+ public new void CancelAsync(object userState) {
+ base.CancelAsync(userState);
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:msdn-com:public-content-syndication/2006/09/common")]
+[System.Xml.Serialization.XmlRootAttribute(Namespace="urn:msdn-com:public-content-syndication/2006/09/common", IsNullable=false)]
+public partial class appId : System.Web.Services.Protocols.SoapHeader {
+
+ private string valueField;
+
+ /// <remarks/>
+ public string value {
+ get {
+ return this.valueField;
+ }
+ set {
+ this.valueField = value;
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:msdn-com:public-content-syndication")]
+public partial class navigationPathNode {
+
+ private string titleField;
+
+ private bool isPhantomField;
+
+ private bool isPhantomFieldSpecified;
+
+ private navigationKey navigationNodeKeyField;
+
+ private navigationKey contentNodeKeyField;
+
+ /// <remarks/>
+ public string title {
+ get {
+ return this.titleField;
+ }
+ set {
+ this.titleField = value;
+ }
+ }
+
+ /// <remarks/>
+ public bool isPhantom {
+ get {
+ return this.isPhantomField;
+ }
+ set {
+ this.isPhantomField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ public bool isPhantomSpecified {
+ get {
+ return this.isPhantomFieldSpecified;
+ }
+ set {
+ this.isPhantomFieldSpecified = value;
+ }
+ }
+
+ /// <remarks/>
+ public navigationKey navigationNodeKey {
+ get {
+ return this.navigationNodeKeyField;
+ }
+ set {
+ this.navigationNodeKeyField = value;
+ }
+ }
+
+ /// <remarks/>
+ public navigationKey contentNodeKey {
+ get {
+ return this.contentNodeKeyField;
+ }
+ set {
+ this.contentNodeKeyField = value;
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:msdn-com:public-content-syndication")]
+public partial class navigationKey {
+
+ private string contentIdField;
+
+ private string localeField;
+
+ private string versionField;
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlElementAttribute(Namespace="urn:mtpg-com:mtps/2004/1/key")]
+ public string contentId {
+ get {
+ return this.contentIdField;
+ }
+ set {
+ this.contentIdField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlElementAttribute(Namespace="urn:mtpg-com:mtps/2004/1/key")]
+ public string locale {
+ get {
+ return this.localeField;
+ }
+ set {
+ this.localeField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlElementAttribute(Namespace="urn:mtpg-com:mtps/2004/1/key")]
+ public string version {
+ get {
+ return this.versionField;
+ }
+ set {
+ this.versionField = value;
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:msdn-com:public-content-syndication")]
+public partial class navigationPath {
+
+ private navigationPathNode[] navigationPathNodesField;
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlArrayItemAttribute(IsNullable=false)]
+ public navigationPathNode[] navigationPathNodes {
+ get {
+ return this.navigationPathNodesField;
+ }
+ set {
+ this.navigationPathNodesField = value;
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:msdn-com:public-content-syndication")]
+public partial class availableVersionAndLocale {
+
+ private string localeField;
+
+ private string versionField;
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlElementAttribute(Namespace="urn:mtpg-com:mtps/2004/1/key")]
+ public string locale {
+ get {
+ return this.localeField;
+ }
+ set {
+ this.localeField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlElementAttribute(Namespace="urn:mtpg-com:mtps/2004/1/key")]
+ public string version {
+ get {
+ return this.versionField;
+ }
+ set {
+ this.versionField = value;
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:msdn-com:public-content-syndication")]
+public partial class requestedDocument {
+
+ private string selectorField;
+
+ private documentTypes typeField;
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlAttributeAttribute()]
+ public string selector {
+ get {
+ return this.selectorField;
+ }
+ set {
+ this.selectorField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlAttributeAttribute()]
+ public documentTypes type {
+ get {
+ return this.typeField;
+ }
+ set {
+ this.typeField = value;
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:msdn-com:public-content-syndication")]
+public enum documentTypes {
+
+ /// <remarks/>
+ primary,
+
+ /// <remarks/>
+ common,
+
+ /// <remarks/>
+ image,
+
+ /// <remarks/>
+ feature,
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:mtpg-com:mtps/2004/1/primary")]
+public partial class primary {
+
+ private System.Xml.XmlElement anyField;
+
+ private string primaryFormatField;
+
+ private string locationField;
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlAnyElementAttribute()]
+ public System.Xml.XmlElement Any {
+ get {
+ return this.anyField;
+ }
+ set {
+ this.anyField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified, Namespace="urn:mtpg-com:mtps/2004/1/primary/category")]
+ public string primaryFormat {
+ get {
+ return this.primaryFormatField;
+ }
+ set {
+ this.primaryFormatField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlAttributeAttribute()]
+ public string location {
+ get {
+ return this.locationField;
+ }
+ set {
+ this.locationField = value;
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:mtpg-com:mtps/2004/1/image")]
+public partial class image {
+
+ private string nameField;
+
+ private string imageFormatField;
+
+ private string locationField;
+
+ private byte[] valueField;
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlAttributeAttribute()]
+ public string name {
+ get {
+ return this.nameField;
+ }
+ set {
+ this.nameField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified, Namespace="urn:mtpg-com:mtps/2004/1/image/category")]
+ public string imageFormat {
+ get {
+ return this.imageFormatField;
+ }
+ set {
+ this.imageFormatField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlAttributeAttribute()]
+ public string location {
+ get {
+ return this.locationField;
+ }
+ set {
+ this.locationField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlTextAttribute(DataType="base64Binary")]
+ public byte[] Value {
+ get {
+ return this.valueField;
+ }
+ set {
+ this.valueField = value;
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:mtpg-com:mtps/2004/1/common")]
+public partial class common {
+
+ private System.Xml.XmlElement[] anyField;
+
+ private string commonFormatField;
+
+ private string locationField;
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlAnyElementAttribute()]
+ public System.Xml.XmlElement[] Any {
+ get {
+ return this.anyField;
+ }
+ set {
+ this.anyField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified, Namespace="urn:mtpg-com:mtps/2004/1/common/category")]
+ public string commonFormat {
+ get {
+ return this.commonFormatField;
+ }
+ set {
+ this.commonFormatField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlAttributeAttribute()]
+ public string location {
+ get {
+ return this.locationField;
+ }
+ set {
+ this.locationField = value;
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:mtpg-com:mtps/2004/1/feature")]
+public partial class feature {
+
+ private System.Xml.XmlElement[] anyField;
+
+ private string featureFormatField;
+
+ private string locationField;
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlAnyElementAttribute()]
+ public System.Xml.XmlElement[] Any {
+ get {
+ return this.anyField;
+ }
+ set {
+ this.anyField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified, Namespace="urn:mtpg-com:mtps/2004/1/feature/category")]
+ public string featureFormat {
+ get {
+ return this.featureFormatField;
+ }
+ set {
+ this.featureFormatField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlAttributeAttribute()]
+ public string location {
+ get {
+ return this.locationField;
+ }
+ set {
+ this.locationField = value;
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:msdn-com:public-content-syndication")]
+public partial class getContentRequest {
+
+ private string contentIdentifierField;
+
+ private string localeField;
+
+ private string versionField;
+
+ private requestedDocument[] requestedDocumentsField;
+
+ /// <remarks/>
+ public string contentIdentifier {
+ get {
+ return this.contentIdentifierField;
+ }
+ set {
+ this.contentIdentifierField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlElementAttribute(Namespace="urn:mtpg-com:mtps/2004/1/key")]
+ public string locale {
+ get {
+ return this.localeField;
+ }
+ set {
+ this.localeField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlElementAttribute(Namespace="urn:mtpg-com:mtps/2004/1/key")]
+ public string version {
+ get {
+ return this.versionField;
+ }
+ set {
+ this.versionField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlArrayItemAttribute(IsNullable=false)]
+ public requestedDocument[] requestedDocuments {
+ get {
+ return this.requestedDocumentsField;
+ }
+ set {
+ this.requestedDocumentsField = value;
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:msdn-com:public-content-syndication")]
+public partial class getContentResponse {
+
+ private string contentIdField;
+
+ private string contentGuidField;
+
+ private string contentAliasField;
+
+ private string localeField;
+
+ private string versionField;
+
+ private availableVersionAndLocale[] availableVersionsAndLocalesField;
+
+ private primary[] primaryDocumentsField;
+
+ private image[] imageDocumentsField;
+
+ private common[] commonDocumentsField;
+
+ private feature[] featureDocumentsField;
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlElementAttribute(Namespace="urn:mtpg-com:mtps/2004/1/key")]
+ public string contentId {
+ get {
+ return this.contentIdField;
+ }
+ set {
+ this.contentIdField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlElementAttribute(Namespace="urn:mtpg-com:mtps/2004/1/key")]
+ public string contentGuid {
+ get {
+ return this.contentGuidField;
+ }
+ set {
+ this.contentGuidField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlElementAttribute(Namespace="urn:mtpg-com:mtps/2004/1/key")]
+ public string contentAlias {
+ get {
+ return this.contentAliasField;
+ }
+ set {
+ this.contentAliasField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlElementAttribute(Namespace="urn:mtpg-com:mtps/2004/1/key")]
+ public string locale {
+ get {
+ return this.localeField;
+ }
+ set {
+ this.localeField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlElementAttribute(Namespace="urn:mtpg-com:mtps/2004/1/key")]
+ public string version {
+ get {
+ return this.versionField;
+ }
+ set {
+ this.versionField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlArrayItemAttribute(IsNullable=false)]
+ public availableVersionAndLocale[] availableVersionsAndLocales {
+ get {
+ return this.availableVersionsAndLocalesField;
+ }
+ set {
+ this.availableVersionsAndLocalesField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlArrayItemAttribute("primary", Namespace="urn:mtpg-com:mtps/2004/1/primary", IsNullable=false)]
+ public primary[] primaryDocuments {
+ get {
+ return this.primaryDocumentsField;
+ }
+ set {
+ this.primaryDocumentsField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlArrayItemAttribute("image", Namespace="urn:mtpg-com:mtps/2004/1/image", IsNullable=false)]
+ public image[] imageDocuments {
+ get {
+ return this.imageDocumentsField;
+ }
+ set {
+ this.imageDocumentsField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlArrayItemAttribute("common", Namespace="urn:mtpg-com:mtps/2004/1/common", IsNullable=false)]
+ public common[] commonDocuments {
+ get {
+ return this.commonDocumentsField;
+ }
+ set {
+ this.commonDocumentsField = value;
+ }
+ }
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlArrayItemAttribute("feature", Namespace="urn:mtpg-com:mtps/2004/1/feature", IsNullable=false)]
+ public feature[] featureDocuments {
+ get {
+ return this.featureDocumentsField;
+ }
+ set {
+ this.featureDocumentsField = value;
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:msdn-com:public-content-syndication")]
+public partial class getNavigationPathsRequest {
+
+ private navigationKey rootField;
+
+ private navigationKey targetField;
+
+ /// <remarks/>
+ public navigationKey root {
+ get {
+ return this.rootField;
+ }
+ set {
+ this.rootField = value;
+ }
+ }
+
+ /// <remarks/>
+ public navigationKey target {
+ get {
+ return this.targetField;
+ }
+ set {
+ this.targetField = value;
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.SerializableAttribute()]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:msdn-com:public-content-syndication")]
+public partial class getNavigationPathsResponse {
+
+ private navigationPath[] navigationPathsField;
+
+ /// <remarks/>
+ [System.Xml.Serialization.XmlArrayItemAttribute(IsNullable=false)]
+ public navigationPath[] navigationPaths {
+ get {
+ return this.navigationPathsField;
+ }
+ set {
+ this.navigationPathsField = value;
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+public delegate void GetContentCompletedEventHandler(object sender, GetContentCompletedEventArgs e);
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+public partial class GetContentCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
+
+ private object[] results;
+
+ internal GetContentCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
+ base(exception, cancelled, userState) {
+ this.results = results;
+ }
+
+ /// <remarks/>
+ public getContentResponse Result {
+ get {
+ this.RaiseExceptionIfNecessary();
+ return ((getContentResponse)(this.results[0]));
+ }
+ }
+}
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+public delegate void GetNavigationPathsCompletedEventHandler(object sender, GetNavigationPathsCompletedEventArgs e);
+
+/// <remarks/>
+[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.ComponentModel.DesignerCategoryAttribute("code")]
+public partial class GetNavigationPathsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
+
+ private object[] results;
+
+ internal GetNavigationPathsCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
+ base(exception, cancelled, userState) {
+ this.results = results;
+ }
+
+ /// <remarks/>
+ public getNavigationPathsResponse Result {
+ get {
+ this.RaiseExceptionIfNecessary();
+ return ((getNavigationPathsResponse)(this.results[0]));
+ }
+ }
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/PlatformsComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/PlatformsComponent.cs
new file mode 100644
index 0000000..cd3f2cc
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/PlatformsComponent.cs
@@ -0,0 +1,674 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Xml;
+using System.Xml.XPath;
+using System.IO;
+using System.Text;
+
+// still have problems with spaces
+
+namespace Microsoft.Ddue.Tools
+{
+
+ public class PlatformsComponent : BuildComponent
+ {
+
+ private Dictionary<string, Dictionary<string, VersionFilter>> versionFilters = new Dictionary<string, Dictionary<string, VersionFilter>>();
+
+ private XPathExpression platformQuery = XPathExpression.Compile("/platforms/platform");
+ private XPathExpression referenceExpression = XPathExpression.Compile("/document/reference");
+ private XPathExpression versionNodesExpression = XPathExpression.Compile("versions//version");
+ private XPathExpression apiGroupExpression = XPathExpression.Compile("string(apidata/@group)");
+ private XPathExpression topicdataGroupExpression = XPathExpression.Compile("string(topicdata/@group)");
+ private XPathExpression topicdataSubgroupExpression = XPathExpression.Compile("string(topicdata/@subgroup)");
+ private XPathExpression listTypeNameExpression = XPathExpression.Compile("string(apidata/@name)");
+ private XPathExpression apiNamespaceNameExpression = XPathExpression.Compile("string(containers/namespace/apidata/@name)");
+ private XPathExpression memberTypeNameExpression = XPathExpression.Compile("string(containers/type/apidata/@name)");
+
+ private XPathExpression listTopicElementNodesExpression = XPathExpression.Compile("elements//element");
+ private XPathExpression elementIdExpression = XPathExpression.Compile("string(@api)");
+
+ public PlatformsComponent(BuildAssembler assembler, XPathNavigator configuration)
+ : base(assembler, configuration)
+ {
+ // get the filter files
+ XPathNodeIterator filterNodes = configuration.Select("filter");
+ foreach (XPathNavigator filterNode in filterNodes)
+ {
+ string filterFiles = filterNode.GetAttribute("files", String.Empty);
+ if ((filterFiles == null) || (filterFiles.Length == 0))
+ throw new ConfigurationErrorsException("The filter/@files attribute must specify a path.");
+ ParseDocuments(filterFiles);
+ }
+ //WriteMessage(MessageLevel.Info, String.Format("Indexed {0} elements.", index.Count));
+ }
+
+ public void ParseDocuments(string wildcardPath)
+ {
+ string filterFiles = Environment.ExpandEnvironmentVariables(wildcardPath);
+ if ((filterFiles == null) || (filterFiles.Length == 0))
+ throw new ConfigurationErrorsException("The filter path is an empty string.");
+
+ WriteMessage(MessageLevel.Info, String.Format("Searching for files that match '{0}'.", filterFiles));
+ string directoryPart = Path.GetDirectoryName(filterFiles);
+ if (String.IsNullOrEmpty(directoryPart))
+ directoryPart = Environment.CurrentDirectory;
+ directoryPart = Path.GetFullPath(directoryPart);
+ string filePart = Path.GetFileName(filterFiles);
+ string[] files = Directory.GetFiles(directoryPart, filePart);
+ foreach (string file in files)
+ ParseDocument(file);
+ WriteMessage(MessageLevel.Info, String.Format("Found {0} files in {1}.", files.Length, filterFiles));
+ }
+
+ private void AddPlatformVersionFilter(string platformId, string versionId, XPathNavigator platformNode, string file)
+ {
+ Dictionary<string, VersionFilter> platformFrameworks;
+ if (!versionFilters.TryGetValue(platformId, out platformFrameworks))
+ {
+ platformFrameworks = new Dictionary<string, VersionFilter>();
+ versionFilters.Add(platformId, platformFrameworks);
+ }
+
+ try
+ {
+ VersionFilter filter;
+ XmlReader platformReader = platformNode.ReadSubtree();
+ platformReader.MoveToContent();
+ if (!platformFrameworks.TryGetValue(versionId, out filter))
+ {
+ filter = new VersionFilter(platformReader, versionId, file);
+ }
+ else
+ {
+ // if the platform already has a filter for this version, add the data from the current platform node
+ filter.AddPlatformNode(platformReader, file);
+ }
+ platformReader.Close();
+
+ platformFrameworks.Remove(versionId);
+ platformFrameworks.Add(versionId, filter);
+ }
+ catch (Exception e)
+ {
+ WriteMessage(MessageLevel.Error, e.Message);
+ }
+ }
+
+ private void ParseDocument(string file)
+ {
+ try
+ {
+ XPathDocument document = new XPathDocument(file);
+
+ XPathNodeIterator platformNodes = document.CreateNavigator().Select(platformQuery);
+ foreach (XPathNavigator platformNode in platformNodes)
+ {
+ string platformId = platformNode.GetAttribute("name", String.Empty);
+ string[] platformIds = platformId.Split(',');
+
+ string version = platformNode.GetAttribute("version", String.Empty);
+ string[] versionIds = version.Split(',');
+ for (int i = 0; i < versionIds.Length; i++)
+ {
+ for (int j = 0; j < platformIds.Length; j++)
+ {
+ XPathNavigator platformNodeClone = platformNode.Clone();
+ AddPlatformVersionFilter(platformIds[j], versionIds[i], platformNodeClone, file);
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ WriteMessage(MessageLevel.Error, e.Message);
+ }
+ }
+
+ public override void Apply(XmlDocument document, string key)
+ {
+ XPathNavigator targetDoc = document.CreateNavigator();
+ XPathNavigator referenceNode = targetDoc.SelectSingleNode(referenceExpression);
+ string apiGroup = (string)referenceNode.Evaluate(apiGroupExpression);
+ string topicdataGroup = (string)referenceNode.Evaluate(topicdataGroupExpression);
+ string topicdataSubgroup = (string)referenceNode.Evaluate(topicdataSubgroupExpression);
+
+ // get the namespace and typename of the current type to locate the filter information that applies to the current topic
+ // For filtering inherited members, the platform filters use the namespace and typename of the inheriting type, not the declaring type,
+ string topicNamespaceName = (string)referenceNode.Evaluate(apiNamespaceNameExpression);
+ string topicTypeName = (string)referenceNode.Evaluate(memberTypeNameExpression);
+
+ // write platforms info for normal api topics (excluding memberlist and overload list topics
+ if (topicdataGroup != "list" && topicdataSubgroup != "DerivedTypeList" && (apiGroup == "type" || apiGroup == "member") && versionFilters.Count > 0)
+ {
+ WriteApiPlatforms(referenceNode, apiGroup, key, topicTypeName, topicNamespaceName);
+ }
+
+ // write platforms for elements//element nodes (member list and overload topics; not root or namespace)
+ if ((topicdataGroup == "list" && topicdataSubgroup != "DerivedTypeList") && apiGroup != "root" && versionFilters.Count > 0)
+ {
+ if (topicdataSubgroup != "overload")
+ topicTypeName = (string)referenceNode.Evaluate(listTypeNameExpression);
+
+ XPathNodeIterator elementNodes = referenceNode.Select(listTopicElementNodesExpression);
+ foreach (XPathNavigator elementNode in elementNodes)
+ {
+ string elementId = (string)elementNode.Evaluate(elementIdExpression);
+ WriteApiPlatforms(elementNode, "member", elementId, topicTypeName, topicNamespaceName);
+ }
+ }
+ }
+
+ private void WriteApiPlatforms(XPathNavigator referenceNode, string apiGroup, string key, string topicTypeName, string topicNamespaceName)
+ {
+ XPathNodeIterator versionNodes = referenceNode.Select(versionNodesExpression);
+ List<string> supportedPlatforms = new List<string>();
+ XmlWriter platformsWriter = referenceNode.AppendChild();
+
+ foreach (string platformId in versionFilters.Keys)
+ {
+ Dictionary<string, VersionFilter> filters = versionFilters[platformId];
+ bool included = false;
+ foreach (XPathNavigator versionNode in versionNodes)
+ {
+ string versionId = versionNode.GetAttribute("name", string.Empty);
+ VersionFilter filter;
+ if (filters.TryGetValue(versionId, out filter))
+ {
+ switch (apiGroup)
+ {
+ case "type":
+ included = filter.IsIncludedType(referenceNode, key, topicNamespaceName);
+ break;
+ case "member":
+ included = filter.IsIncludedMember(referenceNode, key, topicTypeName, topicNamespaceName);
+ break;
+ }
+ }
+ if (included)
+ break;
+ }
+
+ if (included)
+ supportedPlatforms.Add(platformId);
+ }
+ platformsWriter.WriteStartElement("platforms");
+ foreach (string platformId in supportedPlatforms)
+ {
+ platformsWriter.WriteElementString("platform", platformId);
+ }
+ platformsWriter.WriteEndElement();
+ platformsWriter.Close();
+ }
+
+ }
+
+ public abstract class InclusionFilter
+ {
+ public InclusionFilter(string file)
+ {
+ sourceFiles.Add(file);
+ }
+
+ protected List<string> sourceFiles = new List<string>();
+
+ protected static XPathExpression apiNameExpression = XPathExpression.Compile("string(apidata/@name)");
+ protected static XPathExpression apiParameterNodesExpression = XPathExpression.Compile("parameters/parameter");
+ protected static XPathExpression apiParameterTypeNameExpression = XPathExpression.Compile("string(.//type/@api)");
+ protected static XPathExpression apiParameterTemplateNameExpression = XPathExpression.Compile("string(.//template/@name)");
+ }
+
+ public class VersionFilter : InclusionFilter
+ {
+
+ public VersionFilter(XmlReader platformReader, string id, string file)
+ : base(file)
+ {
+ // platform/@version can only list included framework versions; excluding versions is not supported
+ included = true;
+ versionId = id;
+ AddPlatformNode(platformReader, file);
+ }
+
+ public void AddPlatformNode(XmlReader platformReader, string file)
+ {
+ XmlReader subtree = platformReader.ReadSubtree();
+ while (subtree.Read())
+ {
+ if ((subtree.NodeType == XmlNodeType.Element) && (subtree.Name == "namespace"))
+ {
+ string namespaceName = subtree.GetAttribute("name");
+
+ NamespaceFilter namespaceFilter;
+ if (!namespaceFilters.TryGetValue(namespaceName, out namespaceFilter))
+ {
+ namespaceFilter = new NamespaceFilter(subtree, file);
+ }
+ else
+ {
+ // if the version already has a filter for this namespace, add the data from the current namespace node
+ // unless the namespace node has a different @include value, in which case log a warning
+ string nsIncludeAttr = subtree.GetAttribute("include");
+ bool nsIncluded = Convert.ToBoolean(string.IsNullOrEmpty(nsIncludeAttr) ? "true" : nsIncludeAttr);
+ if (nsIncluded != namespaceFilter.Included)
+ {
+ // write warning message about conflicting filters
+ // ISSUE: how to invoke WriteMessage from here
+ Console.Write("");
+ }
+ else
+ {
+ namespaceFilter.AddNamespaceNode(subtree, file);
+ }
+
+ }
+ namespaceFilters.Remove(namespaceName);
+ namespaceFilters.Add(namespaceName, namespaceFilter);
+ }
+ }
+ subtree.Close();
+ }
+
+ private string versionId;
+
+ // platform/@version can only list included framework versions; excluding versions is not supported
+ private bool included;
+
+ private Dictionary<string, NamespaceFilter> namespaceFilters = new Dictionary<string, NamespaceFilter>();
+
+ public string VersionId
+ {
+ get
+ {
+ return (versionId);
+ }
+ }
+
+ public Dictionary<string, NamespaceFilter> NamespaceFilters
+ {
+ get
+ {
+ return (namespaceFilters);
+ }
+ }
+
+ /// <summary>
+ /// If we get here, we know that the platform supports this version, and the api is included in this version.
+ /// So returns true unless the type or its namespace are explicitly excluded by this version filter.
+ /// </summary>
+ /// <param name="referenceNode">The type's reflection data.</param>
+ /// <returns></returns>
+ public bool IsIncludedType(XPathNavigator referenceNode, string key, string topicNamespaceName)
+ {
+ // if we have a filter for the topic's namespace, check it
+ NamespaceFilter namespaceFilter;
+ if (namespaceFilters.TryGetValue(topicNamespaceName, out namespaceFilter))
+ {
+ return namespaceFilter.IsIncludedType(referenceNode, key);
+ }
+ return included;
+ }
+
+ public bool IsIncludedMember(XPathNavigator referenceNode, string key, string topicTypeName, string topicNamespaceName)
+ {
+ // if we have a filter for the topic's namespace, check it
+ NamespaceFilter namespaceFilter;
+ if (namespaceFilters.TryGetValue(topicNamespaceName, out namespaceFilter))
+ {
+ return namespaceFilter.IsIncludedMember(referenceNode, key, topicTypeName);
+ }
+ return included;
+ }
+ }
+
+
+ public class NamespaceFilter : InclusionFilter
+ {
+
+ public NamespaceFilter(XmlReader namespaceReader, string file)
+ : base(file)
+ {
+ //name = namespaceReader.GetAttribute("name");
+ string includeAttr = namespaceReader.GetAttribute("include");
+ included = Convert.ToBoolean(string.IsNullOrEmpty(includeAttr) ? "true" : includeAttr);
+ AddNamespaceNode(namespaceReader, file);
+ }
+
+ public void AddNamespaceNode(XmlReader namespaceReader, string file)
+ {
+ XmlReader subtree = namespaceReader.ReadSubtree();
+ while (subtree.Read())
+ {
+ if ((subtree.NodeType == XmlNodeType.Element) && (subtree.Name == "type"))
+ {
+ string typeName = subtree.GetAttribute("name");
+
+ TypeFilter typeFilter;
+ if (!typeFilters.TryGetValue(typeName, out typeFilter))
+ {
+ typeFilter = new TypeFilter(subtree, file);
+ }
+ else
+ {
+ // if the namespace already has a filter for this type, add the data from the current type node
+ // unless the type node has a different @include value, in which case log a warning
+ string typeIncludeAttr = subtree.GetAttribute("include");
+ bool typeIncluded = Convert.ToBoolean(string.IsNullOrEmpty(typeIncludeAttr) ? "true" : typeIncludeAttr);
+ if (typeIncluded != typeFilter.Included)
+ {
+ // write warning message about conflicting filters
+ // ISSUE: how to invoke WriteMessage from here
+ Console.Write("");
+ }
+ else
+ {
+ typeFilter.AddTypeNode(subtree, file);
+ }
+ }
+ typeFilters.Remove(typeName);
+ typeFilters.Add(typeName, typeFilter);
+ }
+ }
+ subtree.Close();
+ }
+
+ //private string name;
+
+ private bool included;
+ public bool Included
+ {
+ get
+ {
+ return (included);
+ }
+ }
+
+ private Dictionary<string, TypeFilter> typeFilters = new Dictionary<string, TypeFilter>();
+ public Dictionary<string, TypeFilter> TypeFilters
+ {
+ get
+ {
+ return (typeFilters);
+ }
+ }
+
+ public bool IsIncludedType(XPathNavigator referenceNode, string key)
+ {
+ // get the type's name
+ string typeName = (string)referenceNode.Evaluate(apiNameExpression);
+
+ // if we have a filter for that type, check it
+ TypeFilter typeFilter;
+ if (typeFilters.TryGetValue(typeName, out typeFilter))
+ {
+ return typeFilter.Included;
+ }
+ return included;
+ }
+
+ public bool IsIncludedMember(XPathNavigator referenceNode, string key, string topicTypeName)
+ {
+ // if we have a filter for the type, check it
+ TypeFilter typeFilter;
+ if (typeFilters.TryGetValue(topicTypeName, out typeFilter))
+ {
+ return typeFilter.IsIncludedMember(referenceNode, key);
+ }
+ return included;
+ }
+ }
+
+ public class TypeFilter : InclusionFilter
+ {
+
+ public TypeFilter(XmlReader typeReader, string file)
+ : base(file)
+ {
+ //name = typeReader.GetAttribute("name");
+ string includeAttr = typeReader.GetAttribute("include");
+ included = Convert.ToBoolean(string.IsNullOrEmpty(includeAttr) ? "true" : includeAttr);
+ AddTypeNode(typeReader, file);
+ }
+
+ public void AddTypeNode(XmlReader typeReader, string file)
+ {
+ XmlReader subtree = typeReader.ReadSubtree();
+ while (subtree.Read())
+ {
+ if ((subtree.NodeType == XmlNodeType.Element) && (subtree.Name == "member"))
+ {
+ string memberName = subtree.GetAttribute("name");
+
+ MemberFilter memberFilter;
+ if (!memberFilters.TryGetValue(memberName, out memberFilter))
+ {
+ memberFilter = new MemberFilter(subtree, file);
+ }
+ else
+ {
+ // if the type already has a filter for this member, add the data from the current member node
+ // unless the member node has a different @include value, in which case log a warning
+ string memberIncludeAttr = subtree.GetAttribute("include");
+ bool memberIncluded = Convert.ToBoolean(string.IsNullOrEmpty(memberIncludeAttr) ? "true" : memberIncludeAttr);
+ if (memberIncluded != memberFilter.Included)
+ {
+ // write warning message about conflicting filters
+ // ISSUE: how to invoke WriteMessage from here
+ Console.Write("");
+ }
+ else
+ {
+ memberFilter.AddMemberNode(subtree, file);
+ }
+ }
+ memberFilters.Remove(memberName);
+ memberFilters.Add(memberName, memberFilter);
+ }
+ }
+ subtree.Close();
+ }
+
+ //private string name;
+
+ private bool included;
+ public bool Included
+ {
+ get
+ {
+ return (included);
+ }
+ }
+
+ private Dictionary<string, MemberFilter> memberFilters = new Dictionary<string, MemberFilter>();
+ public Dictionary<string, MemberFilter> MemberFilters
+ {
+ get
+ {
+ return (memberFilters);
+ }
+ }
+
+ public bool IsIncludedMember(XPathNavigator referenceNode, string key)
+ {
+ // get the member's name
+ string memberName = (string)referenceNode.Evaluate(apiNameExpression);
+
+ // if we have a filter for that member, check it
+ MemberFilter memberFilter;
+ if (memberFilters.TryGetValue(memberName, out memberFilter))
+ {
+ return memberFilter.IsIncludedMember(referenceNode, key);
+ }
+ return included;
+ }
+
+ }
+
+ public class MemberFilter : InclusionFilter
+ {
+
+ public MemberFilter(XmlReader memberReader, string file)
+ : base(file)
+ {
+ //name = memberReader.GetAttribute("name");
+
+ string includeAttr = memberReader.GetAttribute("include");
+ included = Convert.ToBoolean(string.IsNullOrEmpty(includeAttr) ? "true" : includeAttr);
+ AddMemberNode(memberReader, file);
+ }
+
+ public void AddMemberNode(XmlReader memberReader, string file)
+ {
+ XmlReader subtree = memberReader.ReadSubtree();
+ while (subtree.Read())
+ {
+ if ((subtree.NodeType == XmlNodeType.Element) && (subtree.Name == "overload"))
+ {
+ string overloadId = subtree.GetAttribute("api");
+ string paramTypes = subtree.GetAttribute("types");
+ string paramNames = subtree.GetAttribute("names");
+ string overloadIncludeAttr = subtree.GetAttribute("include");
+ bool overloadIncluded = Convert.ToBoolean(string.IsNullOrEmpty(overloadIncludeAttr) ? "true" : overloadIncludeAttr);
+ // check for existing overload filters that identify the same overload
+ bool alreadyFiltered = false;
+ foreach (OverloadFilter overloadFilter in overloadFilters)
+ {
+ if (!string.IsNullOrEmpty(paramTypes) && paramTypes == overloadFilter.ParamTypes)
+ alreadyFiltered = true;
+ if (alreadyFiltered && (overloadIncluded != overloadFilter.Included))
+ {
+ // write warning message about conflicting filters
+ // ISSUE: how to invoke WriteMessage from here
+ Console.Write("");
+ }
+ }
+ if (!alreadyFiltered)
+ {
+ OverloadFilter overloadFilter = new OverloadFilter(subtree, file);
+ overloadFilters.Add(overloadFilter);
+ }
+ }
+ }
+ subtree.Close();
+ }
+
+ //private string name;
+
+ private bool included;
+ public bool Included
+ {
+ get
+ {
+ return (included);
+ }
+ }
+
+ private List<OverloadFilter> overloadFilters = new List<OverloadFilter>();
+
+ public bool IsIncludedMember(XPathNavigator referenceNode, string key)
+ {
+ if (overloadFilters.Count == 0)
+ return included;
+
+ // get the member's paramTypes string
+
+
+ // get the member's paramNames string
+ XPathNodeIterator parameterNodes = referenceNode.Select(apiParameterNodesExpression);
+
+ StringBuilder paramNames = new StringBuilder();
+ StringBuilder paramTypes = new StringBuilder();
+ int i = 0;
+ foreach (XPathNavigator parameterNode in parameterNodes)
+ {
+ i++;
+ paramNames.Append(parameterNode.GetAttribute("name", string.Empty));
+ if (i < parameterNodes.Count)
+ paramNames.Append(",");
+
+ // BUGBUG: code here and in the psx conversion transform is a quick hack; make it better
+ string arrayOf = (parameterNode.SelectSingleNode("arrayOf") == null) ? "" : "[]";
+ string typeName = (string)parameterNode.Evaluate(apiParameterTypeNameExpression);
+ if (string.IsNullOrEmpty(typeName))
+ typeName = (string)parameterNode.Evaluate(apiParameterTemplateNameExpression);
+
+ int basenameStart = typeName.LastIndexOf(':') + 1;
+ if (basenameStart > 0 && basenameStart < typeName.Length)
+ typeName = typeName.Substring(basenameStart);
+
+ paramTypes.Append(typeName + arrayOf);
+ if (i < parameterNodes.Count)
+ paramTypes.Append(",");
+ }
+
+ foreach (OverloadFilter overloadFilter in overloadFilters)
+ {
+ if (paramTypes.ToString() == overloadFilter.ParamTypes)
+ return overloadFilter.Included;
+ }
+
+ return included;
+ }
+
+ }
+
+ public class OverloadFilter : InclusionFilter
+ {
+
+ public OverloadFilter(XmlReader overloadReader, string file)
+ : base(file)
+ {
+ //name = overloadReader.GetAttribute("name");
+ string includeAttr = overloadReader.GetAttribute("include");
+ included = Convert.ToBoolean(string.IsNullOrEmpty(includeAttr) ? "true" : includeAttr);
+ overloadId = overloadReader.GetAttribute("api");
+ paramTypes = overloadReader.GetAttribute("types");
+ paramNames = overloadReader.GetAttribute("names");
+ }
+
+ //private string name;
+
+ private bool included;
+ public bool Included
+ {
+ get
+ {
+ return (included);
+ }
+ }
+
+ private string paramTypes;
+ public string ParamTypes
+ {
+ get
+ {
+ return (paramTypes);
+ }
+ }
+
+ private string paramNames;
+ public string ParamNames
+ {
+ get
+ {
+ return (paramNames);
+ }
+ }
+ private string overloadId;
+ public string OverloadId
+ {
+ get
+ {
+ return (overloadId);
+ }
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/AssemblyInfo.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..41965fc
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/AssemblyInfo.cs
@@ -0,0 +1,42 @@
+// 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.
+
+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("BuildComponents")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("BuildComponents")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2006")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: System.CLSCompliant(true)]
+
+// 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("146f3298-2c7f-4588-88f2-520438232a23")]
+
+// 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.5.10626.00")]
+[assembly: AssemblyFileVersion("2.5.10626.00")]
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/Settings.Designer.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..930f32a
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.42
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace BuildComponents.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/Settings.settings b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/Settings.settings
new file mode 100644
index 0000000..8e615f2
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/Settings.settings
@@ -0,0 +1,5 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+ <Profiles />
+ <Settings />
+</SettingsFile> \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/References.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/References.cs
new file mode 100644
index 0000000..ba23c6f
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/References.cs
@@ -0,0 +1,340 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace BuildComponents {
+
+ public interface ISimpleReference {
+
+ string Id { get; }
+
+ }
+
+ public abstract partial class Reference { }
+
+ // Namespace
+
+ public partial class NamespaceReference : Reference, ISimpleReference {
+
+ internal NamespaceReference (string id) {
+ this.namespaceId = id;
+ }
+
+ private string namespaceId;
+
+ public string Id {
+ get {
+ return (namespaceId);
+ }
+ }
+
+ }
+
+ // Type
+
+ public abstract partial class TypeReference : Reference { }
+
+ public partial class SimpleTypeReference : TypeReference {
+
+ internal SimpleTypeReference (string id) {
+ this.typeId = id;
+ }
+
+ private string typeId;
+
+ public string Id {
+ get {
+ return (typeId);
+ }
+ }
+
+
+ }
+
+ public partial class ReferenceTypeReference : TypeReference {
+
+ private TypeReference referedToType;
+
+ public TypeReference ReferedToType {
+ get {
+ return (referedToType);
+ }
+ }
+
+ internal ReferenceTypeReference (TypeReference referedToType) {
+ if (referedToType == null) throw new ArgumentNullException("referedToType");
+ this.referedToType = referedToType;
+ }
+ }
+
+ public partial class PointerTypeReference : TypeReference {
+
+ internal PointerTypeReference (TypeReference pointedToType) {
+ if (pointedToType == null) throw new ArgumentNullException("pointedToType");
+ this.pointedToType = pointedToType;
+ }
+
+ private TypeReference pointedToType;
+
+ public TypeReference PointedToType {
+ get {
+ return (pointedToType);
+ }
+ }
+
+ }
+
+ public partial class ArrayTypeReference : TypeReference {
+
+ internal ArrayTypeReference (TypeReference elementType, int rank) {
+ if (elementType == null) throw new ArgumentNullException("elementType");
+ if (rank <= 0) throw new ArgumentOutOfRangeException("rank");
+ this.elementType = elementType;
+ this.rank = rank;
+ }
+
+ private int rank;
+
+ private TypeReference elementType;
+
+ public int Rank {
+ get {
+ return (rank);
+ }
+ }
+
+ public TypeReference ElementType {
+ get {
+ return (elementType);
+ }
+ }
+
+ }
+
+ public class TemplateTypeReference : TypeReference {
+
+ internal TemplateTypeReference (string templateId, int position) {
+ if (template == null) throw new ArgumentNullException("template");
+ if (position < 0) throw new ArgumentOutOfRangeException("position");
+ this.template = null; // fix this: create a reference
+ this.position = position;
+ }
+
+ internal TemplateTypeReference (ISimpleReference template, int position) {
+ if (template == null) throw new ArgumentNullException("template");
+ if (position < 0) throw new ArgumentOutOfRangeException("position");
+ this.template = template;
+ this.position = position;
+ }
+
+ private ISimpleReference template;
+
+ private int position;
+ }
+
+ public abstract partial class MemberReference : Reference {}
+
+ public partial class SimpleMemberReference : MemberReference, ISimpleReference {
+
+ internal SimpleMemberReference (string id) {
+ if (id == null) throw new ArgumentNullException("id");
+ this.memberId = id;
+ }
+
+ private string memberId;
+
+ public string Id {
+ get {
+ return(memberId);
+ }
+ }
+
+
+
+ }
+
+
+
+
+ // ***** XML PARSING ****
+
+ public partial class Reference {
+
+ public static Reference Create (XmlReader element) {
+ if (element == null) throw new ArgumentNullException("element");
+ switch (element.LocalName) {
+ case "namespace":
+ return (NamespaceReference.Create(element));
+ case "member":
+ return (MemberReference.Create(element));
+ default:
+ return (TypeReference.Create(element));
+ }
+ }
+
+ public static Reference Create (XPathNavigator node) {
+ if (node == null) throw new ArgumentNullException("node");
+ if (node.NodeType == XPathNodeType.Element) {
+ string tag = node.LocalName;
+ if (tag == "namespace") return (NamespaceReference.Create(node));
+ //if (tag == "member") return (MemberReference.Create(node));
+ return (TypeReference.Create(node));
+ } else {
+ return (null);
+ }
+ }
+
+ protected static XPathExpression referenceApiExpression = XPathExpression.Compile("string(@api)");
+
+
+ }
+
+ public partial class NamespaceReference {
+
+ public static new NamespaceReference Create (XmlReader space) {
+ if (space == null) throw new ArgumentNullException("space");
+
+ string api = space.GetAttribute("api");
+
+ return(new NamespaceReference(api));
+
+ }
+
+ public static new NamespaceReference Create (XPathNavigator space) {
+ if (space == null) throw new ArgumentNullException("space");
+ string api = (string) space.Evaluate(referenceApiExpression);
+ return(new NamespaceReference(api));
+ }
+
+ }
+
+ public partial class TypeReference {
+
+ public static new TypeReference Create (XmlReader element) {
+ if (element == null) throw new ArgumentNullException("element");
+ switch (element.LocalName) {
+ case "type":
+ // also handle specialization!
+ return(SimpleTypeReference.Create(element));
+ case "referenceTo":
+ return(ReferenceTypeReference.Create(element));
+ case "pointerTo":
+ return(PointerTypeReference.Create(element));
+ case "arrayOf":
+ return(ArrayTypeReference.Create(element));
+
+ }
+ return (null);
+ }
+
+ public static new TypeReference Create (XPathNavigator element) {
+ if (element == null) throw new ArgumentNullException("element");
+ string tag = element.LocalName;
+ if (tag == "type") {
+ bool isSpecialized = (bool)element.Evaluate("boolean(.//specialization)");
+ if (isSpecialized) {
+ // deal with specialization!
+ // return (CreateSpecializedTypeReference(element));
+ return (SimpleTypeReference.Create(element));
+ } else {
+ return (SimpleTypeReference.Create(element));
+ }
+ } else if (tag == "arrayOf") {
+ string rankValue = element.GetAttribute("rank", String.Empty);
+ XPathNavigator elementNode = element.SelectSingleNode("*[1]");
+ return (new ArrayTypeReference(TypeReference.Create(elementNode), Convert.ToInt32(rankValue)));
+ } else if (tag == "referenceTo") {
+ XPathNavigator referedToNode = element.SelectSingleNode("*[1]");
+ return (new ReferenceTypeReference(TypeReference.Create(referedToNode)));
+ } else if (tag == "pointerTo") {
+ XPathNavigator pointedToNode = element.SelectSingleNode("*[1]");
+ return (new PointerTypeReference(TypeReference.Create(pointedToNode)));
+ } else if (tag == "template") {
+ //string nameValue = element.GetAttribute("name", String.Empty);
+ string indexValue = element.GetAttribute("index", String.Empty);
+ string apiValue = element.GetAttribute("api", String.Empty);
+ if ((!String.IsNullOrEmpty(apiValue)) && (!String.IsNullOrEmpty(indexValue))) {
+ return (new TemplateTypeReference(apiValue, Convert.ToInt32(indexValue)));
+ // return (new IndexedTemplateTypeReference(apiValue, Convert.ToInt32(indexValue)));
+ } else {
+ throw new InvalidOperationException();
+ // return (new NamedTemplateTypeReference(nameValue));
+ }
+ }
+
+ throw new InvalidOperationException(String.Format("INVALID '{0}'", tag));
+ }
+
+ }
+
+ public partial class SimpleTypeReference {
+
+ public static new SimpleTypeReference Create (XmlReader type) {
+ if (type == null) throw new ArgumentNullException("type");
+ string api = type.GetAttribute("api");
+ return (new SimpleTypeReference(api));
+ }
+
+ public static new SimpleTypeReference Create (XPathNavigator type) {
+ if (type == null) throw new ArgumentNullException("type");
+ string api = (string)type.Evaluate(referenceApiExpression);
+ return(new SimpleTypeReference(api));
+ }
+
+ }
+
+ public partial class ReferenceTypeReference {
+
+ public static new ReferenceTypeReference Create (XmlReader referenceTo) {
+ if (referenceTo == null) throw new ArgumentException("refernceTo");
+ referenceTo.Read();
+ TypeReference referedToType = TypeReference.Create(referenceTo);
+ return (new ReferenceTypeReference(referedToType));
+ }
+
+ public static new ReferenceTypeReference Create (XPathNavigator referenceTo) {
+ XPathNavigator referedToNode = referenceTo.SelectSingleNode("*[1]");
+ TypeReference referedToType = TypeReference.Create(referedToNode);
+ return (new ReferenceTypeReference(referedToType));
+ }
+ }
+
+ public partial class PointerTypeReference {
+
+ public static new PointerTypeReference Create (XmlReader pointerTo) {
+ if (pointerTo == null) throw new ArgumentNullException("pointerTo");
+ pointerTo.Read();
+ TypeReference pointedToType = TypeReference.Create(pointerTo);
+ return (new PointerTypeReference(pointedToType));
+ }
+
+ public static new PointerTypeReference Create (XPathNavigator pointerTo) {
+ XPathNavigator pointedToNode = pointerTo.SelectSingleNode("*[1]");
+ TypeReference pointedToType = TypeReference.Create(pointedToNode);
+ return (new PointerTypeReference(pointedToType));
+ }
+ }
+
+ public partial class ArrayTypeReference {
+
+ public static new ArrayTypeReference Create (XmlReader arrayOf) {
+ if (arrayOf == null) throw new ArgumentNullException("arrayOf");
+
+ int rank = 1;
+ string rankText = arrayOf.GetAttribute("rank");
+ if (!String.IsNullOrEmpty(rankText)) rank = Convert.ToInt32(rankText);
+
+ arrayOf.Read();
+ TypeReference elementType = TypeReference.Create(arrayOf);
+
+ return (new ArrayTypeReference(elementType, rank));
+ }
+ }
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveArtLinksComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveArtLinksComponent.cs
new file mode 100644
index 0000000..77d763d
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveArtLinksComponent.cs
@@ -0,0 +1,195 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class ResolveArtLinksComponent : BuildComponent {
+
+ public ResolveArtLinksComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ XPathNodeIterator targets_nodes = configuration.Select("targets");
+ foreach (XPathNavigator targets_node in targets_nodes) {
+
+ string input = targets_node.GetAttribute("input", String.Empty);
+ if (String.IsNullOrEmpty(input)) WriteMessage(MessageLevel.Error, "Each targets element must have an input attribute specifying a directory containing art files.");
+ input = Environment.ExpandEnvironmentVariables(input);
+ if (!Directory.Exists(input)) WriteMessage(MessageLevel.Error, String.Format("The art input directory '{0}' does not exist.", input));
+
+ string baseOutputPath = targets_node.GetAttribute("baseOutput", String.Empty);
+ if (!String.IsNullOrEmpty(baseOutputPath)) {
+ baseOutputPath = Path.GetFullPath(Environment.ExpandEnvironmentVariables(baseOutputPath));
+ }
+
+ string outputPath_value = targets_node.GetAttribute("outputPath", string.Empty);
+ if (string.IsNullOrEmpty(outputPath_value)) WriteMessage(MessageLevel.Error, "Each targets element must have an output attribute specifying a directory in which to place referenced art files.");
+ XPathExpression output_XPath = XPathExpression.Compile(outputPath_value);
+
+ string linkValue = targets_node.GetAttribute("link", String.Empty);
+ if (String.IsNullOrEmpty(linkValue)) linkValue = "../art";
+ //linkValue = Environment.ExpandEnvironmentVariables(linkValue);
+
+ string map = targets_node.GetAttribute("map", String.Empty);
+ if (String.IsNullOrEmpty(map)) WriteMessage(MessageLevel.Error, "Each targets element must have a map attribute specifying a file that maps art ids to files in the input directory.");
+ map = Environment.ExpandEnvironmentVariables(map);
+ if (!File.Exists(map)) WriteMessage(MessageLevel.Error, String.Format("The art map file '{0}' does not exist.", map));
+
+ string format = targets_node.GetAttribute("format", String.Empty);
+ XPathExpression format_xpath = String.IsNullOrEmpty(format) ? null : XPathExpression.Compile(format);
+
+ string relative_to = targets_node.GetAttribute("relative-to", String.Empty);
+ XPathExpression relative_to_xpath = String.IsNullOrEmpty(relative_to) ? null : XPathExpression.Compile(relative_to);
+
+ AddTargets(map, input, baseOutputPath, output_XPath, linkValue, format_xpath, relative_to_xpath);
+
+ }
+
+ WriteMessage(MessageLevel.Info, String.Format("Indexed {0} art targets.", targets.Count));
+
+ }
+
+ private void AddTargets (string map, string input, string baseOutputPath, XPathExpression outputXPath, string link, XPathExpression formatXPath, XPathExpression relativeToXPath) {
+
+ XPathDocument document = new XPathDocument(map);
+
+ XPathNodeIterator items = document.CreateNavigator().Select("/*/item");
+ foreach (XPathNavigator item in items) {
+
+ string id = (string) item.Evaluate(artIdExpression);
+ string file = (string) item.Evaluate(artFileExpression);
+ string text = (string) item.Evaluate(artTextExpression);
+
+ id = id.ToLower();
+ string name = Path.GetFileName(file);
+
+ ArtTarget target = new ArtTarget();
+ target.Id = id;
+ target.InputPath = Path.Combine(input, file);
+ target.baseOutputPath = baseOutputPath;
+ target.OutputXPath = outputXPath;
+
+ if (string.IsNullOrEmpty(name)) target.LinkPath = link;
+ else target.LinkPath = string.Format("{0}/{1}", link, name);
+
+ target.Text = text;
+ target.Name = name;
+ target.FormatXPath = formatXPath;
+ target.RelativeToXPath = relativeToXPath;
+
+ targets[id] = target;
+ // targets.Add(id, target);
+ }
+
+ }
+
+ private XPathExpression artIdExpression = XPathExpression.Compile("string(@id)");
+ private XPathExpression artFileExpression = XPathExpression.Compile("string(image/@file)");
+ private XPathExpression artTextExpression = XPathExpression.Compile("string(image/altText)");
+
+ private Dictionary<string,ArtTarget> targets = new Dictionary<string,ArtTarget>();
+
+ public override void Apply (XmlDocument document, string id) {
+
+ XPathNodeIterator artLinkIterator = document.CreateNavigator().Select(artLinkExpression);
+ XPathNavigator[] artLinks = BuildComponentUtilities.ConvertNodeIteratorToArray(artLinkIterator);
+ foreach (XPathNavigator artLink in artLinks) {
+
+ string name = artLink.GetAttribute("target", String.Empty).ToLower();
+
+ if (targets.ContainsKey(name)) {
+ ArtTarget target = targets[name];
+
+ // evaluate the path
+ string path = document.CreateNavigator().Evaluate(target.OutputXPath).ToString();
+
+ if (target.baseOutputPath != null) path = Path.Combine(target.baseOutputPath, path);
+ string outputPath = Path.Combine(path, target.Name);
+
+ string targetDirectory = Path.GetDirectoryName(outputPath);
+
+ if (!Directory.Exists(targetDirectory)) Directory.CreateDirectory(targetDirectory);
+
+ if (File.Exists(target.InputPath)) {
+
+ if (File.Exists(outputPath)) {
+ File.SetAttributes(outputPath, FileAttributes.Normal);
+ }
+
+ File.Copy(target.InputPath, outputPath, true);
+ } else {
+ WriteMessage(MessageLevel.Warn, String.Format("The file '{0}' for the art target '{1}' was not found.", target.InputPath, name));
+ }
+
+ // Get the relative art path for HXF generation.
+ int index = target.LinkPath.IndexOf('/');
+ string artPath = target.LinkPath.Substring(index+1, target.LinkPath.Length - (index+1));
+
+ FileCreatedEventArgs fe = new FileCreatedEventArgs(artPath, Path.GetDirectoryName(path));
+ OnComponentEvent(fe);
+
+ XmlWriter writer = artLink.InsertAfter();
+
+ writer.WriteStartElement("img");
+ if (!String.IsNullOrEmpty(target.Text)) writer.WriteAttributeString("alt", target.Text);
+
+ if (target.FormatXPath == null) {
+ writer.WriteAttributeString("src", target.LinkPath);
+ }
+ else {
+ // WebDocs way, which uses the 'format' xpath expression to calculate the target path
+ // and then makes it relative to the current page if the 'relative-to' attribute is
+ // used.
+ string src = BuildComponentUtilities.EvalXPathExpr(document, target.FormatXPath, "key", Path.GetFileName(outputPath));
+ if (target.RelativeToXPath != null)
+ src = BuildComponentUtilities.GetRelativePath(src, BuildComponentUtilities.EvalXPathExpr(document, target.RelativeToXPath, "key", id));
+ writer.WriteAttributeString("src", src);
+ }
+
+ writer.WriteEndElement();
+
+ writer.Close();
+
+ artLink.DeleteSelf();
+
+ } else {
+ WriteMessage(MessageLevel.Warn, String.Format("Unknown art target '{0}'", name));
+ }
+
+ }
+
+ }
+
+ private static XPathExpression artLinkExpression = XPathExpression.Compile("//artLink");
+
+ }
+
+ internal class ArtTarget {
+
+ public string Id;
+
+ public string InputPath;
+
+ public string baseOutputPath;
+
+ public XPathExpression OutputXPath;
+
+ public string LinkPath;
+
+ public string Text;
+
+ public string Name;
+
+ public XPathExpression FormatXPath;
+
+ public XPathExpression RelativeToXPath;
+
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveConceptualLinksComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveConceptualLinksComponent.cs
new file mode 100644
index 0000000..2531e23
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveConceptualLinksComponent.cs
@@ -0,0 +1,448 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Text.RegularExpressions;
+using System.Web;
+
+
+namespace Microsoft.Ddue.Tools {
+
+ public class ResolveConceptualLinksComponent : BuildComponent {
+
+ // Instantiation logic
+
+ public ResolveConceptualLinksComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ string showBrokenLinkTextValue = configuration.GetAttribute("showBrokenLinkText", String.Empty);
+ if (!String.IsNullOrEmpty(showBrokenLinkTextValue)) showBrokenLinkText = Convert.ToBoolean(showBrokenLinkTextValue);
+
+ XPathNodeIterator targetsNodes = configuration.Select("targets");
+ foreach (XPathNavigator targetsNode in targetsNodes) {
+
+ // the base directory containing target; required
+ string baseValue = targetsNode.GetAttribute("base", String.Empty);
+ if (String.IsNullOrEmpty(baseValue)) WriteMessage(MessageLevel.Error, "Every targets element must have a base attribute that specifies the path to a directory of target metadata files.");
+ baseValue = Environment.ExpandEnvironmentVariables(baseValue);
+ if (!Directory.Exists(baseValue)) WriteMessage(MessageLevel.Error, String.Format("The specified target metadata directory '{0}' does not exist.", baseValue));
+
+ // an xpath expression to construct a file name
+ // (not currently used; pattern is hard-coded to $target.cmp.xml
+ string filesValue = targetsNode.GetAttribute("files", String.Empty);
+
+ // an xpath expression to construct a url
+ string urlValue = targetsNode.GetAttribute("url", String.Empty);
+ XPathExpression urlExpression;
+ if (String.IsNullOrEmpty(urlValue)) {
+ urlExpression = XPathExpression.Compile("concat(/metadata/topic/@id,'.htm')");
+ } else {
+ urlExpression = CompileXPathExpression(urlValue);
+ }
+
+ // an xpath expression to construct link text
+ string textValue = targetsNode.GetAttribute("text", String.Empty);
+ XPathExpression textExpression;
+ if (String.IsNullOrEmpty(textValue)) {
+ textExpression = XPathExpression.Compile("string(/metadata/topic/title)");
+ } else {
+ textExpression = CompileXPathExpression(textValue);
+ }
+
+ // the type of link to create to targets found in the directory; required
+ string typeValue = targetsNode.GetAttribute("type", String.Empty);
+ if (String.IsNullOrEmpty(typeValue)) WriteMessage(MessageLevel.Error, "Every targets element must have a type attribute that specifies what kind of link to create to targets found in that directory.");
+
+ // convert the link type to an enumeration member
+ LinkType type = LinkType.None;
+ try {
+ type = (LinkType) Enum.Parse(typeof(LinkType), typeValue, true);
+ } catch (ArgumentException) {
+ WriteMessage(MessageLevel.Error, String.Format("'{0}' is not a valid link type.", typeValue));
+ }
+
+ // we have all the required information; create a TargetDirectory and add it to our collection
+ TargetDirectory targetDirectory = new TargetDirectory(baseValue, urlExpression, textExpression, type);
+ targetDirectories.Add(targetDirectory);
+
+ }
+
+ WriteMessage(MessageLevel.Info, String.Format("Collected {0} targets directories.", targetDirectories.Count));
+
+ }
+
+ private XPathExpression CompileXPathExpression (string xpath) {
+ XPathExpression expression = null;
+ try {
+ expression = XPathExpression.Compile(xpath);
+ } catch (ArgumentException e) {
+ WriteMessage(MessageLevel.Error, String.Format("'{0}' is not a valid XPath expression. The error message is: {1}", xpath, e.Message));
+ } catch (XPathException e) {
+ WriteMessage(MessageLevel.Error, String.Format("'{0}' is not a valid XPath expression. The error message is: {1}", xpath, e.Message));
+ }
+ return (expression);
+ }
+
+ // Conceptual link resolution logic
+
+ public override void Apply (XmlDocument document, string key) {
+ ResolveConceptualLinks(document, key);
+ }
+
+ private bool showBrokenLinkText = false;
+
+ private string BrokenLinkDisplayText (string target, string text) {
+ if (showBrokenLinkText) {
+ return(String.Format("{0}", text));
+ } else {
+ return(String.Format("[{0}]", target));
+ }
+ }
+
+ private TargetDirectoryCollection targetDirectories = new TargetDirectoryCollection();
+
+ private static XPathExpression conceptualLinks = XPathExpression.Compile("//conceptualLink");
+
+ private static Regex validGuid = new Regex(@"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", RegexOptions.Compiled);
+
+ private void ResolveConceptualLinks (XmlDocument document, string key) {
+
+ // find links
+ XPathNodeIterator linkIterator = document.CreateNavigator().Select(conceptualLinks);
+
+ // copy them to an array, because enumerating through an XPathNodeIterator
+ // fails when the nodes in it are altered
+ XPathNavigator[] linkNodes = BuildComponentUtilities.ConvertNodeIteratorToArray(linkIterator);
+
+ foreach (XPathNavigator linkNode in linkNodes) {
+
+ ConceptualLinkInfo link = ConceptualLinkInfo.Create(linkNode);
+
+ // determine url, text, and link type
+ string url = null;
+ string text = null;
+ LinkType type = LinkType.None;
+ bool isValidLink = validGuid.IsMatch(link.Target);
+ if (isValidLink) {
+ // a valid link; try to fetch target info
+ TargetInfo target = GetTargetInfoFromCache(link.Target.ToLower());
+ if (target == null) {
+ // no target found; issue warning, set link style to none, and text to in-source fall-back
+ //type = LinkType.None;
+ type = LinkType.Index;
+ text = BrokenLinkDisplayText(link.Target, link.Text);
+ WriteMessage(MessageLevel.Warn, String.Format("Unknown conceptual link target '{0}'.", link.Target));
+ } else {
+ // found target; get url, text, and type from stored info
+ url = target.Url;
+ text = target.Text;
+ type = target.Type;
+ }
+ } else {
+ // not a valid link; issue warning, set link style to none, and text to invalid target
+ //type = LinkType.None;
+ type = LinkType.Index;
+ text = BrokenLinkDisplayText(link.Target, link.Text);
+ WriteMessage(MessageLevel.Warn, String.Format("Invalid conceptual link target '{0}'.", link.Target));
+ }
+
+ // write opening link tag and target info
+ XmlWriter writer = linkNode.InsertAfter();
+ switch (type) {
+ case LinkType.None:
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nolink");
+ break;
+ case LinkType.Local:
+ writer.WriteStartElement("a");
+ writer.WriteAttributeString("href", url);
+ break;
+ case LinkType.Index:
+ writer.WriteStartElement("mshelp", "link", "http://msdn.microsoft.com/mshelp");
+ writer.WriteAttributeString("keywords", link.Target.ToLower());
+ writer.WriteAttributeString("tabindex", "0");
+ break;
+ }
+
+ // write the link text
+ writer.WriteString(text);
+
+ // write the closing link tag
+ writer.WriteEndElement();
+ writer.Close();
+
+ // delete the original tag
+ linkNode.DeleteSelf();
+ }
+ }
+
+
+
+
+ // a simple caching system for target names
+
+ private TargetInfo GetTargetInfoFromCache (string target) {
+
+ TargetInfo info;
+ if (!cache.TryGetValue(target, out info)) {
+ info = targetDirectories.GetTargetInfo(target + ".cmp.xml");
+
+ if (cache.Count >= cacheSize) cache.Clear();
+
+ cache.Add(target, info);
+ }
+
+ return(info);
+
+ }
+
+ private static int cacheSize = 1000;
+
+ private Dictionary<string,TargetInfo> cache = new Dictionary<string,TargetInfo>(cacheSize);
+
+ //private CustomContext context = new CustomContext();
+
+ }
+
+ // different types of links
+
+ internal enum LinkType {
+ None, // not active
+ Local, // a href
+ Index // mshelp:link keyword
+ //Regex // regular expression with match/replace
+ }
+
+ // a representation of a targets directory, along with all the assoicated expressions used to
+ // find target metadat files in it, and extract urls and link text from those files
+
+ internal class TargetDirectory {
+
+ private string directory;
+
+ private XPathExpression fileExpression = XPathExpression.Compile("concat($target,'.cmp.htm')");
+
+ private XPathExpression urlExpression = XPathExpression.Compile("concat(/metadata/topic/@id,'.htm')");
+
+ private XPathExpression textExpression = XPathExpression.Compile("string(/metadata/topic/title)");
+
+ private LinkType type;
+
+ public string Directory {
+ get {
+ return (directory);
+ }
+ }
+
+ public XPathExpression UrlExpression {
+ get {
+ return (urlExpression);
+ }
+ }
+
+ public XPathExpression TextExpression {
+ get {
+ return (textExpression);
+ }
+ }
+
+
+ public LinkType LinkType {
+ get {
+ return (type);
+ }
+ }
+
+ public TargetDirectory (string directory, LinkType type) {
+ if (directory == null) throw new ArgumentNullException("directory");
+ this.directory = directory;
+ this.type = type;
+ }
+
+ public TargetDirectory (string directory, XPathExpression urlExpression, XPathExpression textExpression, LinkType type) {
+ if (directory == null) throw new ArgumentNullException("directory");
+ if (urlExpression == null) throw new ArgumentNullException("urlExpression");
+ if (textExpression == null) throw new ArgumentNullException("textExpression");
+ this.directory = directory;
+ this.urlExpression = urlExpression;
+ this.textExpression = textExpression;
+ this.type = type;
+ }
+
+ private XPathDocument GetDocument (string file) {
+ string path = Path.Combine(directory, file);
+ if (File.Exists(path)) {
+ XPathDocument document = new XPathDocument(path);
+ return (document);
+ } else {
+ return (null);
+ }
+ }
+
+ public TargetInfo GetTargetInfo (string file) {
+ XPathDocument document = GetDocument(file);
+ if (document == null) {
+ return(null);
+ } else {
+ XPathNavigator context = document.CreateNavigator();
+
+ string url = context.Evaluate(urlExpression).ToString();
+ string text = context.Evaluate(textExpression).ToString();
+ TargetInfo info = new TargetInfo(url, text, type);
+ return(info);
+ }
+ }
+
+ public TargetInfo GetTargetInfo (XPathNavigator linkNode, CustomContext context) {
+
+ // compute the metadata file name to open
+ XPathExpression localFileExpression = fileExpression.Clone();
+ localFileExpression.SetContext(context);
+ string file = linkNode.Evaluate(localFileExpression).ToString();
+ if (String.IsNullOrEmpty(file)) return (null);
+
+ // load the metadata file
+ XPathDocument metadataDocument = GetDocument(file);
+ if (metadataDocument == null) return (null);
+
+ // querry the metadata file for the target url and link text
+ XPathNavigator metadataNode = metadataDocument.CreateNavigator();
+ XPathExpression localUrlExpression = urlExpression.Clone();
+ localUrlExpression.SetContext(context);
+ string url = metadataNode.Evaluate(localUrlExpression).ToString();
+ XPathExpression localTextExpression = textExpression.Clone();
+ localTextExpression.SetContext(context);
+ string text = metadataNode.Evaluate(localTextExpression).ToString();
+
+ // return this information
+ TargetInfo info = new TargetInfo(url, text, type);
+ return (info);
+ }
+
+
+
+ }
+
+ // our collection of targets directories
+
+ internal class TargetDirectoryCollection {
+
+ public TargetDirectoryCollection() {}
+
+ private List<TargetDirectory> targetDirectories = new List<TargetDirectory>();
+
+ public int Count {
+ get {
+ return(targetDirectories.Count);
+ }
+ }
+
+ public void Add (TargetDirectory targetDirectory) {
+ targetDirectories.Add(targetDirectory);
+ }
+
+ public TargetInfo GetTargetInfo (string file) {
+ foreach (TargetDirectory targetDirectory in targetDirectories) {
+ TargetInfo info = targetDirectory.GetTargetInfo(file);
+ if (info != null) return (info);
+ }
+ return (null);
+ }
+
+ public TargetInfo GetTargetInfo (XPathNavigator linkNode, CustomContext context) {
+ foreach (TargetDirectory targetDirectory in targetDirectories) {
+ TargetInfo info = targetDirectory.GetTargetInfo(linkNode, context);
+ if (info != null) return (info);
+ }
+ return (null);
+ }
+
+ }
+
+ // a representation of a resolved target, containing all the information necessary to actually write out the link
+
+ internal class TargetInfo {
+
+ private string url;
+
+ private string text;
+
+ private LinkType type;
+
+ public string Url {
+ get {
+ return(url);
+ }
+ }
+
+ public string Text {
+ get {
+ return(text);
+ }
+ }
+
+ public LinkType Type {
+ get {
+ return(type);
+ }
+ }
+
+ internal TargetInfo (string url, string text, LinkType type) {
+ if (url == null) throw new ArgumentNullException("url");
+ if (text == null) throw new ArgumentNullException("url");
+ this.url = url;
+ this.text = text;
+ this.type = type;
+ }
+ }
+
+ // a representation of a conceptual link
+
+ internal class ConceptualLinkInfo {
+
+ private string target;
+
+ private string text;
+
+ private bool showText = false;
+
+ public string Target {
+ get {
+ return (target);
+ }
+ }
+
+ public string Text {
+ get {
+ return (text);
+ }
+ }
+
+ public bool ShowText {
+ get {
+ return (showText);
+ }
+ }
+
+ private ConceptualLinkInfo () { }
+
+ public static ConceptualLinkInfo Create (XPathNavigator node) {
+ if (node == null) throw new ArgumentNullException("node");
+
+ ConceptualLinkInfo info = new ConceptualLinkInfo();
+
+ info.target = node.GetAttribute("target", String.Empty);
+ info.text = node.ToString();
+
+ return(info);
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveReferenceLinksComponent2.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveReferenceLinksComponent2.cs
new file mode 100644
index 0000000..22587ac
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveReferenceLinksComponent2.cs
@@ -0,0 +1,497 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.XPath;
+
+
+namespace Microsoft.Ddue.Tools {
+
+ // replace the old component with the new one
+ public class ResolveReferenceLinksComponent : ResolveReferenceLinksComponent2 {
+
+ public ResolveReferenceLinksComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) { }
+
+ }
+
+ public class ResolveReferenceLinksComponent2 : BuildComponent {
+
+ // instantiation logic
+
+ public ResolveReferenceLinksComponent2 (BuildAssembler assembler, XPathNavigator configuration)
+ : base(assembler, configuration) {
+
+ // base-url is an xpath expression applied against the current document to pick up the save location of the
+ // document. If specified, local links will be made relative to the base-url.
+ string baseUrlValue = configuration.GetAttribute("base-url", String.Empty);
+ if (!String.IsNullOrEmpty(baseUrlValue))
+ baseUrl = XPathExpression.Compile(baseUrlValue);
+
+ // url-format is a string format that is used to format the value of local href attributes. The default is
+ // "{0}.htm" for backwards compatibility.
+ string hrefFormatValue = configuration.GetAttribute("href-format", String.Empty);
+ if (!String.IsNullOrEmpty(hrefFormatValue))
+ hrefFormat = hrefFormatValue;
+
+ // the container XPath can be replaced; this is useful
+ string containerValue = configuration.GetAttribute("container", String.Empty);
+ if (!String.IsNullOrEmpty(containerValue)) XmlTargetCollectionUtilities.ContainerExpression = containerValue;
+
+ targets = new TargetCollection();
+ resolver = new LinkTextResolver(targets);
+
+ XPathNodeIterator targets_nodes = configuration.Select("targets");
+ foreach (XPathNavigator targets_node in targets_nodes) {
+
+ // get target type
+ string typeValue = targets_node.GetAttribute("type", String.Empty);
+ if (String.IsNullOrEmpty(typeValue)) WriteMessage(MessageLevel.Error, "Each targets element must have a type attribute that specifies which type of links to create.");
+
+ LinkType2 type = LinkType2.None;
+ try {
+ type = (LinkType2)Enum.Parse(typeof(LinkType2), typeValue, true);
+ if ((type == LinkType2.Msdn) && (msdn == null)) {
+ WriteMessage(MessageLevel.Info, "Creating MSDN URL resolver.");
+ msdn = new MsdnResolver();
+ }
+ } catch (ArgumentException) {
+ WriteMessage(MessageLevel.Error, String.Format("'{0}' is not a supported reference link type.", typeValue));
+ }
+
+ // get base directory
+ string baseValue = targets_node.GetAttribute("base", String.Empty);
+
+ // get file pattern
+ string filesValue = targets_node.GetAttribute("files", String.Empty);
+ if (String.IsNullOrEmpty(filesValue)) WriteMessage(MessageLevel.Error, "Each targets element must have a files attribute specifying which target files to load.");
+
+ // determine whether to search recursively
+ bool recurse = false;
+ string recurseValue = targets_node.GetAttribute("recurse", String.Empty);
+ if (!String.IsNullOrEmpty(recurseValue)) {
+ if (String.Compare(recurseValue, Boolean.TrueString, true) == 0) {
+ recurse = true;
+ } else if (String.Compare(recurseValue, Boolean.FalseString, true) == 0) {
+ recurse = false;
+ } else {
+ WriteMessage(MessageLevel.Error, String.Format("On the targets element, recurse='{0}' is not an allowed value.", recurseValue));
+ }
+ }
+
+ // turn baseValue and filesValue into directoryPath and filePattern
+ string fullPath;
+ if (String.IsNullOrEmpty(baseValue)) {
+ fullPath = filesValue;
+ } else {
+ fullPath = Path.Combine(baseValue, filesValue);
+ }
+ fullPath = Environment.ExpandEnvironmentVariables(fullPath);
+ string directoryPath = Path.GetDirectoryName(fullPath);
+ if (String.IsNullOrEmpty(directoryPath)) directoryPath = Environment.CurrentDirectory;
+ string filePattern = Path.GetFileName(fullPath);
+
+ // verify that directory exists
+ if (!Directory.Exists(directoryPath)) WriteMessage(MessageLevel.Error, String.Format("The targets directory '{0}' does not exist.", directoryPath));
+
+ // add the specified targets from the directory
+ WriteMessage(MessageLevel.Info, String.Format("Searching directory '{0}' for targets files of the form '{1}'.", directoryPath, filePattern));
+ AddTargets(directoryPath, filePattern, recurse, type);
+
+ }
+
+ WriteMessage(MessageLevel.Info, String.Format("Loaded {0} reference targets.", targets.Count));
+
+ string locale_value = configuration.GetAttribute("locale", String.Empty);
+ if (!String.IsNullOrEmpty(locale_value) && msdn != null) msdn.Locale = locale_value;
+
+ string target_value = configuration.GetAttribute("linkTarget", String.Empty);
+ if (!String.IsNullOrEmpty(target_value)) linkTarget = target_value;
+ }
+
+ private void AddTargets (string directory, string filePattern, bool recurse, LinkType2 type) {
+ string[] files = Directory.GetFiles(directory, filePattern);
+ foreach (string file in files) {
+ AddTargets(file, type);
+ }
+ if (recurse) {
+ string[] subdirectories = Directory.GetDirectories(directory);
+ foreach (string subdirectory in subdirectories) {
+ AddTargets(subdirectory, filePattern, recurse, type);
+ }
+ }
+ }
+
+ private void AddTargets (string file, LinkType2 type) {
+ try {
+ XPathDocument document = new XPathDocument(file);
+ XmlTargetCollectionUtilities.AddTargets(targets, document.CreateNavigator(), type);
+ } catch (XmlSchemaException e) {
+ WriteMessage(MessageLevel.Error, String.Format("The reference targets file '{0}' is not valid. The error message is: {1}", file, BuildComponentUtilities.GetExceptionMessage(e)));
+ } catch (XmlException e) {
+ WriteMessage(MessageLevel.Error, String.Format("The reference targets file '{0}' is not well-formed XML. The error message is: {1}", file, BuildComponentUtilities.GetExceptionMessage(e)));
+ } catch (IOException e) {
+ WriteMessage(MessageLevel.Error, String.Format("An access error occured while opening the reference targets file '{0}'. The error message is: {1}", file, BuildComponentUtilities.GetExceptionMessage(e)));
+ }
+ }
+
+ private string linkTarget = "_blank";
+
+ // target information storage
+
+ private TargetCollection targets;
+
+ private LinkTextResolver resolver;
+
+ private static XPathExpression referenceLinkExpression = XPathExpression.Compile("//referenceLink");
+
+ // WebDocs target url formatting
+
+ private XPathExpression baseUrl;
+
+ private string hrefFormat = "{0}.htm";
+
+ // component logic
+
+ public override void Apply (XmlDocument document, string key) {
+
+ // XmlNodeList link_nodes = document.SelectNodes("//referenceLink");
+ XPathNodeIterator linkIterator = document.CreateNavigator().Select(referenceLinkExpression);
+
+ XPathNavigator[] linkNodes = BuildComponentUtilities.ConvertNodeIteratorToArray(linkIterator);
+
+ foreach (XPathNavigator linkNode in linkNodes) {
+
+ // extract link information
+ ReferenceLinkInfo2 link = ReferenceLinkInfo2.Create(linkNode);
+
+ if (link == null) {
+ WriteMessage(MessageLevel.Warn, "Invalid referenceLink element.");
+ } else {
+
+ // determine target, link type, and display options
+ string targetId = link.Target;
+ DisplayOptions options = link.DisplayOptions;
+ LinkType2 type = LinkType2.None;
+
+ Target target = targets[targetId];
+ if (target == null) {
+ // no such target known; set link type to none and warn
+ type = LinkType2.None;
+ WriteMessage(MessageLevel.Warn, String.Format("Unknown reference link target '{0}'.", targetId));
+ } else {
+ // if overload is prefered and found, change targetId and make link options hide parameters
+ if (link.PreferOverload) {
+
+ bool isConversionOperator = false;
+
+ MethodTarget method = target as MethodTarget;
+ if (method != null) {
+ isConversionOperator = method.conversionOperator;
+ }
+
+ MemberTarget member = target as MemberTarget;
+
+ // if conversion operator is found, always link to individual topic.
+ if ((member != null) && (!String.IsNullOrEmpty(member.OverloadId)) && !isConversionOperator) {
+ Target overloadTarget = targets[member.OverloadId];
+ if (overloadTarget != null) {
+ target = overloadTarget;
+ targetId = overloadTarget.Id;
+ }
+ }
+
+ // if individual conversion operator is found, always display parameters.
+ if (isConversionOperator && member != null && (!string.IsNullOrEmpty(member.OverloadId))) {
+ options = options | DisplayOptions.ShowParameters;
+ } else {
+ options = options & ~DisplayOptions.ShowParameters;
+ }
+ }
+
+ // get stored link type
+ type = target.DefaultLinkType;
+
+ // if link type is local or index, determine which
+ if (type == LinkType2.LocalOrIndex) {
+ if ((key != null) && targets.Contains(key) && (target.Container == targets[key].Container)) {
+ type = LinkType2.Local;
+ } else {
+ type = LinkType2.Index;
+ }
+ }
+ }
+
+ // links to this page are not live
+ if (targetId == key) {
+ type = LinkType2.Self;
+ } else if ((target != null) && (key != null) && targets.Contains(key) && (target.File == targets[key].File)) {
+ type = LinkType2.Self;
+ }
+
+ // get msdn endpoint, if needed
+ string msdnUrl = null;
+ if (type == LinkType2.Msdn) {
+ if ((msdn == null) || (msdn.IsDisabled)) {
+ // no msdn resolver
+ } else {
+ msdnUrl = msdn.GetMsdnUrl(targetId);
+ if (String.IsNullOrEmpty(msdnUrl)) {
+ WriteMessage(MessageLevel.Warn, String.Format("MSDN URL not found for target '{0}'.", targetId));
+ }
+ }
+ if (String.IsNullOrEmpty(msdnUrl)) type = LinkType2.None;
+ }
+
+ // write opening link tag and target info
+ XmlWriter writer = linkNode.InsertAfter();
+ switch (type) {
+ case LinkType2.None:
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nolink");
+ break;
+ case LinkType2.Self:
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "selflink");
+ break;
+ case LinkType2.Local:
+ // format link with prefix and/or postfix
+ string href = String.Format(hrefFormat, target.File);
+
+ // make link relative, if we have a baseUrl
+ if (baseUrl != null)
+ href = BuildComponentUtilities.GetRelativePath(href, BuildComponentUtilities.EvalXPathExpr(document, baseUrl, "key", key));
+
+ writer.WriteStartElement("a");
+ writer.WriteAttributeString("href", href);
+ break;
+ case LinkType2.Index:
+ writer.WriteStartElement("mshelp", "link", "http://msdn.microsoft.com/mshelp");
+ writer.WriteAttributeString("keywords", targetId);
+ writer.WriteAttributeString("tabindex", "0");
+ break;
+ case LinkType2.Msdn:
+ writer.WriteStartElement("a");
+ writer.WriteAttributeString("href", msdnUrl);
+ writer.WriteAttributeString("target", linkTarget);
+ break;
+ }
+
+ // write the link text
+ if (String.IsNullOrEmpty(link.DisplayTarget)) {
+ if (link.Contents == null) {
+ if (target != null) {
+ resolver.WriteTarget(target, options, writer);
+ } else {
+ //Console.WriteLine("Attemting to create reference");
+ Reference reference = TextReferenceUtilities.CreateReference(targetId);
+ //Console.WriteLine("Returned");
+ if (reference is InvalidReference) WriteMessage(MessageLevel.Warn, String.Format("Invalid reference link target '{0}'.", targetId));
+ resolver.WriteReference(reference, options, writer);
+ }
+ } else {
+ // write contents to writer
+ link.Contents.WriteSubtree(writer);
+ }
+ } else {
+ //Console.WriteLine("Display target = {0}", link.DisplayTarget);
+ if ((String.Compare(link.DisplayTarget, "content", true) == 0) && (link.Contents != null)) {
+ // Use the contents as an XML representation of the display target
+
+ //Console.WriteLine(link.Contents.NodeType);
+ Reference reference = XmlTargetCollectionUtilities.CreateReference(link.Contents);
+ //Console.WriteLine(reference.GetType().FullName);
+ resolver.WriteReference(reference, options, writer);
+ } if ((String.Compare(link.DisplayTarget, "format", true) == 0) && (link.Contents != null)) {
+ // Use the contents as a format string for the display target
+
+ string format = link.Contents.OuterXml;
+ //Console.WriteLine("format = {0}", format);
+
+ string input = null;
+ StringWriter textStore = new StringWriter();
+ try {
+ XmlWriterSettings settings = new XmlWriterSettings();
+ settings.ConformanceLevel = ConformanceLevel.Fragment;
+
+ XmlWriter xmlStore = XmlWriter.Create(textStore, settings);
+ try {
+ if (target != null) {
+ resolver.WriteTarget(target, options, xmlStore);
+ } else {
+ Reference reference = TextReferenceUtilities.CreateReference(targetId);
+ resolver.WriteReference(reference, options, xmlStore);
+ }
+ } finally {
+ xmlStore.Close();
+ }
+ input = textStore.ToString();
+ } finally {
+ textStore.Close();
+ }
+ //Console.WriteLine("input = {0}", input);
+
+ string output = String.Format(format, input);
+ //Console.WriteLine("output = {0}", output);
+
+ XmlDocumentFragment fragment = document.CreateDocumentFragment();
+ fragment.InnerXml = output;
+ fragment.WriteTo(writer);
+
+ //writer.WriteRaw(output);
+ }
+ else if ((String.Compare(link.DisplayTarget, "extension", true) == 0) && (link.Contents != null))
+ {
+ Reference extMethodReference = XmlTargetCollectionUtilities.CreateExtensionMethodReference(link.Contents);
+ resolver.WriteReference(extMethodReference, options, writer);
+ } else {
+ // Use the display target value as a CER for the display target
+
+ TextReferenceUtilities.SetGenericContext(key);
+ Reference reference = TextReferenceUtilities.CreateReference(link.DisplayTarget);
+ //Console.WriteLine("Reference is {0}", reference.GetType().FullName);
+ resolver.WriteReference(reference, options, writer);
+ }
+ }
+
+ // write the closing link tag
+ writer.WriteEndElement();
+ writer.Close();
+ }
+
+ // delete the original tag
+ linkNode.DeleteSelf();
+
+ }
+
+ }
+
+ // msdn resolver
+
+ private MsdnResolver msdn = null;
+
+
+ }
+
+
+ internal class ReferenceLinkInfo2 {
+
+ // stored data
+
+ private string target;
+
+ private string displayTarget;
+
+ private DisplayOptions options = DisplayOptions.Default;
+
+ private bool preferOverload = false;
+
+ private XPathNavigator contents;
+
+ // data accessors
+
+ public string Target {
+ get {
+ return(target);
+ }
+ }
+
+ public string DisplayTarget {
+ get {
+ return(displayTarget);
+ }
+ }
+
+ public DisplayOptions DisplayOptions {
+ get {
+ return(options);
+ }
+ }
+
+ public bool PreferOverload {
+ get {
+ return(preferOverload);
+ }
+ }
+
+ public XPathNavigator Contents {
+ get {
+ return(contents);
+ }
+ }
+
+ // creation logic
+
+ private ReferenceLinkInfo2 () {}
+
+ public static ReferenceLinkInfo2 Create (XPathNavigator element) {
+ if (element == null) throw new ArgumentNullException("element");
+
+ ReferenceLinkInfo2 info = new ReferenceLinkInfo2();
+
+ info.target = element.GetAttribute("target", String.Empty);
+ if (String.IsNullOrEmpty(info.target)) return(null);
+
+ info.displayTarget = element.GetAttribute("display-target", String.Empty);
+
+ string showContainer = element.GetAttribute("show-container", String.Empty);
+ if (String.IsNullOrEmpty(showContainer)) showContainer = element.GetAttribute("qualified", String.Empty);
+ if (!String.IsNullOrEmpty(showContainer)) {
+ if (String.Compare(showContainer, Boolean.TrueString, true) == 0) {
+ info.options = info.options | DisplayOptions.ShowContainer;
+ } else if (String.Compare(showContainer, Boolean.FalseString, true) == 0) {
+ info.options = info.options & ~DisplayOptions.ShowContainer;
+ } else {
+ return(null);
+ }
+ }
+
+ string showTemplates = element.GetAttribute("show-templates", String.Empty);
+ if (!String.IsNullOrEmpty(showTemplates)) {
+ if (String.Compare(showTemplates, Boolean.TrueString, true) == 0) {
+ info.options = info.options | DisplayOptions.ShowTemplates;
+ } else if (String.Compare(showTemplates, Boolean.FalseString, true) == 0) {
+ info.options = info.options & ~DisplayOptions.ShowTemplates;
+ } else {
+ return(null);
+ }
+ }
+
+ string showParameters = element.GetAttribute("show-parameters", String.Empty);
+ if (!String.IsNullOrEmpty(showParameters)) {
+ if (String.Compare(showParameters, Boolean.TrueString, true) == 0) {
+ info.options = info.options | DisplayOptions.ShowParameters;
+ } else if (String.Compare(showParameters, Boolean.FalseString, true) == 0) {
+ info.options = info.options & ~DisplayOptions.ShowParameters;
+ } else {
+ return(null);
+ }
+ }
+
+
+ string preferOverload = element.GetAttribute("prefer-overload", String.Empty);
+ if (String.IsNullOrEmpty(preferOverload)) preferOverload = element.GetAttribute("auto-upgrade", String.Empty);
+ if (!String.IsNullOrEmpty(preferOverload)) {
+ if (String.Compare(preferOverload, Boolean.TrueString, true) == 0) {
+ info.preferOverload = true;
+ } else if (String.Compare(preferOverload, Boolean.FalseString, true) == 0) {
+ info.preferOverload = false;
+ } else {
+ return(null);
+ }
+ }
+
+ info.contents = element.Clone();
+ if (!info.contents.MoveToFirstChild()) info.contents = null;
+
+ return(info);
+ }
+
+ }
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SaveComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SaveComponent.cs
new file mode 100644
index 0000000..8b8fea9
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SaveComponent.cs
@@ -0,0 +1,149 @@
+// 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.
+
+using System;
+using System.Configuration;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+
+using System.IO;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class SaveComponent : BuildComponent {
+
+ private CustomContext context = new CustomContext();
+
+ private XPathExpression path_expression;
+
+ private XPathExpression select_expression;
+
+ private XmlWriterSettings settings = new XmlWriterSettings();
+
+ public SaveComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ // load the target path format
+ XPathNavigator save_node = configuration.SelectSingleNode("save");
+ if (save_node == null) throw new ConfigurationErrorsException("When instantiating a save component, you must specify a the target file using the <save> element.");
+
+ string base_value = save_node.GetAttribute("base", String.Empty);
+ if (!String.IsNullOrEmpty(base_value)) {
+ basePath = Path.GetFullPath(Environment.ExpandEnvironmentVariables(base_value));
+ }
+
+ string path_value = save_node.GetAttribute("path", String.Empty);
+ if (String.IsNullOrEmpty(path_value)) WriteMessage(MessageLevel.Error, "Each save element must have a path attribute specifying an XPath that evaluates to the location to save the file.");
+ path_expression = XPathExpression.Compile(path_value);
+
+ string select_value = save_node.GetAttribute("select", String.Empty);
+ if (!String.IsNullOrEmpty(select_value))
+ select_expression = XPathExpression.Compile(select_value);
+
+ settings.Encoding = Encoding.UTF8;
+
+ string indent_value = save_node.GetAttribute("indent", String.Empty);
+ if (!String.IsNullOrEmpty(indent_value)) settings.Indent = Convert.ToBoolean(indent_value);
+
+ string omit_value = save_node.GetAttribute("omit-xml-declaration", String.Empty);
+ if (!String.IsNullOrEmpty(omit_value)) settings.OmitXmlDeclaration = Convert.ToBoolean(omit_value);
+
+ linkPath = save_node.GetAttribute("link", String.Empty);
+ if (String.IsNullOrEmpty(linkPath)) linkPath = "../html";
+
+ // encoding
+
+ settings.CloseOutput = true;
+
+ }
+
+ private string basePath = null;
+
+ private string linkPath = null;
+
+ public override void Apply (XmlDocument document, string key) {
+
+ // set the evaluation context
+ context["key"] = key;
+
+ XPathExpression path_xpath = path_expression.Clone();
+ path_xpath.SetContext(context);
+
+ // evaluate the path
+ string path = document.CreateNavigator().Evaluate(path_xpath).ToString();
+ string file = Path.GetFileName(path);
+
+ string fileLinkPath = Path.Combine(linkPath, file);
+ if (basePath != null) path = Path.Combine(basePath, path);
+
+
+ // *SECURIY* The path name may be derived from user entered meta data in Doc Studio and as such
+ // it is not trustworthy. To pass, the path must be inside the directory tree base_directory
+ // (which is the current directory if a path is not specified).
+
+ // This test is causing problems
+ /*
+ string absoluteBasePath = (basePath == null) ? Directory.GetCurrentDirectory() : Path.GetFullPath(basePath);
+ string targetPath = Path.GetDirectoryName(path);
+ if (!targetPath.StartsWith(absoluteBasePath, StringComparison.CurrentCultureIgnoreCase)) {
+ WriteMessage(MessageLevel.Error, string.Format("Cannot save document outside of base directory: {0}", targetPath));
+ return;
+ }
+ */
+ string targetDirectory = Path.GetDirectoryName(path);
+ if (!Directory.Exists(targetDirectory)) Directory.CreateDirectory(targetDirectory);
+
+ // save the document
+ // select_expression determines which nodes get saved. If there is no select_expression
+ // we simply save the root node as before. If there is a select_expression, we evaluate the
+ // xpath expression and save the resulting node set. The select expression also enables the
+ // "literal-text" processing instruction, which outputs its content as unescaped text.
+ if (select_expression == null) {
+ XmlNode doctype = document.DocumentType;
+ try {
+ //Console.WriteLine("path = '{0}'", path);
+ //document.Save(path);
+
+ using (XmlWriter writer = XmlWriter.Create(path, settings)) {
+ document.Save(writer);
+ }
+
+ } catch (IOException e) {
+ WriteMessage(MessageLevel.Error, String.Format("An access error occured while attempting to save to the file '{0}'. The error message is: {1}", path, BuildComponentUtilities.GetExceptionMessage(e)));
+ } catch (XmlException e) {
+ WriteMessage(MessageLevel.Error, String.Format("Invalid XML was written to the output file '{0}'. The error message is: '{1}'", path, BuildComponentUtilities.GetExceptionMessage(e)));
+ }
+
+ // Get the relative html path for HXF generation.
+ int index = fileLinkPath.IndexOf('/');
+ string htmlPath = fileLinkPath.Substring(index + 1, fileLinkPath.Length - (index + 1));
+
+ FileCreatedEventArgs fe = new FileCreatedEventArgs(htmlPath, Path.GetDirectoryName(targetDirectory));
+ OnComponentEvent(fe);
+ }
+ else {
+ // IMPLEMENTATION NOTE: The separate StreamWriter is used to maintain XML indenting.
+ // Without it the XmlWriter won't honor our indent settings after plain text nodes have been
+ // written.
+ settings.ConformanceLevel = ConformanceLevel.Auto;
+ using (StreamWriter output = File.CreateText(path)) {
+ using (XmlWriter writer = XmlWriter.Create(output, settings)) {
+ XPathExpression select_xpath = select_expression.Clone();
+ select_xpath.SetContext(context);
+ XPathNodeIterator ni = document.CreateNavigator().Select(select_expression);
+ while (ni.MoveNext()) {
+ if (ni.Current.NodeType == XPathNodeType.ProcessingInstruction && ni.Current.Name.Equals("literal-text")) {
+ writer.Flush();
+ output.Write(ni.Current.Value);
+ }
+ else
+ ni.Current.WriteSubtree(writer);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SharedContentComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SharedContentComponent.cs
new file mode 100644
index 0000000..2a255fc
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SharedContentComponent.cs
@@ -0,0 +1,380 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Schema;
+
+// still have problems with spaces
+
+namespace Microsoft.Ddue.Tools {
+
+ public class SharedContentComponent : BuildComponent {
+
+ public SharedContentComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ // get context
+ context = GetContext(configuration);
+
+ // get the tags to be resolved
+ XPathNodeIterator resolve_nodes = configuration.Select("replace");
+ foreach (XPathNavigator resolve_node in resolve_nodes) {
+ string path = resolve_node.GetAttribute("elements", String.Empty);
+ if (String.IsNullOrEmpty(path)) path = "//(include|includeAttribute)";
+ // if (String.IsNullOrEmpty(path)) WriteMessage(MessageLevel.Error, "Each resolve element must contain a path attribute specifying an XPath expression for shared content elements.");
+ try {
+ XPathExpression path_expresion = XPathExpression.Compile(path, context);
+ } catch (XPathException) {
+ WriteMessage(MessageLevel.Error, String.Format("The elements expression '{0}' is not a valid XPath.", path));
+ }
+
+ string item = resolve_node.GetAttribute("item", String.Empty);
+ if (String.IsNullOrEmpty(item)) item = "string(@item)";
+ try {
+ XPathExpression item_expression = XPathExpression.Compile(item, context);
+ } catch (XPathException) {
+ WriteMessage(MessageLevel.Error, String.Format("The item expression '{0}' is not a valid XPath.", item));
+ }
+
+ string parameters = resolve_node.GetAttribute("parameters", String.Empty);
+ if (String.IsNullOrEmpty(parameters)) parameters = "parameter";
+
+ string attribute = resolve_node.GetAttribute("attribute", String.Empty);
+ if (String.IsNullOrEmpty(attribute)) attribute = "string(@name)";
+
+ elements.Add( new SharedContentElement(path, item, parameters, attribute, context) );
+ }
+
+ // Console.WriteLine("{0} elements explicitly defined", elements.Count);
+
+ if (elements.Count == 0) elements.Add( new SharedContentElement(@"//include | //includeAttribute", "string(@item)", "parameter", "string(@name)", context) );
+
+ // get the source and target formats
+ XPathNodeIterator content_nodes = configuration.Select("content");
+ foreach (XPathNavigator content_node in content_nodes)
+ {
+ // get the files
+ string sharedContentFiles = content_node.GetAttribute("file", String.Empty);
+ if (String.IsNullOrEmpty(sharedContentFiles))
+ WriteMessage(MessageLevel.Error, "The content/@file attribute must specify a path.");
+ ParseDocuments(sharedContentFiles);
+ }
+ WriteMessage(MessageLevel.Info, String.Format("Loaded {0} shared content items.", content.Count));
+ }
+
+ public void ParseDocuments(string wildcardPath)
+ {
+ string sharedContentFiles = Environment.ExpandEnvironmentVariables(wildcardPath);
+ if (String.IsNullOrEmpty(sharedContentFiles))
+ WriteMessage(MessageLevel.Error, "The content/@file attribute specifies an empty string.");
+
+ WriteMessage(MessageLevel.Info, String.Format("Searching for files that match '{0}'.", sharedContentFiles));
+ string directoryPart = Path.GetDirectoryName(sharedContentFiles);
+ if (String.IsNullOrEmpty(directoryPart))
+ directoryPart = Environment.CurrentDirectory;
+ directoryPart = Path.GetFullPath(directoryPart);
+ string filePart = Path.GetFileName(sharedContentFiles);
+ string[] files = Directory.GetFiles(directoryPart, filePart);
+ foreach (string file in files)
+ LoadContent(file);
+ WriteMessage(MessageLevel.Info, String.Format("Found {0} files in {1}.", files.Length, sharedContentFiles));
+ }
+
+ private void LoadContent(string file)
+ {
+
+ WriteMessage(MessageLevel.Info, String.Format("Loading shared content file '{0}'.", file) );
+
+ try {
+ XmlReader reader = XmlReader.Create(file);
+
+ try {
+ reader.MoveToContent();
+ while (!reader.EOF) {
+
+ if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "item")) {
+
+ string key = reader.GetAttribute("id").ToLower();
+ string value = reader.ReadInnerXml();
+
+ if (content.ContainsKey(key)) WriteMessage(MessageLevel.Info, String.Format("Overriding shared content item '{0}' with value in file '{1}'.", key, file));
+ content[key] = value;
+ // content.Add(key, value);
+ } else {
+ reader.Read();
+ }
+
+ }
+ } finally {
+ reader.Close();
+ }
+
+ } catch (IOException e) {
+ WriteMessage(MessageLevel.Error, String.Format("The shared content file '{0}' could not be opened. The error message is: {1}", file, BuildComponentUtilities.GetExceptionMessage(e)));
+ } catch (XmlException e) {
+ WriteMessage(MessageLevel.Error, String.Format("The shared content file '{0}' is not well-formed. The error message is: {1}", file, BuildComponentUtilities.GetExceptionMessage(e)));
+ } catch (XmlSchemaException e) {
+ WriteMessage(MessageLevel.Error, String.Format("The shared content file '{0}' is not valid. The error message is: {1}", file, BuildComponentUtilities.GetExceptionMessage(e)));
+ }
+
+ }
+
+ private void DetectLoops () {
+
+ }
+
+ // Stored data
+
+ // The context
+ private CustomContext context = new CustomContext();
+
+ // The shared content items
+ private Dictionary<string,string> content = new Dictionary<string,string>();
+
+ // THe shared content elements
+ private List<SharedContentElement> elements = new List<SharedContentElement>();
+
+ public override void Apply (XmlDocument document, string key) {
+ ResolveContent(document);
+ }
+
+ // private XPathExpression expression = XPathExpression.Compile("//include | //includeAttribute");
+
+ private void ResolveContent (XmlDocument document) {
+ //Console.WriteLine("doc={0}", document.CreateNavigator().InnerXml);
+ ResolveContent(document, document.CreateNavigator());
+ }
+
+ private void ResolveContent (XmlDocument document, XPathNavigator start) {
+
+ // for each kind of shared content element
+ foreach (SharedContentElement element in elements) {
+
+ // find all such elements
+ XPathNodeIterator nodeIterator = start.Select(element.Path);
+ // Console.WriteLine("Found {0} shared content elements.", nodeIterator.Count);
+
+ // convert to an array so as not to cause an error when manipulating the document
+ XPathNavigator[] nodes = ConvertIteratorToArray(nodeIterator);
+
+ // process each element
+ foreach (XPathNavigator node in nodes) {
+
+ // Console.WriteLine(node.LocalName);
+
+ // get the key
+ string item = node.Evaluate(element.Item).ToString().ToLower();
+
+ // check for missing key
+ if (String.IsNullOrEmpty(item)) {
+ WriteMessage(MessageLevel.Warn, "A shared content element did not specify an item.");
+ } else {
+
+ // Console.WriteLine("node={0}", node.OuterXml);
+
+ // extract parameters
+ List<string> parameters = new List<string>();
+ XPathNodeIterator parameter_nodes = node.Select(element.Parameters);
+ foreach (XPathNavigator parameter_node in parameter_nodes) {
+ string parameter = BuildComponentUtilities.GetInnerXml(parameter_node);
+ // Console.WriteLine("parameter={0}", parameter);
+ parameters.Add(parameter);
+ }
+
+ // get the content
+ string content = GetContent(item, parameters.ToArray());
+
+ // check for missing content
+ if (content == null) {
+ WriteMessage(MessageLevel.Warn, String.Format("Missing shared content item. Tag:'{0}'; Id:'{1}'.", node.LocalName, item));
+ } else {
+
+ // store the content in a document fragment
+ XmlDocumentFragment fragment = document.CreateDocumentFragment();
+ fragment.InnerXml = content;
+
+ // resolve any shared content in the fragment
+ ResolveContent(document, fragment.CreateNavigator());
+ //string resolvedContent = fragment.InnerXml;
+ //Console.WriteLine("value = '{0}'", resolvedContent);
+
+ // look for an attribute name
+ string attribute = node.Evaluate(element.Attribute).ToString();
+
+ // insert the resolved content
+ if (String.IsNullOrEmpty(attribute)) {
+ // as mixed content
+ // node.InsertAfter(resolvedContent);
+ XmlWriter writer = node.InsertAfter();
+ fragment.WriteTo(writer);
+ writer.Close();
+ } else {
+ // as an attribute
+ XPathNavigator parent = node.CreateNavigator();
+ parent.MoveToParent();
+ parent.CreateAttribute(String.Empty, attribute, String.Empty, fragment.InnerText);
+ }
+
+ }
+
+
+ }
+
+ // keep a reference to the parent element
+ XPathNavigator parentElement = node.CreateNavigator();
+ parentElement.MoveToParent();
+
+ // remove the node
+ node.DeleteSelf();
+
+ // if there is no content left in the parent element, make sure it is self-closing
+ if (!parentElement.HasChildren && !parentElement.IsEmptyElement) {
+
+ //If 'node' was already the root then we will have a blank node now and
+ //doing an InsertAfter() will throw an exception.
+ if (parentElement.Name.Length > 0)
+ {
+ // create a new element
+ XmlWriter attributeWriter = parentElement.InsertAfter();
+ attributeWriter.WriteStartElement(parentElement.Prefix, parentElement.LocalName, parentElement.NamespaceURI);
+
+ // copy attributes to it
+ XmlReader attributeReader = parentElement.ReadSubtree();
+ attributeReader.Read();
+ attributeWriter.WriteAttributes(attributeReader, false);
+ attributeReader.Close();
+
+ // close it
+ attributeWriter.WriteEndElement();
+ attributeWriter.Close();
+
+ // delete the old element
+ parentElement.DeleteSelf();
+ }
+ else
+ {
+ //if we are inside a tag such as title, removing the content will make it in the
+ //form of <title /> which is not allowed in html.
+ //Since this usually means there is a problem with the shared content or the transforms
+ //leading up to this we will just report the error here.
+ WriteMessage(MessageLevel.Error, "Error replacing item.");
+ }
+ }
+
+ }
+
+ }
+
+ }
+
+ // look up shared content
+ private string GetContent (string key, string[] parameters) {
+
+ string value;
+ if (content.TryGetValue(key, out value)) {
+ try {
+ value = String.Format(value, parameters);
+ } catch (FormatException) {
+ WriteMessage(MessageLevel.Error, String.Format("The shared content item '{0}' could not be formatted with {1} parameters.", key, parameters.Length));
+ }
+
+ return(value);
+ } else {
+ return(null);
+ }
+
+ }
+
+ private static XPathNavigator[] ConvertIteratorToArray (XPathNodeIterator iterator) {
+ XPathNavigator[] result = new XPathNavigator[iterator.Count];
+ for (int i=0; i<result.Length; i++) {
+ iterator.MoveNext();
+ result[i] = iterator.Current.Clone();
+ }
+ return(result);
+ }
+
+ private static CustomContext GetContext (XPathNavigator configuration) {
+
+ CustomContext context = new CustomContext();
+
+ XPathNodeIterator context_nodes = configuration.Select("context");
+ foreach (XPathNavigator context_node in context_nodes) {
+ string prefix = context_node.GetAttribute("prefix", String.Empty);
+ string name = context_node.GetAttribute("name", String.Empty);
+ context.AddNamespace(prefix, name);
+ }
+
+ return(context);
+
+ }
+
+ }
+
+ internal class SharedContentElement {
+
+ public SharedContentElement (string path, string item, string parameters, string attribute, IXmlNamespaceResolver context) {
+ this.path = XPathExpression.Compile(path, context);
+ this.item = XPathExpression.Compile(item, context);
+ this.parameters = XPathExpression.Compile(parameters, context);
+ this.attribute = XPathExpression.Compile(attribute, context);
+ }
+
+
+
+ public SharedContentElement (string path, string item, string parameters, string attribute) {
+ this.path = XPathExpression.Compile(path);
+ this.item = XPathExpression.Compile(item);
+ this.parameters = XPathExpression.Compile(parameters);
+ if (attribute != null) {
+ this.attribute = XPathExpression.Compile(attribute);
+ }
+ }
+
+ private XPathExpression path;
+
+ private XPathExpression item;
+
+ private XPathExpression parameters;
+
+ private XPathExpression attribute;
+
+ public XPathExpression Path {
+ get {
+ return(path);
+ }
+ }
+
+ public XPathExpression Item {
+ get {
+ return(item);
+ }
+ }
+
+ public XPathExpression Parameters {
+ get {
+ return(parameters);
+ }
+ }
+
+ public XPathExpression Attribute {
+ get {
+ return(attribute);
+ }
+ }
+
+ public bool IsAttribute {
+ get {
+ return(attribute != null);
+ }
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SnippetComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SnippetComponent.cs
new file mode 100644
index 0000000..d4a3d68
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SnippetComponent.cs
@@ -0,0 +1,1223 @@
+// 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.
+
+// <summary>Contains code to insert snippets directly from the source files without using any
+// intermediate XML files.
+// </summary>
+namespace Microsoft.Ddue.Tools
+{
+ using System;
+ using System.Configuration;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Text;
+ using System.Text.RegularExpressions;
+ using System.Xml;
+ using System.Xml.XPath;
+ using System.Globalization;
+ using System.Diagnostics;
+
+ /// <summary>
+ /// SnippetComponent class to replace the snippet code references.
+ /// </summary>
+ public class SnippetComponent : BuildComponent
+ {
+ #region Private members
+ /// <summary>
+ /// Regex to validate the snippet references.
+ /// </summary>
+ private static Regex validSnippetReference = new Regex(
+ @"^[^#\a\b\f\n\r\t\v]+#(\w+,)*\w+$",
+ RegexOptions.Compiled);
+
+ /// <summary>
+ /// Dictionary to map language folder names to language id.
+ /// </summary>
+ private static Dictionary<string, string> languageMap = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
+
+ /// <summary>
+ /// List that controls the order in which languages snippets are displayed.
+ /// </summary>
+ private static List<string> languageList = new List<string>();
+
+ /// <summary>
+ /// Dictionary consisting of example name as key and example path as value.
+ /// </summary>
+ private Dictionary<string, string> exampleIndex = new Dictionary<string, string>();
+
+ /// <summary>
+ /// Dictionary consisting of exampleName\unitName as key with a null value.
+ /// </summary>
+ private Dictionary<string, string> approvedSnippetIndex = new Dictionary<string,string>();
+
+ /// <summary>
+ /// Dictionary containing the example name as key and list of rejected language snippets as values.
+ /// </summary>
+ private Dictionary<string, List<string>> rejectedSnippetIndex = new Dictionary<string, List<string>>();
+
+ /// <summary>
+ /// List of unit folder names to exclude from sample parsing.
+ /// </summary>
+ private Dictionary<string, Object> excludedUnits = new Dictionary<string, Object>();
+
+ /// <summary>
+ /// Dictionary consisting of exampleName\unitName as key with a null value.
+ /// </summary>
+ private SnippetCache snippetCache = null;
+
+ /// <summary>
+ /// XPathExpression to look for snippet references in the topics.
+ /// </summary>
+ private XPathExpression selector;
+
+ /// <summary>
+ /// XmlNamespaceManager to set the context.
+ /// </summary>
+ private XmlNamespaceManager context = new CustomContext();
+
+ /// <summary>
+ /// List of languages.
+ /// </summary>
+ private List<Language> languages = new List<Language>();
+
+ /// <summary>
+ /// snippet store.
+ /// </summary>
+ private Dictionary<SnippetIdentifier, List<Snippet>> snippets = new Dictionary<SnippetIdentifier, List<Snippet>>();
+ #endregion
+
+ #region Constructor
+
+ /// <summary>
+ /// Constructor for SnippetComponent class.
+ /// </summary>
+ /// <param name="assembler">An instance of Build Assembler</param>
+ /// <param name="configuration">configuration to be parsed for information related to snippets</param>
+ public SnippetComponent(BuildAssembler assembler, XPathNavigator configuration)
+ : base(assembler, configuration)
+ {
+ Debug.Assert(assembler != null);
+ Debug.Assert(configuration != null);
+
+ // Get the parsnip examples location.
+ XPathNodeIterator examplesNode = configuration.Select("examples/example");
+
+ if (examplesNode.Count == 0)
+ WriteMessage(MessageLevel.Error, "Each snippet component element must have a child element named 'examples' containing an element named 'example' with an attribute named 'directory', whose value is a path to the directory containing examples.");
+
+ foreach (XPathNavigator exampleNode in examplesNode)
+ {
+ string rootDirectory = exampleNode.GetAttribute("directory", string.Empty);
+
+ if (string.IsNullOrEmpty(rootDirectory))
+ WriteMessage(MessageLevel.Error, "Each examples element must have a directory attribute specifying a directory containing parsnip samples.");
+
+ rootDirectory = Environment.ExpandEnvironmentVariables(rootDirectory);
+ if (!Directory.Exists(rootDirectory))
+ WriteMessage(MessageLevel.Error, String.Format("The examples/@directory attribute specified a directory that doesn't exist: '{0}'", rootDirectory));
+
+ // create a dictionary that maps the example names to the example path under the root directory
+ this.loadExamples(rootDirectory);
+ }
+
+ // Get the approved log files location.
+ XPathNodeIterator approvedSnippetsNode = configuration.Select("approvalLogs/approvalLog");
+
+ if (approvedSnippetsNode.Count == 0)
+ WriteMessage(MessageLevel.Warn, "The config did not have an 'approvalLogs' node to specify a snippet approval logs.");
+
+ foreach (XPathNavigator node in approvedSnippetsNode)
+ {
+ string approvalLogFile = node.GetAttribute("file", string.Empty);
+
+ if (string.IsNullOrEmpty(approvalLogFile))
+ WriteMessage(MessageLevel.Error, "The approvalLog node must have a 'file' attribute specifying the path to a snippet approval log.");
+
+ approvalLogFile = Environment.ExpandEnvironmentVariables(approvalLogFile);
+ if (!File.Exists(approvalLogFile))
+ WriteMessage(MessageLevel.Error, String.Format("The approvalLog/@file attribute specified a file that doesn't exist: '{0}'", approvalLogFile));
+
+ // load the approval log into the approvedSnippetIndex dictionary
+ this.parseApprovalLogFiles(approvalLogFile);
+ }
+
+ // Get the names of the unit directories in the sample tree to exclude from parsing
+ // <excludedUnits><unitFolder name="CPP_OLD" /></excludedUnits>
+ XPathNodeIterator excludedUnitNodes = configuration.Select("excludedUnits/unitFolder");
+ foreach (XPathNavigator unitFolder in excludedUnitNodes)
+ {
+ string folderName = unitFolder.GetAttribute("name", string.Empty);
+
+ if (string.IsNullOrEmpty(folderName))
+ WriteMessage(MessageLevel.Error, "Each excludedUnits/unitFolder node must have a 'name' attribute specifying the name of a folder name to exclude.");
+
+ folderName = Environment.ExpandEnvironmentVariables(folderName);
+
+ // add the folderName to the list of names to be excluded
+ this.excludedUnits.Add(folderName.ToLower(),null);
+ }
+
+ // Get the languages defined.
+ XPathNodeIterator languageNodes = configuration.Select("languages/language");
+ foreach (XPathNavigator languageNode in languageNodes)
+ {
+ // read the @languageId, @unit, and @extension attributes
+ string languageId = languageNode.GetAttribute("languageId", string.Empty);
+ if (string.IsNullOrEmpty(languageId))
+ WriteMessage(MessageLevel.Error, "Each language node must specify an @languageId attribute.");
+
+ string unit = languageNode.GetAttribute("unit", string.Empty);
+
+ // if both @languageId and @unit are specified, add this language to the language map
+ if (!string.IsNullOrEmpty(unit))
+ languageMap.Add(unit.ToLower(), languageId);
+
+ // add languageId to the languageList for purpose of ordering snippets in the output
+ if (!languageList.Contains(languageId))
+ languageList.Add(languageId.ToLower());
+
+ string extension = languageNode.GetAttribute("extension", string.Empty);
+ if (!string.IsNullOrEmpty(extension))
+ {
+ if (!extension.Contains("."))
+ {
+ extension = "." + extension;
+ WriteMessage(MessageLevel.Warn, String.Format("The @extension value must begin with a period. Adding a period to the extension value '{0}' of the {1} language.", extension, languageId));
+ }
+ else
+ {
+ int indexOfPeriod = extension.IndexOf('.');
+ if (indexOfPeriod != 0)
+ {
+ extension = extension.Substring(indexOfPeriod);
+ WriteMessage(MessageLevel.Warn, String.Format("The @extension value must begin with a period. Using the substring beginning with the first period of the specified extension value '{0}' of the {1} language.", extension, languageId));
+ }
+ }
+ }
+
+ // read the color nodes, if any, and add them to the list of colorization rules
+ List<ColorizationRule> rules = new List<ColorizationRule>();
+
+ XPathNodeIterator colorNodes = languageNode.Select("color");
+ foreach (XPathNavigator colorNode in colorNodes)
+ {
+ string pattern = colorNode.GetAttribute("pattern", String.Empty);
+ string region = colorNode.GetAttribute("region", String.Empty);
+ string name = colorNode.GetAttribute("class", String.Empty);
+ if (String.IsNullOrEmpty(region))
+ {
+ rules.Add(new ColorizationRule(pattern, name));
+ }
+ else
+ {
+ rules.Add(new ColorizationRule(pattern, region, name));
+ }
+ }
+
+ this.languages.Add(new Language(languageId, extension, rules));
+ WriteMessage(MessageLevel.Info, String.Format("Loaded {0} colorization rules for the language '{1}', extension '{2}.", rules.Count, languageId, extension));
+ }
+
+ this.context.AddNamespace("ddue", "http://ddue.schemas.microsoft.com/authoring/2003/5");
+ this.selector = XPathExpression.Compile("//ddue:codeReference");
+ this.selector.SetContext(this.context);
+
+ // create the snippet cache
+ snippetCache = new SnippetCache(100, approvedSnippetIndex, languageMap, languages, excludedUnits);
+ }
+ #endregion
+
+ #region Public methods
+ /// <summary>
+ /// Apply method to perform the actual work of the component.
+ /// </summary>
+ /// <param name="document">document to be parsed for snippet references</param>
+ /// <param name="key">Id of a topic</param>
+ public override void Apply(XmlDocument document, string key)
+ {
+ // clear out the snippets dictionary of any snippets from the previous document
+ snippets.Clear();
+
+ XPathNodeIterator nodesIterator = document.CreateNavigator().Select(this.selector);
+ XPathNavigator[] nodes = BuildComponentUtilities.ConvertNodeIteratorToArray(nodesIterator);
+ foreach (XPathNavigator node in nodes)
+ {
+ // get the snippet reference, which can contain one or more snippet ids
+ string reference = node.Value;
+
+ // check for validity of reference
+ if (!validSnippetReference.IsMatch(reference))
+ {
+ WriteMessage(MessageLevel.Warn, "Skipping invalid snippet reference: " + reference);
+ continue;
+ }
+
+ // get the identifiers from the codeReference
+ SnippetIdentifier[] identifiers = SnippetIdentifier.ParseReference(reference);
+
+ // load the language-specific snippets for each of the specified identifiers
+ foreach (SnippetIdentifier identifier in identifiers)
+ {
+ if (snippets.ContainsKey(identifier))
+ continue;
+
+ // look up the snippets example path
+ string examplePath = string.Empty;
+ if (!this.exampleIndex.TryGetValue(identifier.Example, out examplePath))
+ {
+ WriteMessage(MessageLevel.Warn, String.Format("Snippet with identifier '{0}' was not found. The '{1}' example was not found in the examples directory.", identifier.ToString(), identifier.Example));
+ continue;
+ }
+
+ // get the snippet from the snippet cache
+ List<Snippet> snippetList = snippetCache.GetContent(examplePath, identifier);
+ if (snippetList != null)
+ {
+ snippets.Add(identifier, snippetList);
+ }
+ else
+ {
+ // if no approval log was specified in the config, all snippets are treated as approved by default
+ // so show an warning message that the snippet was not found
+ if (approvedSnippetIndex.Count == 0)
+ WriteMessage(MessageLevel.Warn, string.Format("No Snippet with identifier '{0}' was found.", identifier.ToString()));
+ else
+ {
+ // show a warning message: either snippet not found, or snippet not approved.
+ bool isApproved = false;
+
+ foreach (string snippetIndex in this.approvedSnippetIndex.Keys)
+ {
+ string[] splitSnippet = snippetIndex.Split('\\');
+ if (splitSnippet[0] == identifier.Example)
+ {
+ isApproved = true;
+ break;
+ }
+ }
+
+ // check whether snippets are present in parsnip approval logs and throw warnings accordingly.
+ if (!isApproved || !rejectedSnippetIndex.ContainsKey(identifier.Example))
+ WriteMessage(MessageLevel.Warn, string.Format("The snippet with identifier '{0}' was omitted because it is not present in parsnip approval logs.", identifier.ToString()));
+ else
+ WriteMessage(MessageLevel.Warn, string.Format("No Snippet with identifier '{0}' was found.", identifier.ToString()));
+ }
+
+ continue;
+ }
+
+ // write warning messages for any rejected units for this example
+ List<string> rejectedUnits;
+ if (rejectedSnippetIndex.TryGetValue(identifier.Example, out rejectedUnits))
+ {
+ foreach (string rejectedUnit in rejectedUnits)
+ WriteMessage(MessageLevel.Warn, string.Format("The '{0}' snippet with identifier '{1}' was omitted because the {2}\\{0} unit did not pass Parsnip testing.", rejectedUnit, identifier.ToString(), identifier.Example));
+ }
+ }
+
+ if (identifiers.Length == 1)
+ {
+ // one snippet referenced
+ SnippetIdentifier identifier = identifiers[0];
+
+ if (snippets.ContainsKey(identifier))
+ {
+ writeSnippetContent(node, identifier, snippets[identifier]);
+ }
+ }
+ else
+ {
+ // handle case where codeReference contains multiple identifiers
+ // Each language's set of snippets from multiple identifiers are displayed in a single block;
+
+ // create dictionary that maps each language to its set of snippets
+ Dictionary<string, List<Snippet>> map = new Dictionary<string, List<Snippet>>();
+ foreach (SnippetIdentifier identifier in identifiers)
+ {
+ List<Snippet> values;
+ if (snippets.TryGetValue(identifier, out values))
+ {
+ foreach (Snippet value in values)
+ {
+ List<Snippet> pieces;
+ if (!map.TryGetValue(value.Language.LanguageId, out pieces))
+ {
+ pieces = new List<Snippet>();
+ map.Add(value.Language.LanguageId, pieces);
+ }
+ pieces.Add(value);
+ }
+ }
+ }
+
+ // now write the collection of snippet pieces to the document
+ XmlWriter writer = node.InsertAfter();
+ writer.WriteStartElement("snippets");
+ writer.WriteAttributeString("reference", reference);
+
+ // first write the snippets in the order their language shows up in the language map (if any)
+ foreach (string devlang in languageList)
+ {
+ foreach (KeyValuePair<string, List<Snippet>> entry in map)
+ {
+ if (!(devlang == entry.Key.ToLower()))
+ continue;
+ writer.WriteStartElement("snippet");
+ writer.WriteAttributeString("language", entry.Key);
+ writer.WriteString("\n");
+
+ // write the set of snippets for this language
+ List<Snippet> values = entry.Value;
+ for (int i = 0; i < values.Count; i++)
+ {
+ if (i > 0)
+ writer.WriteString("\n...\n\n\n");
+ // write the colorized or plaintext snippet text
+ WriteSnippetText(values[i], writer);
+ }
+
+ writer.WriteEndElement();
+ }
+ }
+
+ // now write any snippets whose language isn't in the language map
+ foreach (KeyValuePair<string, List<Snippet>> entry in map)
+ {
+ if (languageList.Contains(entry.Key.ToLower()))
+ continue;
+ writer.WriteStartElement("snippet");
+ writer.WriteAttributeString("language", entry.Key);
+ writer.WriteString("\n");
+
+ // write the set of snippets for this language
+ List<Snippet> values = entry.Value;
+ for (int i = 0; i < values.Count; i++)
+ {
+ if (i > 0)
+ writer.WriteString("\n...\n\n\n");
+ // write the colorized or plaintext snippet text
+ WriteSnippetText(values[i], writer);
+ }
+
+ writer.WriteEndElement();
+ }
+
+ writer.WriteEndElement();
+ writer.Close();
+ }
+ node.DeleteSelf();
+ }
+ }
+ #endregion
+
+ #region Private methods
+ /// <summary>
+ /// Index the example names to paths.
+ /// </summary>
+ /// <param name="rootDirectory">root directory location of parsnip samples</param>
+ private void loadExamples(string rootDirectory)
+ {
+ try
+ {
+ DirectoryInfo root = new DirectoryInfo(rootDirectory);
+ DirectoryInfo[] areaDirectories = root.GetDirectories();
+
+ foreach (DirectoryInfo area in areaDirectories)
+ {
+ DirectoryInfo[] exampleDirectories = area.GetDirectories();
+
+ foreach (DirectoryInfo example in exampleDirectories)
+ {
+ string path;
+ if (this.exampleIndex.TryGetValue(example.Name.ToLower(CultureInfo.InvariantCulture), out path))
+ WriteMessage(MessageLevel.Warn, string.Format("The example '{0}' under folder '{1}' already exists under '{2}'", example.Name, example.FullName, path));
+
+ this.exampleIndex[example.Name.ToLower(CultureInfo.InvariantCulture)] = example.FullName;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ WriteMessage(MessageLevel.Error, string.Format(System.Threading.Thread.CurrentThread.CurrentCulture, "The loading of examples failed:{0}", e.Message));
+ throw;
+ }
+ }
+
+ /// <summary>
+ /// Index the approved snippets.
+ /// </summary>
+ /// <param name="file">approved snippets log file</param>
+ private void parseApprovalLogFiles(string file)
+ {
+ string sampleName = string.Empty;
+ string unitName = string.Empty;
+ List<string> rejectedUnits = null;
+
+ XmlReader reader = XmlReader.Create(file);
+ try
+ {
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ if (reader.Name == "Sample")
+ {
+ sampleName = reader.GetAttribute("name").ToLower(CultureInfo.InvariantCulture);
+ //create a new rejectedUnits list for this sample
+ rejectedUnits = null;
+ }
+
+ if (reader.Name == "Unit")
+ {
+ unitName = reader.GetAttribute("name").ToLower(CultureInfo.InvariantCulture);
+
+ bool include = Convert.ToBoolean(reader.GetAttribute("include"));
+
+ if (include)
+ {
+ if (this.approvedSnippetIndex.ContainsKey(Path.Combine(sampleName, unitName)))
+ WriteMessage(MessageLevel.Warn, string.Format("Sample '{0}' already exists in the approval log files.", sampleName));
+ this.approvedSnippetIndex[Path.Combine(sampleName, unitName)] = null;
+ }
+ else
+ {
+ if (rejectedUnits == null)
+ {
+ rejectedUnits = new List<string>();
+ rejectedSnippetIndex[sampleName] = rejectedUnits;
+ }
+ rejectedUnits.Add(unitName);
+ }
+ }
+ }
+ }
+ }
+ catch (XmlException e)
+ {
+ WriteMessage(MessageLevel.Error, String.Format("The specified approval log file is not well-formed. The error message is: {0}", e.Message));
+ }
+ finally
+ {
+ reader.Close();
+ }
+ }
+
+ /// <summary>
+ /// Write the snippet content to output files.
+ /// </summary>
+ /// <param name="node">code reference node</param>
+ /// <param name="identifier">List of snippets</param>
+ private void writeSnippetContent(XPathNavigator node, SnippetIdentifier identifier, List<Snippet> snippetList)
+ {
+ if (snippetList == null || snippetList.Count == 0)
+ {
+ WriteMessage(MessageLevel.Warn, "Empty snippet list past for node " + node.Name);
+ return;
+ }
+
+ XmlWriter writer = node.InsertAfter();
+ writer.WriteStartElement("snippets");
+ writer.WriteAttributeString("reference", node.Value);
+
+ // first write the snippets in the order their language shows up in the language map (if any)
+ foreach (string devlang in languageList)
+ {
+ foreach (Snippet snippet in snippetList)
+ {
+ if (!(devlang == snippet.Language.LanguageId.ToLower()))
+ continue;
+ writer.WriteStartElement("snippet");
+ writer.WriteAttributeString("language", snippet.Language.LanguageId);
+ writer.WriteString("\n");
+ // write the colorized or plaintext snippet text
+ WriteSnippetText(snippet, writer);
+ writer.WriteEndElement();
+ }
+ }
+
+ // now write any snippets whose language isn't in the language map
+ foreach (Snippet snippet in snippetList)
+ {
+ if (languageList.Contains(snippet.Language.LanguageId.ToLower()))
+ continue;
+ writer.WriteStartElement("snippet");
+ writer.WriteAttributeString("language", snippet.Language.LanguageId);
+ writer.WriteString("\n");
+ // write the colorized or plaintext snippet text
+ WriteSnippetText(snippet, writer);
+ writer.WriteEndElement();
+ }
+
+ writer.WriteEndElement();
+ writer.Close();
+ }
+
+ private void WriteSnippetText(Snippet snippet, XmlWriter writer)
+ {
+ // if colorization rules are defined, then colorize the snippet.
+ if (snippet.Language.ColorizationRules != null)
+ {
+ writeColorizedSnippet(colorizeSnippet(snippet.Content, snippet.Language.ColorizationRules), writer);
+ }
+ else
+ {
+ writer.WriteString(snippet.Content);
+ }
+ }
+
+ private static ICollection<Region> colorizeSnippet(string text, List<ColorizationRule> rules)
+ {
+ // Console.WriteLine("colorizing: '{0}'", text);
+ // create a linked list consiting entirely of one uncolored region
+ LinkedList<Region> regions = new LinkedList<Region>();
+ regions.AddFirst(new Region(text));
+
+ // loop over colorization rules
+ foreach (ColorizationRule rule in rules)
+ {
+ // loop over regions
+ LinkedListNode<Region> node = regions.First;
+ while (node != null)
+ {
+ // only try to colorize uncolored regions
+ if (node.Value.ClassName != null)
+ {
+ node = node.Next;
+ continue;
+ }
+
+ // find matches in the region
+ string regionText = node.Value.Text;
+ Capture[] matches = rule.Apply(regionText);
+
+ // if no matches were found, continue to the next region
+ if (matches.Length == 0)
+ {
+ node = node.Next;
+ continue;
+ }
+
+ // we found matches; break the region into colored and uncolered subregions
+ // index is where we are looking from; index-1 is the end of the last match
+ int index = 0;
+
+ LinkedListNode<Region> referenceNode = node;
+
+ foreach (Capture match in matches)
+ {
+ // create a leading uncolored region
+ if (match.Index > index)
+ {
+ //Console.WriteLine("uncolored: {0} '{1}' -> {2} '{3}'", index, regionText[index], match.Index - 1, regionText[match.Index - 1]);
+ Region uncoloredRegion = new Region(regionText.Substring(index, match.Index - index));
+ referenceNode = regions.AddAfter(referenceNode, uncoloredRegion);
+ }
+
+ // create a colored region
+ // Console.WriteLine("name = {0}", rule.ClassName);
+ //Console.WriteLine("colored: {0} '{1}' -> {2} '{3}'", match.Index, regionText[match.Index], match.Index + match.Length - 1, regionText[match.Index + match.Length - 1]);
+ Region coloredRegion = new Region(rule.ClassName, regionText.Substring(match.Index, match.Length));
+ referenceNode = regions.AddAfter(referenceNode, coloredRegion);
+
+ index = match.Index + match.Length;
+ }
+
+ // create a trailing uncolored region
+ if (index < regionText.Length)
+ {
+ Region uncoloredRegion = new Region(regionText.Substring(index));
+ referenceNode = regions.AddAfter(referenceNode, uncoloredRegion);
+ }
+
+ // remove the original node
+ regions.Remove(node);
+ node = referenceNode.Next;
+ }
+ }
+ return (regions);
+ }
+
+ private static void writeColorizedSnippet(ICollection<Region> regions, XmlWriter writer)
+ {
+ foreach (Region region in regions)
+ {
+ // Console.WriteLine("writing {0}", region.ClassName);
+ if (region.ClassName == null)
+ {
+ writer.WriteString(region.Text);
+ }
+ else
+ {
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", region.ClassName);
+ writer.WriteString(region.Text);
+ writer.WriteEndElement();
+ }
+ }
+ }
+ #endregion
+ }
+
+ /// <summary>
+ /// Language class.
+ /// </summary>
+ internal class Language
+ {
+ #region Private members
+ /// <summary>
+ /// The id of the programming language.
+ /// </summary>
+ private string languageId;
+
+ /// <summary>
+ /// Language file extension.
+ /// </summary>
+ private string extension;
+
+ /// <summary>
+ /// List of colorization rules.
+ /// </summary>
+ private List<ColorizationRule> colorizationRules;
+ #endregion
+
+ #region Constructor
+ /// <summary>
+ /// Language Constructor
+ /// </summary>
+ /// <param name="languageId">language id</param>
+ /// <param name="extension">language file extension</param>
+ /// <param name="rules">colorization rules</param>
+ public Language(string languageId, string extension, List<ColorizationRule> rules)
+ {
+ this.languageId = languageId;
+ this.extension = extension;
+ this.colorizationRules = rules;
+ }
+ #endregion
+
+ #region Public properties
+ /// <summary>
+ /// Gets the languageId.
+ /// </summary>
+ public string LanguageId
+ {
+ get
+ {
+ return this.languageId;
+ }
+ }
+
+ /// <summary>
+ /// Gets the file extension
+ /// </summary>
+ public string Extension
+ {
+ get
+ {
+ return this.extension;
+ }
+ }
+
+ /// <summary>
+ /// Gets the colorization rules
+ /// </summary>
+ public List<ColorizationRule> ColorizationRules
+ {
+ get
+ {
+ return this.colorizationRules;
+ }
+ }
+ #endregion
+
+ #region Public methods
+ /// <summary>
+ /// Check if the language is defined.
+ /// </summary>
+ /// <param name="languageId">language id</param>
+ /// <param name="extension">file extension</param>
+ /// <returns>boolean indicating if a language is defined</returns>
+ public bool IsMatch(string languageId, string extension)
+ {
+ if (this.languageId == languageId)
+ {
+ if (this.extension == extension)
+ {
+ return true;
+ }
+ else if (this.extension == "*")
+ {
+ return true;
+ }
+ }
+ else if (this.languageId == "*")
+ {
+ if (this.extension == extension)
+ {
+ return true;
+ }
+
+ if (this.extension == "*")
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ #endregion
+ }
+
+ /// <summary>
+ /// Snippet class.
+ /// </summary>
+ internal class Snippet
+ {
+ #region Private Members
+ /// <summary>
+ /// snippet content.
+ /// </summary>
+ private string content;
+
+ /// <summary>
+ /// snippet language
+ /// </summary>
+ private Language language;
+ #endregion
+
+ #region Constructor
+ /// <summary>
+ /// Constructor for Snippet class.
+ /// </summary>
+ /// <param name="content">snippet content</param>
+ /// <param name="language">snippet language</param>
+ public Snippet(string content, Language language)
+ {
+ this.content = content;
+ this.language = language;
+ }
+ #endregion
+
+ #region Public properties
+ /// <summary>
+ /// Gets the snippet content.
+ /// </summary>
+ public string Content
+ {
+ get
+ {
+ return this.content;
+ }
+ }
+
+ /// <summary>
+ /// Gets the snippet language.
+ /// </summary>
+ public Language Language
+ {
+ get
+ {
+ return this.language;
+ }
+ }
+ #endregion
+ }
+
+ internal class SnippetCache
+ {
+ private int _cacheSize = 100;
+
+ private LinkedList<String> lruLinkedList;
+
+ private Dictionary<string, IndexedExample> cache;
+
+ private Dictionary<string, string> _approvalIndex;
+ private Dictionary<string, string> _languageMap;
+ private List<Language> _languages;
+ private Dictionary<string, Object> _excludedUnits;
+
+ public SnippetCache(int cacheSize, Dictionary<string, string> approvalIndex, Dictionary<string, string> languageMap, List<Language> languages, Dictionary<string, Object> excludedUnits)
+ {
+ _cacheSize = cacheSize;
+ _approvalIndex = approvalIndex;
+ _languageMap = languageMap;
+ _languages = languages;
+ _excludedUnits = excludedUnits;
+
+ cache = new Dictionary<string, IndexedExample>(_cacheSize);
+
+ lruLinkedList = new LinkedList<string>();
+ }
+
+ public List<Snippet> GetContent(string examplePath, SnippetIdentifier snippetId)
+ {
+
+ // get the example containing the identifier
+ IndexedExample exampleIndex = GetCachedExample(examplePath);
+ if (exampleIndex == null)
+ return (null);
+
+ //
+ return exampleIndex.GetContent(snippetId);
+ }
+
+ private IndexedExample GetCachedExample(string examplePath)
+ {
+ IndexedExample exampleIndex;
+ if (cache.TryGetValue(examplePath, out exampleIndex))
+ {
+ // move the file from its current position to the head of the lru linked list
+ lruLinkedList.Remove(exampleIndex.ListNode);
+ lruLinkedList.AddFirst(exampleIndex.ListNode);
+ }
+ else
+ {
+ // not in the cache, so load and index a new example
+ exampleIndex = new IndexedExample(examplePath, _approvalIndex, _languageMap, _languages, _excludedUnits);
+ if (cache.Count >= _cacheSize)
+ {
+ // the cache is full
+ // the last node in the linked list has the path of the next file to remove from the cache
+ if (lruLinkedList.Last != null)
+ {
+ cache.Remove(lruLinkedList.Last.Value);
+ lruLinkedList.RemoveLast();
+ }
+ }
+ // add the new file to the cache and to the head of the lru linked list
+ cache.Add(examplePath, exampleIndex);
+ exampleIndex.ListNode = lruLinkedList.AddFirst(examplePath);
+ }
+ return (exampleIndex);
+ }
+
+
+ }
+
+ internal class IndexedExample
+ {
+ /// <summary>
+ /// snippet store.
+ /// </summary>
+ private Dictionary<SnippetIdentifier, List<Snippet>> exampleSnippets = new Dictionary<SnippetIdentifier, List<Snippet>>();
+ private Dictionary<string, string> _approvalIndex;
+ private Dictionary<string, string> _languageMap;
+ private List<Language> _languages;
+ private Dictionary<string, Object> _excludedUnits;
+
+ public IndexedExample(string examplePath, Dictionary<string, string> approvalIndex, Dictionary<string, string> languageMap, List<Language> languages, Dictionary<string, Object> excludedUnits)
+ {
+ _approvalIndex = approvalIndex;
+ _languageMap = languageMap;
+ _languages = languages;
+ _excludedUnits = excludedUnits;
+
+ // load all the snippets under the specified example path
+ this.ParseExample(new DirectoryInfo(examplePath));
+ }
+
+ public List<Snippet> GetContent(SnippetIdentifier identifier)
+ {
+ if (exampleSnippets.ContainsKey(identifier))
+ return exampleSnippets[identifier];
+ else
+ return null;
+ }
+
+ private LinkedListNode<string> listNode;
+ public LinkedListNode<string> ListNode
+ {
+ get
+ {
+ return (listNode);
+ }
+ set
+ {
+ listNode = value;
+ }
+ }
+
+ /// <summary>
+ /// Check whether the snippet unit is approved
+ /// </summary>
+ /// <param name="unit">unit directory</param>
+ /// <returns>boolean indicating whether the snippet unit is approved</returns>
+ private bool isApprovedUnit(DirectoryInfo unit)
+ {
+ string sampleName = unit.Parent.Name.ToLower(CultureInfo.InvariantCulture);
+ string unitName = unit.Name.ToLower(CultureInfo.InvariantCulture);
+
+ // return false if the unit name is in the list of names to exclude
+ if (_excludedUnits.ContainsKey(unitName))
+ return false;
+
+ // if no approval log is specified, all snippets are approved by default
+ if (_approvalIndex.Count == 0)
+ return true;
+
+ if (_approvalIndex.ContainsKey(Path.Combine(sampleName, unitName)))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Parse the example directory.
+ /// </summary>
+ /// <param name="unit">unit directory</param>
+ private void ParseExample(DirectoryInfo exampleDirectory)
+ {
+ // process the approved language-specific unit directories for this example
+ DirectoryInfo[] unitDirectories = exampleDirectory.GetDirectories();
+
+ foreach (DirectoryInfo unit in unitDirectories)
+ {
+ if (this.isApprovedUnit(unit))
+ this.ParseUnit(unit);
+ }
+ }
+
+ /// <summary>
+ /// Parse the unit directory for language files.
+ /// </summary>
+ /// <param name="unit">unit directory containing a language-specific version of the example</param>
+ private void ParseUnit(DirectoryInfo unit)
+ {
+ // the language is the Unit Directory name, or the language id mapped to that name
+ string language = unit.Name;
+ if (_languageMap.ContainsKey(language.ToLower()))
+ language = _languageMap[language.ToLower()];
+
+ ParseDirectory(unit, language, unit.Parent.Name);
+ }
+
+ /// <summary>
+ /// Parse an example subdir looking for source files containing snipppets.
+ /// </summary>
+ /// <param name="directory">The directory to parse</param>
+ /// <param name="language">the id of a programming language</param>
+ /// <param name="exampleName">the name of the example</param>
+ private void ParseDirectory(DirectoryInfo directory, string language, string exampleName)
+ {
+ // parse the files in this directory
+ FileInfo[] files = directory.GetFiles();
+ foreach (FileInfo file in files)
+ ParseFile(file, language, exampleName);
+
+ // recurse to get files in any subdirectories
+ DirectoryInfo[] subdirectories = directory.GetDirectories();
+ foreach (DirectoryInfo subdirectory in subdirectories)
+ ParseDirectory(subdirectory, language, exampleName);
+ }
+
+ /// <summary>
+ /// Parse the language files to retrieve the snippet content.
+ /// </summary>
+ /// <param name="file">snippet file</param>
+ /// <param name="language">snippet language</param>
+ /// <param name="example">name of the example that contains this file</param>
+ private void ParseFile(FileInfo file, string language, string exampleName)
+ {
+ string snippetLanguage = string.Empty;
+
+ // The snippet language is the name (or id mapping) of the Unit folder
+ // unless the file extension is .xaml
+ // NOTE: this is just preserving the way ExampleBuilder handled it (which we can change when we're confident there are no unwanted side-effects)
+ if (file.Extension.ToLower() == ".xaml")
+ snippetLanguage = "XAML";
+ else
+ snippetLanguage = language;
+
+ // get the text in the file
+ StreamReader reader = file.OpenText();
+ string text = reader.ReadToEnd();
+ reader.Close();
+
+ this.parseSnippetContent(text, snippetLanguage, file.Extension, exampleName);
+ }
+
+ /// <summary>
+ /// Parse the snippet content.
+ /// </summary>
+ /// <param name="text">content to be parsed</param>
+ /// <param name="language">snippet language</param>
+ /// <param name="extension">file extension</param>
+ /// <param name="example">snippet example</param>
+ private void parseSnippetContent(string text, string language, string extension, string example)
+ {
+ // parse the text for snippets
+ for (Match match = find.Match(text); match.Success; match = find.Match(text, match.Index + 10))
+ {
+ string snippetIdentifier = match.Groups["id"].Value;
+ string snippetContent = match.Groups["tx"].Value;
+ snippetContent = clean.Replace(snippetContent, "\n");
+
+ //if necessary, clean one more time to catch snippet comments on consecutive lines
+ if (clean.Match(snippetContent).Success)
+ {
+ snippetContent = clean.Replace(snippetContent, "\n");
+ }
+
+ snippetContent = cleanAtStart.Replace(snippetContent, "");
+ snippetContent = cleanAtEnd.Replace(snippetContent, "");
+
+ // get the language/extension from our languages List, which may contain colorization rules for the language
+ Language snippetLanguage = new Language(language, extension, null);
+ foreach (Language lang in _languages)
+ {
+ if (!lang.IsMatch(language, extension))
+ continue;
+ snippetLanguage = lang;
+ break;
+ }
+
+ SnippetIdentifier identifier = new SnippetIdentifier(example, snippetIdentifier);
+ // BUGBUG: i don't think this ever happens, but if it did we should write an error
+ if (!IsLegalXmlText(snippetContent))
+ {
+ // WriteMessage(MessageLevel.Warn, String.Format("Snippet '{0}' language '{1}' contains illegal characters.", identifier.ToString(), snippetLanguage.LanguageId));
+ continue;
+ }
+
+ snippetContent = StripLeadingSpaces(snippetContent);
+
+ // Add the snippet information to dictionary
+ Snippet snippet = new Snippet(snippetContent, snippetLanguage);
+ List<Snippet> values;
+
+ if (!this.exampleSnippets.TryGetValue(identifier, out values))
+ {
+ values = new List<Snippet>();
+ this.exampleSnippets.Add(identifier, values);
+ }
+ values.Add(snippet);
+ }
+ }
+
+ private bool IsLegalXmlText(string text)
+ {
+ foreach (char c in text)
+ {
+ if (!IsLegalXmlCharacter(c)) return (false);
+ }
+ return (true);
+ }
+
+ private bool IsLegalXmlCharacter(char c)
+ {
+ if (c < 0x20)
+ {
+ return ((c == 0x09) || (c == 0x0A) || (c == 0x0D));
+ }
+ else
+ {
+ if (c < 0xD800)
+ {
+ return (true);
+ }
+ else
+ {
+ return ((c >= 0xE000) && (c <= 0xFFFD));
+ }
+ }
+ }
+
+ private static string StripLeadingSpaces(string text)
+ {
+
+ if (text == null) throw new ArgumentNullException("text");
+
+ // split the text into lines
+ string[] stringSeparators = new string[] { "\r\n" };
+ string[] lines = text.Split(stringSeparators, StringSplitOptions.None);
+
+ // no need to do this if there is only one line
+ if (lines.Length == 1) return (lines[0]);
+
+ // figure out how many leading spaces to delete
+ int spaces = Int32.MaxValue;
+ for (int i = 0; i < lines.Length; i++)
+ {
+
+ string line = lines[i];
+
+ // skip empty lines
+ if (line.Length == 0) continue;
+
+ // determine the number of leading spaces
+ int index = 0;
+ while (index < line.Length)
+ {
+ if (line[index] != ' ') break;
+ index++;
+ }
+
+ if (index == line.Length)
+ {
+ // lines that are all spaces should just be treated as empty
+ lines[i] = String.Empty;
+ }
+ else
+ {
+ // otherwise, keep track of the minimum number of leading spaces
+ if (index < spaces) spaces = index;
+ }
+
+ }
+
+ // re-form the string with leading spaces deleted
+ StringBuilder result = new StringBuilder();
+ foreach (string line in lines)
+ {
+ if (line.Length == 0)
+ {
+ result.AppendLine();
+ }
+ else
+ {
+ result.AppendLine(line.Substring(spaces));
+ }
+ }
+ // Console.WriteLine("AFTER:");
+ // Console.WriteLine(result.ToString());
+ return (result.ToString());
+
+ }
+
+ /// <summary>
+ /// Regex to find the snippet content.
+ /// </summary>
+ private static Regex find = new Regex(
+ @"<snippet(?<id>\w+)>.*\n(?<tx>(.|\n)*?)\n.*</snippet(\k<id>)>",
+ RegexOptions.IgnoreCase | RegexOptions.Compiled);
+
+ /// <summary>
+ /// Regex to clean the snippet content.
+ /// </summary>
+ private static Regex clean = new Regex(
+ @"\n[^\n]*?<(/?)snippet(\w+)>[^\n]*?\n",
+ RegexOptions.IgnoreCase | RegexOptions.Compiled);
+
+ /// <summary>
+ /// Regex to clean the start of the snippet.
+ /// </summary>
+ private static Regex cleanAtStart = new Regex(
+ @"^[^\n]*?<(/?)snippet(\w+)>[^\n]*?\n",
+ RegexOptions.IgnoreCase | RegexOptions.Compiled);
+
+ /// <summary>
+ /// Regex to clean the end of the snippet.
+ /// </summary>
+ private static Regex cleanAtEnd = new Regex(
+ @"\n[^\n]*?<(/?)snippet(\w+)>[^\n]*?$",
+ RegexOptions.IgnoreCase | RegexOptions.Compiled);
+
+ }
+
+
+}
+
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SwitchComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SwitchComponent.cs
new file mode 100644
index 0000000..48f9fbe
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SwitchComponent.cs
@@ -0,0 +1,77 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Diagnostics;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class SwitchComponent : BuildComponent {
+
+ public SwitchComponent(BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ // get the condition
+ XPathNavigator condition_element = configuration.SelectSingleNode("switch");
+ if (condition_element == null) {
+ throw new ConfigurationErrorsException("You must specifiy a condition using the <switch> statement with a 'value' attribute.");
+ }
+ string condition_value = condition_element.GetAttribute("value", String.Empty);
+ if (String.IsNullOrEmpty(condition_value)) {
+ throw new ConfigurationErrorsException("The switch statement must have a 'value' attribute, which is an xpath expression.");
+ }
+ condition = XPathExpression.Compile(condition_value);
+
+ // load the component stacks for each case
+ XPathNodeIterator case_elements = configuration.Select("case");
+ foreach (XPathNavigator case_element in case_elements) {
+ string case_value = case_element.GetAttribute("value", String.Empty);
+ BuildComponent[] components = BuildAssembler.LoadComponents(case_element);
+ cases.Add(case_value, components);
+ }
+ }
+
+ // data held by the component
+
+ private XPathExpression condition;
+
+ private Dictionary<string,IEnumerable<BuildComponent>> cases = new Dictionary<string,IEnumerable<BuildComponent>>();
+
+ // the action of the component
+
+ public override void Apply(XmlDocument document, string key) {
+
+ // evaluate the condition
+ string result = document.CreateNavigator().Evaluate(condition).ToString();
+
+ // get the corresponding component stack
+ IEnumerable<BuildComponent> components;
+ if (cases.TryGetValue(result, out components)) {
+ // apply it
+ foreach (BuildComponent component in components) {
+ component.Apply(document, key);
+ }
+ } else {
+ // no such case exists
+ }
+
+ }
+
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ foreach (IEnumerable<BuildComponent> components in cases.Values) {
+ foreach (BuildComponent component in components) {
+ component.Dispose();
+ }
+ }
+ }
+ base.Dispose(disposing);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SyntaxComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SyntaxComponent.cs
new file mode 100644
index 0000000..3573712
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SyntaxComponent.cs
@@ -0,0 +1,283 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Reflection;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+
+ public class SyntaxComponent : BuildComponent {
+
+ public SyntaxComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ XPathNavigator syntax_node = configuration.SelectSingleNode("syntax");
+ string syntax_input_xpath = syntax_node.GetAttribute("input", String.Empty);
+ if (String.IsNullOrEmpty(syntax_input_xpath)) throw new ConfigurationErrorsException("You must specify an XPath for input in the syntax element.");
+ syntax_input = XPathExpression.Compile(syntax_input_xpath);
+ string syntax_output_xpath = syntax_node.GetAttribute("output", String.Empty);
+ if (String.IsNullOrEmpty(syntax_output_xpath)) throw new ConfigurationErrorsException("You must specify an XPath for output in the syntax element.");
+ syntax_output = XPathExpression.Compile(syntax_output_xpath);
+
+ writerType = typeof(ManagedSyntaxWriter);
+ //if (writerType == null) Console.WriteLine("null writer");
+
+ XPathNodeIterator generator_nodes = configuration.Select("generators/generator");
+ foreach (XPathNavigator generator_node in generator_nodes) {
+
+ // get the data to load the generator
+ string assembly_path = generator_node.GetAttribute("assembly", String.Empty);
+ if (String.IsNullOrEmpty(assembly_path)) WriteMessage(MessageLevel.Error, "Each generator element must have an assembly attribute.");
+ string type_name = generator_node.GetAttribute("type", String.Empty);
+ if (String.IsNullOrEmpty(type_name)) WriteMessage(MessageLevel.Error, "Each generator element must have a type attribute.");
+
+ // expand environment variables in the path
+ assembly_path = Environment.ExpandEnvironmentVariables(assembly_path);
+
+ //Console.WriteLine("loading {0} from {1}", type_name, assembly_path);
+ try {
+ Assembly assembly = Assembly.LoadFrom(assembly_path);
+ SyntaxGenerator generator = (SyntaxGenerator)assembly.CreateInstance(type_name, false, BindingFlags.Public | BindingFlags.Instance, null, new Object[1] { generator_node.Clone() }, null, null);
+
+ if (generator == null) {
+ WriteMessage(MessageLevel.Error, String.Format("The type '{0}' does not exist in the assembly '{1}'.", type_name, assembly_path));
+ } else {
+ generators.Add(generator);
+ }
+
+ } catch (IOException e) {
+ WriteMessage(MessageLevel.Error, String.Format("A file access error occured while attempting to load the build component '{0}'. The error message is: {1}", assembly_path, e.Message));
+ } catch (BadImageFormatException e) {
+ WriteMessage(MessageLevel.Error, String.Format("A syntax generator assembly '{0}' is invalid. The error message is: {1}.", assembly_path, e.Message));
+ } catch (TypeLoadException e) {
+ WriteMessage(MessageLevel.Error, String.Format("The type '{0}' does not exist in the assembly '{1}'. The error message is: {2}", type_name, assembly_path, e.Message));
+ } catch (MissingMethodException e) {
+ WriteMessage(MessageLevel.Error, String.Format("The type '{0}' in the assembly '{1}' does not have an appropriate constructor. The error message is: {2}", type_name, assembly_path, e.Message));
+ } catch (TargetInvocationException e) {
+ WriteMessage(MessageLevel.Error, String.Format("An error occured while attempting to instantiate the type '{0}' in the assembly '{1}'. The error message is: {2}", type_name, assembly_path, e.InnerException.Message));
+ } catch (InvalidCastException) {
+ WriteMessage(MessageLevel.Error, String.Format("The type '{0}' in the assembly '{1}' is not a SyntaxGenerator.", type_name, assembly_path));
+ }
+ }
+
+ WriteMessage(MessageLevel.Info, String.Format("Loaded {0} syntax generators.", generators.Count));
+
+ }
+
+ private XPathExpression syntax_input;
+
+ private XPathExpression syntax_output;
+
+ private Type writerType;
+
+ private List<SyntaxGenerator> generators = new List<SyntaxGenerator>();
+
+ public override void Apply (XmlDocument document, string key) {
+
+ XPathNavigator input = document.CreateNavigator().SelectSingleNode(syntax_input);
+ if (input == null) Console.WriteLine("null input");
+
+ XPathNavigator output = document.CreateNavigator().SelectSingleNode(syntax_output);
+ if (output == null) Console.WriteLine("null output");
+
+ SyntaxWriter writer = (SyntaxWriter) Activator.CreateInstance(writerType, new Object[1] { output });
+
+ foreach (SyntaxGenerator generator in generators) {
+ generator.WriteSyntax(input, writer);
+ }
+
+ }
+
+ }
+
+ // the writer
+
+ public abstract class SyntaxWriter {
+
+ protected SyntaxWriter (XPathNavigator location) {}
+
+ // Syntax block APIs
+
+ public virtual int Position {
+ get {
+ return (-1);
+ }
+ }
+
+ public abstract void WriteStartBlock(string language);
+
+ public abstract void WriteStartSubBlock(string classId);
+
+ public abstract void WriteEndSubBlock();
+
+ public abstract void WriteString(string text);
+
+ public abstract void WriteStringWithStyle (string text, string style);
+
+ public abstract void WriteReferenceLink (string reference);
+
+ public abstract void WriteReferenceLink (string reference, string text);
+
+ public virtual void WriteLine () {
+ WriteString("\n");
+ }
+
+ public virtual void WriteKeyword (string keyword) {
+ WriteStringWithStyle(keyword, "keyword");
+ }
+
+ public virtual void WriteParameter (string parameter) {
+ WriteStringWithStyle(parameter, "parameter");
+ }
+
+ public virtual void WriteIdentifier (string identifier) {
+ WriteStringWithStyle(identifier, "identifier");
+ }
+
+ public virtual void WriteLiteral (string literal) {
+ WriteStringWithStyle(literal, "literal");
+ }
+
+ public virtual void WriteMessage(string message)
+ {
+ WriteMessage(message, null);
+ }
+
+ public abstract void WriteMessage(string message, IEnumerable<string> parameters);
+
+ public abstract void WriteEndBlock();
+
+ }
+
+ // the concrete writer
+ // the should really be moved out
+
+ public class ManagedSyntaxWriter : SyntaxWriter {
+
+ public ManagedSyntaxWriter (XPathNavigator location) : base(location) {
+ if (location == null) Console.WriteLine("null location");
+ this.location = location;
+ }
+
+ XPathNavigator location;
+
+ XmlWriter writer;
+
+ // position along the line
+ int position = 0;
+
+ public override int Position {
+ get {
+ return (position);
+ }
+ }
+
+ public override void WriteStartBlock(string language)
+ {
+ writer = location.AppendChild();
+ writer.WriteStartElement("div");
+ writer.WriteAttributeString("codeLanguage", language);
+ position = 0;
+ }
+
+ public override void WriteStartSubBlock(string classId)
+ {
+ writer.WriteStartElement("div");
+ writer.WriteAttributeString("class", classId);
+ position = 0;
+ }
+
+ public override void WriteEndSubBlock()
+ {
+ writer.WriteEndElement();
+ position = 0;
+ }
+
+ public override void WriteLine () {
+ base.WriteLine();
+ position = 0;
+ }
+
+ public override void WriteString(string text)
+ {
+ writer.WriteString(text);
+ position += text.Length;
+ }
+
+ public override void WriteStringWithStyle (string text, string style) {
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", style);
+ WriteString(text);
+ writer.WriteEndElement();
+ position += text.Length;
+ }
+
+ public override void WriteReferenceLink (string reference) {
+ writer.WriteStartElement("referenceLink");
+ writer.WriteAttributeString("target", reference);
+ writer.WriteAttributeString("prefer-overload", "false");
+ writer.WriteAttributeString("show-container", "false");
+ writer.WriteAttributeString("show-templates", "false");
+ writer.WriteAttributeString("show-parameters", "false");
+ writer.WriteEndElement();
+ position += 10; // approximate
+ }
+
+ public override void WriteReferenceLink (string reference, string text) {
+ writer.WriteStartElement("referenceLink");
+ writer.WriteAttributeString("target", reference);
+ writer.WriteAttributeString("prefer-overload", "false");
+ writer.WriteAttributeString("show-container", "false");
+ writer.WriteAttributeString("show-templates", "false");
+ writer.WriteAttributeString("show-parameters", "false");
+ writer.WriteString(text);
+ writer.WriteEndElement();
+ position += text.Length;
+ }
+
+ public override void WriteEndBlock () {
+ writer.WriteEndElement();
+ writer.Close();
+ position = 0;
+ }
+
+ public override void WriteMessage(string message, IEnumerable<string> parameters)
+ {
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "message");
+ writer.WriteStartElement("include");
+ writer.WriteAttributeString("item", message);
+ if (parameters != null)
+ {
+ foreach (string parameter in parameters)
+ {
+ writer.WriteStartElement("parameter");
+ writer.WriteRaw(parameter);
+ writer.WriteEndElement();
+ }
+ }
+ writer.WriteEndElement();
+ writer.WriteEndElement();
+ }
+
+ }
+
+ // the abstract generator
+
+ public abstract class SyntaxGenerator {
+
+ protected SyntaxGenerator (XPathNavigator configuration) { }
+
+ public abstract void WriteSyntax (XPathNavigator reflection, SyntaxWriter writer);
+
+ }
+
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TargetCollection.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TargetCollection.cs
new file mode 100644
index 0000000..188da53
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TargetCollection.cs
@@ -0,0 +1,2739 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ // The basic object model here is this:
+ // * Target objects represent files that can be targeted by a reference link
+ // * Different child objects of Target represent different sorts of API targets: Namespace, Type, Member, etc.
+ // * Targets are stored in a TargetCollection
+ // To indicate relationships between targets (e.g. a Method takes a particular type parameter), we
+ // introduce another set of classes:
+ // * Reference objects refer to a specific target
+ // * Objects like SpecializedTypeReference and ArrayTypeReference that represent decorated types
+ // There are two ways to construct such objects:
+ // * XML from a reflection information file defines Target and Reference objects. XmlUtilities does this.
+ // * Code entity reference strings construct Reference objecs. CerUtilities does this.
+ // Finally, we need a way to write the link text corresponding to a reference:
+ // * LinkTextResolver contains routines that, given a reference, writes the corresponding link text
+
+ // all arguments of public methods are verified
+
+ // The fact that the creation methods (via XML or CER strings) for references and their rendering methods
+ // are seperated from the declarations of the reference types goes against OO principals. (The consequent
+ // absence of virtual methods also makes for a lot of ugly casting to figure out what method to call.)
+ // But there is a reason for it: I wanted all the code that intrepreted XML together, all the code that
+ // intrepreted CER strings together, and all the code that did link text renderig together, and I wanted
+ // them all seperate from each other. I belive this is extremely important for maintainability. It may
+ // be possible to leverage partial classes to do this in a more OO fashion.
+
+ public class Test {
+
+ public static void Main (string[] args) {
+
+ TargetCollection targets = new TargetCollection();
+
+ XPathDocument document = new XPathDocument(args[0]);
+ XPathNavigator node = document.CreateNavigator();
+ XmlTargetCollectionUtilities.AddTargets(targets, node, LinkType2.Local);
+ Console.WriteLine(targets.Count);
+
+ LinkTextResolver resolver = new LinkTextResolver(targets);
+
+ // test writer
+ XmlWriterSettings settings = new XmlWriterSettings();
+ settings.Indent = true;
+ XmlWriter writer = XmlWriter.Create(Console.Out, settings);
+ writer.WriteStartDocument();
+ writer.WriteStartElement("types");
+ XPathNodeIterator apiNodes = node.Select("/*/apis/api[not(apidata/@subgroup='enumeration')]//*[@display-api]");
+ foreach (XPathNavigator apiNode in apiNodes) {
+ string api = apiNode.GetAttribute("display-api", String.Empty);
+ if (api[1] != ':') continue;
+
+ string id = (string) apiNode.Evaluate("string(ancestor::api[1]/@id)");
+ TextReferenceUtilities.SetGenericContext(id);
+
+ Reference reference = TextReferenceUtilities.CreateReference(api);
+
+ writer.WriteStartElement("test");
+ writer.WriteAttributeString("api", api);
+ writer.WriteAttributeString("context", id);
+ if (reference == null) {
+ writer.WriteString("NULL REFERENCE");
+ } else {
+ resolver.WriteReference(reference, DisplayOptions.ShowContainer | DisplayOptions.ShowTemplates | DisplayOptions.ShowParameters, writer);
+ }
+ writer.WriteEndElement();
+
+ }
+
+ writer.WriteEndElement();
+ writer.WriteEndDocument();
+ writer.Close();
+
+ }
+
+ }
+
+ // contains a collection of targets
+
+ public class TargetCollection {
+
+ private Dictionary<string, Target> index = new Dictionary<string, Target>();
+
+ // read the collection
+
+ public Target this[string id] {
+ get {
+ Target result;
+ index.TryGetValue(id, out result);
+ return (result);
+ }
+ }
+
+ public bool Contains (string id) {
+ return( index.ContainsKey(id) );
+ }
+
+ public IEnumerable<string> Ids {
+ get {
+ return (index.Keys);
+ }
+ }
+
+ public IEnumerable<Target> Targets {
+ get {
+ return (index.Values);
+ }
+ }
+
+ public int Count {
+ get {
+ return(index.Count);
+ }
+ }
+
+ // change the collection
+
+ public void Add (Target target) {
+ index[target.Id] = target;
+ //index.Add(target.Id, target);
+ }
+
+ public void Clear () {
+ index.Clear();
+ }
+
+ }
+
+ // targets
+
+ public class Target {
+
+ internal string id;
+
+ internal string container;
+
+ internal string file;
+
+ internal LinkType2 type;
+
+ public string Id {
+ get {
+ return (id);
+ }
+ }
+
+ public string Container {
+ get {
+ return (container);
+ }
+ }
+
+ public string File {
+ get {
+ return(file);
+ }
+ }
+
+ internal LinkType2 DefaultLinkType {
+ get {
+ return (type);
+ }
+ }
+
+ public virtual void Add (TargetCollection targets) {
+ targets.Add(this);
+ }
+
+ }
+
+ public class NamespaceTarget : Target {
+
+ internal string name;
+
+ public string Name {
+ get {
+ return(name);
+ }
+ }
+
+ }
+
+ public class TypeTarget : Target {
+
+ internal string name;
+
+ internal NamespaceReference containingNamespace;
+
+ internal SimpleTypeReference containingType;
+
+ internal string[] templates;
+
+ public string Name {
+ get {
+ return(name);
+ }
+ }
+
+ public NamespaceReference Namespace {
+ get {
+ return (containingNamespace);
+ }
+ }
+
+ public SimpleTypeReference OuterType {
+ get {
+ return (containingType);
+ }
+ }
+
+ public string[] Templates {
+ get {
+ return(templates);
+ }
+ }
+
+ }
+
+ public class EnumerationTarget : TypeTarget {
+
+ internal MemberTarget[] elements;
+
+ public override void Add (TargetCollection targets) {
+ base.Add(targets);
+
+ foreach (MemberTarget element in elements) {
+ element.Add(targets);
+ }
+ }
+
+ }
+
+ public class MemberTarget : Target {
+
+ internal string name;
+
+ internal SimpleTypeReference containingType;
+
+ internal string overload;
+
+ public string Name {
+ get {
+ return (name);
+ }
+ }
+
+ public TypeReference Type {
+ get {
+ return (containingType);
+ }
+ }
+
+ public string OverloadId {
+ get {
+ return (overload);
+ }
+ }
+
+ }
+
+ public class ConstructorTarget : MemberTarget {
+
+ internal Parameter[] parameters;
+
+ public Parameter[] Parameters {
+ get {
+ return (parameters);
+ }
+ }
+
+ }
+
+ public class ProcedureTarget : MemberTarget {
+
+ internal bool conversionOperator;
+
+ internal MemberReference explicitlyImplements = null;
+
+ public bool ConversionOperator {
+ get {
+ return (conversionOperator);
+ }
+ }
+
+ public MemberReference ExplicitlyImplements {
+ get {
+ return (explicitlyImplements);
+ }
+ }
+
+ }
+
+ public class EventTarget : ProcedureTarget {
+ }
+
+ public class PropertyTarget : ProcedureTarget {
+
+ internal Parameter[] parameters;
+
+ internal TypeReference returnType;
+
+ public Parameter[] Parameters {
+ get {
+ return (parameters);
+ }
+ }
+
+ }
+
+ public class MethodTarget : ProcedureTarget {
+
+ internal Parameter[] parameters;
+
+ internal TypeReference returnType;
+
+ internal string[] templates;
+
+ public Parameter[] Parameters {
+ get {
+ return (parameters);
+ }
+ }
+
+ public string[] Templates {
+ get {
+ return (templates);
+ }
+ }
+
+ // property to hold specialized template arguments (used with extension methods)
+ internal TypeReference[] templateArgs;
+ public TypeReference[] TemplateArgs
+ {
+ get
+ {
+ return (templateArgs);
+ }
+ }
+
+ }
+
+ public class Parameter {
+
+ private string name;
+
+ private TypeReference type;
+
+ public string Name {
+ get {
+ return (name);
+ }
+ }
+
+ public TypeReference Type {
+ get {
+ return (type);
+ }
+ }
+
+
+ internal Parameter (string name, TypeReference type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ }
+
+ // ***** Reference objects *****
+
+ public abstract class Reference { }
+
+ public class NamespaceReference : Reference {
+
+ private string namespaceId;
+
+ public string Id {
+ get {
+ return(namespaceId);
+ }
+ }
+
+ public Target Resolve (TargetCollection targets) {
+ return(targets[namespaceId]);
+ }
+
+ internal NamespaceReference (string id) {
+ this.namespaceId = id;
+ }
+
+ }
+
+ public abstract class TypeReference : Reference {}
+
+ public class SimpleTypeReference : TypeReference {
+
+ private string typeId;
+
+ public string Id {
+ get {
+ return(typeId);
+ }
+ }
+
+ public Target Resolve (TargetCollection targets) {
+ return(targets[typeId]);
+ }
+
+ internal SimpleTypeReference (string id) {
+ this.typeId = id;
+ }
+
+ }
+
+ public class SpecializedTypeReference : TypeReference {
+
+ private Specialization[] specializations;
+
+ public Specialization[] Specializations {
+ get {
+ return (specializations);
+ }
+ }
+
+ internal SpecializedTypeReference (Specialization[] specializations) {
+ if (specializations == null) throw new ArgumentNullException("specializations");
+ this.specializations = specializations;
+ }
+
+ public Dictionary<IndexedTemplateTypeReference, TypeReference> GetSpecializationDictionary () {
+ Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary = new Dictionary<IndexedTemplateTypeReference, TypeReference>();
+ foreach (Specialization specialization in specializations) {
+ for (int index=0; index<specialization.Arguments.Length; index++) {
+ IndexedTemplateTypeReference template = new IndexedTemplateTypeReference(specialization.TemplateType.Id, index);
+ dictionary.Add(template, specialization.Arguments[index]);
+ }
+ }
+ return (dictionary);
+ }
+
+ }
+
+ public class Specialization {
+
+ private SimpleTypeReference template;
+
+ public TypeReference[] arguments;
+
+ public SimpleTypeReference TemplateType {
+ get {
+ return (template);
+ }
+ }
+
+ [CLSCompliant(false)]
+ public TypeReference[] Arguments {
+ get {
+ return (arguments);
+ }
+ }
+
+ internal Specialization (SimpleTypeReference template, TypeReference[] arguments) {
+ if (template == null) throw new ArgumentNullException("template");
+ if (arguments == null) throw new ArgumentNullException("arguments");
+ this.template = template;
+ this.arguments = arguments;
+ }
+
+ }
+
+ public abstract class TemplateTypeReference : TypeReference { }
+
+ public class IndexedTemplateTypeReference : TemplateTypeReference {
+
+ private string templateId;
+
+ private int index;
+
+ public string TemplateId {
+ get {
+ return (templateId);
+ }
+ }
+
+ public int Index {
+ get {
+ return (index);
+ }
+ }
+
+ internal IndexedTemplateTypeReference (string templateId, int index) {
+ if (templateId == null) throw new ArgumentNullException("templateId");
+ if (index < 0) throw new ArgumentOutOfRangeException("index");
+ this.templateId = templateId;
+ this.index = index;
+ }
+
+ public override int GetHashCode () {
+ return (index ^ templateId.GetHashCode());
+ }
+
+ public override bool Equals (object obj) {
+ IndexedTemplateTypeReference other = obj as IndexedTemplateTypeReference;
+ if (other == null) return (false);
+ if ((this.index == other.index) && (this.templateId == other.templateId)) {
+ return (true);
+ } else {
+ return (false);
+ }
+ }
+ }
+
+ public class NamedTemplateTypeReference : TemplateTypeReference {
+
+ private string name;
+
+ public string Name {
+ get {
+ return (name);
+ }
+ }
+
+ public NamedTemplateTypeReference (string name) {
+ this.name = name;
+ }
+
+ }
+
+ public class TypeTemplateTypeReference : TemplateTypeReference {
+
+ private SimpleTypeReference template;
+
+ private int position;
+
+ public SimpleTypeReference TemplateType {
+ get {
+ return (template);
+ }
+ }
+
+ public int Position {
+ get {
+ return (position);
+ }
+ }
+
+ internal TypeTemplateTypeReference (SimpleTypeReference template, int position) {
+ if (template == null) throw new ArgumentNullException("template");
+ if (position < 0) throw new ArgumentOutOfRangeException("position");
+ this.template = template;
+ this.position = position;
+ }
+
+ }
+
+ public class MethodTemplateTypeReference : TemplateTypeReference {
+
+ private MemberReference template;
+
+ private int position;
+
+ public MemberReference TemplateMethod {
+ get {
+ return (template);
+ }
+ }
+
+ public int Position {
+ get {
+ return (position);
+ }
+ }
+
+ internal MethodTemplateTypeReference (MemberReference template, int position) {
+ this.template = template;
+ this.position = position;
+ }
+
+ }
+
+ public class ArrayTypeReference : TypeReference {
+
+ private int rank;
+
+ private TypeReference elementType;
+
+ public int Rank {
+ get {
+ return(rank);
+ }
+ }
+
+ public TypeReference ElementType {
+ get {
+ return(elementType);
+ }
+ }
+
+ internal ArrayTypeReference (TypeReference elementType, int rank) {
+ if (elementType == null) throw new ArgumentNullException("elementType");
+ if (rank <= 0) throw new ArgumentOutOfRangeException("rank");
+ this.elementType = elementType;
+ this.rank = rank;
+ }
+
+ }
+
+ public class ReferenceTypeReference : TypeReference {
+
+ private TypeReference referedToType;
+
+ public TypeReference ReferedToType {
+ get {
+ return (referedToType);
+ }
+ }
+
+ internal ReferenceTypeReference (TypeReference referedToType) {
+ if (referedToType == null) throw new ArgumentNullException("referedToType");
+ this.referedToType = referedToType;
+ }
+ }
+
+ public class PointerTypeReference : TypeReference {
+
+ private TypeReference pointedToType;
+
+ public TypeReference PointedToType {
+ get {
+ return (pointedToType);
+ }
+ }
+
+ internal PointerTypeReference (TypeReference pointedToType) {
+ if (pointedToType == null) throw new ArgumentNullException("pointedToType");
+ this.pointedToType = pointedToType;
+ }
+ }
+
+
+ public abstract class MemberReference : Reference { }
+
+ /// <summary>
+ /// Contains the information to generate the display string for an extension method link
+ /// </summary>
+ public class ExtensionMethodReference : Reference
+ {
+ private string methodName;
+ public string Name
+ {
+ get
+ {
+ return (methodName);
+ }
+ }
+
+ private Parameter[] parameters;
+ public Parameter[] Parameters
+ {
+ get
+ {
+ return (parameters);
+ }
+ }
+
+ private TypeReference[] templateArgs;
+ public TypeReference[] TemplateArgs
+ {
+ get
+ {
+ return (templateArgs);
+ }
+ }
+
+ internal ExtensionMethodReference(string methodName, Parameter[] parameters, TypeReference[] templateArgs)
+ {
+ if (methodName == null)
+ throw new ArgumentNullException("methodName");
+ this.methodName = methodName;
+ this.parameters = parameters;
+ this.templateArgs = templateArgs;
+ }
+ }
+
+
+ public class SimpleMemberReference : MemberReference {
+
+ private string memberId;
+
+ public string Id {
+ get {
+ return(memberId);
+ }
+ }
+
+ public Target Resolve (TargetCollection targets) {
+ return(targets[memberId]);
+ }
+
+ internal SimpleMemberReference (string id) {
+ if (id == null) throw new ArgumentNullException("id");
+ this.memberId = id;
+ }
+
+ }
+
+
+ public class SpecializedMemberReference : MemberReference {
+
+ private SimpleMemberReference member;
+
+ private SpecializedTypeReference type;
+
+ public SimpleMemberReference TemplateMember {
+ get {
+ return(member);
+ }
+ }
+
+ public SpecializedTypeReference SpecializedType {
+ get {
+ return (type);
+ }
+ }
+
+ internal SpecializedMemberReference (SimpleMemberReference member, SpecializedTypeReference type) {
+ if (member == null) throw new ArgumentNullException("member");
+ if (type == null) throw new ArgumentNullException("type");
+ this.member = member;
+ this.type = type;
+ }
+
+ }
+
+ public class SpecializedMemberWithParametersReference : MemberReference {
+
+ private string prefix;
+
+ private SpecializedTypeReference type;
+
+ private string member;
+
+ private TypeReference[] parameters;
+
+ public string Prefix {
+ get {
+ return (prefix);
+ }
+ }
+
+ public SpecializedTypeReference SpecializedType {
+ get {
+ return (type);
+ }
+ }
+
+ public string MemberName {
+ get {
+ return (member);
+ }
+ }
+
+ public TypeReference[] ParameterTypes {
+ get {
+ return(parameters);
+ }
+ }
+
+ internal SpecializedMemberWithParametersReference (string prefix, SpecializedTypeReference type, string member, TypeReference[] parameters) {
+ if (type == null) throw new ArgumentNullException("type");
+ if (parameters == null) throw new ArgumentNullException("parameters");
+ this.prefix = prefix;
+ this.type = type;
+ this.member = member;
+ this.parameters = parameters;
+ }
+
+ }
+
+ public class InvalidReference : Reference {
+
+ private string id;
+
+ public String Id {
+ get {
+ return (id);
+ }
+ }
+
+ internal InvalidReference (string id) {
+ this.id = id;
+ }
+
+ }
+
+ // ***** Logic to construct Target & Reference objects from XML reflection data *****
+ // Anything that depends on specifics of the XML reflection data format lives here
+
+ public static class XmlTargetCollectionUtilities {
+
+ // XPath expressions for extracting data
+
+ // topic data
+ private static XPathExpression topicIdExpression = XPathExpression.Compile("string(@id)");
+ private static XPathExpression topicContainerExpression = XPathExpression.Compile("string(containers/library/@assembly)");
+ private static XPathExpression topicFileExpression = XPathExpression.Compile("string(file/@name)");
+ private static XPathExpression topicGroupExpression = XPathExpression.Compile("string(topicdata/@group)");
+
+ // api data
+ private static XPathExpression apiNameExpression = XPathExpression.Compile("string(apidata/@name)");
+ private static XPathExpression apiGroupExpression = XPathExpression.Compile("string(apidata/@group)");
+ private static XPathExpression apiSubgroupExpression = XPathExpression.Compile("string(apidata/@subgroup)");
+ private static XPathExpression apiSubsubgroupExpression = XPathExpression.Compile("string(apidata/@subsubgroup)");
+
+ // member data
+ private static XPathExpression apiOverloadIdExpression = XPathExpression.Compile("string(overload/@api | memberdata/@overload)");
+
+ // explicit implmentation data
+ private static XPathExpression apiIsExplicitImplementationExpression = XPathExpression.Compile("boolean(memberdata/@visibility='private' and proceduredata/@virtual='true' and boolean(implements/member))");
+ private static XPathExpression apiImplementedMembersExpression = XPathExpression.Compile("implements/member");
+
+ // op_explicit and op_implicit data
+ private static XPathExpression apiIsConversionOperatorExpression = XPathExpression.Compile("boolean((apidata/@subsubgroup='operator') and (apidata/@name='Explicit' or apidata/@name='Implicit'))");
+
+ // container data
+ private static XPathExpression apiContainingNamespaceExpression = XPathExpression.Compile("(containers/namespace)[1]");
+ private static XPathExpression apiContainingTypeExpression = XPathExpression.Compile("(containers/type)[1]");
+
+ // reference data
+ private static XPathExpression referenceApiExpression = XPathExpression.Compile("string(@api)");
+
+ // template data
+ private static XPathExpression apiTemplatesExpression = XPathExpression.Compile("templates/template");
+ private static XPathExpression templateNameExpression = XPathExpression.Compile("string(@name)");
+
+ // extension method template data
+ private static XPathExpression methodTemplateArgsExpression = XPathExpression.Compile("templates/*");
+
+ // Change the container
+
+ public static string ContainerExpression {
+ get {
+ return (topicContainerExpression.Expression);
+ }
+ set {
+ topicContainerExpression = XPathExpression.Compile(value);
+ }
+ }
+
+ // super factory method
+
+ public static void AddTargets (TargetCollection targets, XPathNavigator topicsNode, LinkType2 type) {
+ XPathNodeIterator topicNodes = topicsNode.Select("/*/apis/api[not(topicdata/@notopic)]");
+ foreach (XPathNavigator topicNode in topicNodes) {
+ Target target = CreateTarget(topicNode, type);
+ if (target != null) target.Add(targets);
+ }
+ }
+
+ // Target factory methods
+
+ public static Target CreateTarget (XPathNavigator topic, LinkType2 type) {
+ if (topic == null) throw new ArgumentNullException("topic");
+
+ bool isApiTarget = (bool)topic.Evaluate("boolean(apidata)");
+
+ Target target;
+ if (isApiTarget) {
+ target = CreateApiTarget(topic, type);
+ } else {
+ target = new Target();
+ }
+
+ if (target == null) throw new XmlSchemaValidationException(String.Format("The target file '{0}' is not valid.", topic.BaseURI));
+
+ target.id = (string)topic.Evaluate(topicIdExpression);
+ if (String.IsNullOrEmpty(target.id)) throw new XmlSchemaValidationException(String.Format("The target file '{0}' is not valid.", topic.BaseURI));
+
+ target.container = (string)topic.Evaluate(topicContainerExpression);
+
+ target.file = (string)topic.Evaluate(topicFileExpression);
+ if (String.IsNullOrEmpty(target.file)) throw new XmlSchemaValidationException(String.Format("The target file '{0}' is not valid.", topic.BaseURI));
+
+ target.type = type;
+
+ return(target);
+ }
+
+ private static Target CreateApiTarget (XPathNavigator api, LinkType2 linkType) {
+ string subGroup = (string) api.Evaluate(apiGroupExpression);
+ if (subGroup == "namespace") {
+ return( CreateNamespaceTarget(api) );
+ } else if (subGroup == "type") {
+ return (CreateTypeTarget(api, linkType));
+ } else if (subGroup == "member") {
+ return (CreateMemberTarget(api));
+ } else {
+ return (null);
+ }
+
+ }
+
+ private static NamespaceTarget CreateNamespaceTarget (XPathNavigator api) {
+ NamespaceTarget target = new NamespaceTarget();
+ target.name = (string) api.Evaluate(apiNameExpression);
+ if (String.IsNullOrEmpty(target.name)) target.name = "(Default Namespace)";
+ return(target);
+ }
+
+ private static TypeTarget CreateTypeTarget (XPathNavigator api, LinkType2 linkType) {
+ string subgroup = (string)api.Evaluate(apiSubgroupExpression);
+
+ TypeTarget target;
+ if (subgroup == "enumeration") {
+ target = CreateEnumerationTarget(api, linkType);
+ } else {
+ target = new TypeTarget();
+ }
+
+ target.name = (string) api.Evaluate(apiNameExpression);
+
+ // containing namespace
+ XPathNavigator namespaceNode = api.SelectSingleNode(apiContainingNamespaceExpression);
+ target.containingNamespace = CreateNamespaceReference(namespaceNode);
+
+ // containing type, if any
+ XPathNavigator typeNode = api.SelectSingleNode(apiContainingTypeExpression);
+ if (typeNode == null) {
+ target.containingType = null;
+ } else {
+ target.containingType = CreateSimpleTypeReference(typeNode);
+ }
+
+ // templates
+ target.templates = GetTemplateNames(api);
+
+ return(target);
+ }
+
+ private static string[] GetTemplateNames (XPathNavigator api) {
+ List<string> templates = new List<string>();
+ XPathNodeIterator templateNodes = api.Select(apiTemplatesExpression);
+ foreach (XPathNavigator templateNode in templateNodes) {
+ templates.Add((string)templateNode.Evaluate(templateNameExpression));
+ }
+ return(templates.ToArray());
+ }
+
+ private static EnumerationTarget CreateEnumerationTarget (XPathNavigator api, LinkType2 linkType) {
+
+ EnumerationTarget enumeration = new EnumerationTarget();
+
+ string typeId = (string) api.Evaluate(topicIdExpression);
+ string file = (string) api.Evaluate(topicFileExpression);
+
+ // Create tar
+ List<MemberTarget> members = new List<MemberTarget>();
+ XPathNodeIterator elementNodes = api.Select("elements/element");
+ foreach (XPathNavigator elementNode in elementNodes) {
+ string memberId = elementNode.GetAttribute("api", String.Empty);
+
+ // try to get name from attribute on element node
+ string memberName = elementNode.GetAttribute("name", String.Empty);
+ if (String.IsNullOrEmpty(memberName)) {
+ // if we can't do that, try to get the name by searching the file for the <api> element of that member
+ XPathNavigator memberApi = api.SelectSingleNode(String.Format("following-sibling::api[@id='{0}']", memberId));
+ if (memberApi != null) {
+ memberName = (string) memberApi.Evaluate(apiNameExpression);
+ } else {
+ // if all else fails, get the name by parsing the identifier
+ string arguments;
+ string type;
+ TextReferenceUtilities.DecomposeMemberIdentifier(memberId, out type, out memberName, out arguments);
+ }
+ }
+
+ MemberTarget member = new MemberTarget();
+ member.id = memberId; // get Id from element
+ member.file = file; // get file from type file
+ member.type = linkType;
+ member.name = memberName; // get name from element
+ member.containingType = new SimpleTypeReference(typeId); // get containing type from this type
+ members.Add(member);
+ }
+
+ enumeration.elements = members.ToArray();
+
+ return (enumeration);
+ }
+
+ public static MemberTarget CreateMemberTarget (XPathNavigator api) {
+
+ string subgroup = (string)api.Evaluate(apiSubgroupExpression);
+
+ MemberTarget target;
+ if (subgroup == "method") {
+ target = CreateMethodTarget(api);
+ } else if (subgroup == "property") {
+ target = CreatePropertyTarget(api);
+ } else if (subgroup == "constructor") {
+ target = CreateConstructorTarget(api);
+ } else if (subgroup == "event") {
+ target = CreateEventTarget(api);
+ } else {
+ target = new MemberTarget();
+ }
+
+ target.name = (string) api.Evaluate(apiNameExpression);
+ target.containingType = CreateSimpleTypeReference( api.SelectSingleNode(apiContainingTypeExpression) );
+ target.overload = (string) api.Evaluate(apiOverloadIdExpression);
+
+ return (target);
+ }
+
+ private static MethodTarget CreateMethodTarget (XPathNavigator api) {
+ MethodTarget target = new MethodTarget();
+ target.parameters = CreateParameterList(api);
+ target.returnType = CreateReturnType(api);
+
+ target.conversionOperator = (bool)api.Evaluate(apiIsConversionOperatorExpression);
+
+ if ((bool)api.Evaluate(apiIsExplicitImplementationExpression)) {
+ target.explicitlyImplements = CreateMemberReference(api.SelectSingleNode(apiImplementedMembersExpression));
+ }
+
+ // this selects templates/template or templates/type, because extension methods can have a mix of generic and specialization
+ XPathNodeIterator templateArgNodes = api.Select(methodTemplateArgsExpression);
+ TypeReference[] templateArgumentReferences = null;
+ if (templateArgNodes != null && templateArgNodes.Count > 0)
+ {
+ templateArgumentReferences = new TypeReference[templateArgNodes.Count];
+ int i = 0;
+ foreach (XPathNavigator templateArgNode in templateArgNodes)
+ {
+ templateArgumentReferences[i] = CreateTypeReference(templateArgNode);
+ i++;
+ }
+ }
+ target.templateArgs = templateArgumentReferences;
+
+ // get the short name of each template param
+ target.templates = GetTemplateNames(api);
+
+ return (target);
+ }
+
+ private static PropertyTarget CreatePropertyTarget (XPathNavigator api) {
+ PropertyTarget target = new PropertyTarget();
+ target.parameters = CreateParameterList(api);
+ target.returnType = CreateReturnType(api);
+
+ if ((bool)api.Evaluate(apiIsExplicitImplementationExpression)) {
+ target.explicitlyImplements = CreateMemberReference(api.SelectSingleNode(apiImplementedMembersExpression));
+ }
+
+ return (target);
+ }
+
+ private static EventTarget CreateEventTarget (XPathNavigator api) {
+ EventTarget target = new EventTarget();
+ if ((bool)api.Evaluate(apiIsExplicitImplementationExpression)) {
+ target.explicitlyImplements = CreateMemberReference(api.SelectSingleNode(apiImplementedMembersExpression));
+ }
+ return (target);
+ }
+
+ private static ConstructorTarget CreateConstructorTarget (XPathNavigator api) {
+ ConstructorTarget target = new ConstructorTarget();
+ target.parameters = CreateParameterList(api);
+ return (target);
+ }
+
+ private static Parameter[] CreateParameterList (XPathNavigator api) {
+ List<Parameter> parameters = new List<Parameter>();
+ XPathNodeIterator parameterNodes = api.Select("parameters/parameter");
+ foreach (XPathNavigator parameterNode in parameterNodes) {
+ string name = parameterNode.GetAttribute("name", String.Empty);
+ XPathNavigator type = parameterNode.SelectSingleNode("*[1]");
+ Parameter parameter = new Parameter(name, CreateTypeReference(type));
+ parameters.Add(parameter);
+ }
+ return (parameters.ToArray());
+ }
+
+ private static TypeReference CreateReturnType (XPathNavigator api) {
+ XPathNavigator returnTypeNode = api.SelectSingleNode("returns/*[1]");
+ if (returnTypeNode == null) {
+ return (null);
+ } else {
+ return (CreateTypeReference(returnTypeNode));
+ }
+ }
+
+ // reference factory
+
+ public static Reference CreateReference (XPathNavigator node) {
+ if (node == null) throw new ArgumentNullException("node");
+ if (node.NodeType == XPathNodeType.Element) {
+ string tag = node.LocalName;
+ if (tag == "namespace") return(CreateNamespaceReference(node));
+ if (tag == "member") return (CreateMemberReference(node));
+ return (CreateTypeReference(node));
+ } else {
+ return (null);
+ }
+ }
+
+ public static NamespaceReference CreateNamespaceReference (XPathNavigator namespaceElement) {
+ if (namespaceElement == null) throw new ArgumentNullException("namespaceElement");
+ string api = (string) namespaceElement.Evaluate(referenceApiExpression);
+ NamespaceReference reference = new NamespaceReference(api);
+ return(reference);
+ }
+
+ public static TypeReference CreateTypeReference (XPathNavigator node) {
+ if (node == null) throw new ArgumentNullException("reference");
+ string tag = node.LocalName;
+ if (tag == "type") {
+ bool isSpecialized = (bool)node.Evaluate("boolean(.//specialization)");
+ if (isSpecialized) {
+ return (CreateSpecializedTypeReference(node));
+ } else {
+ return (CreateSimpleTypeReference(node));
+ }
+ } else if (tag == "arrayOf") {
+ string rankValue = node.GetAttribute("rank", String.Empty);
+ XPathNavigator elementNode = node.SelectSingleNode("*[1]");
+ return (new ArrayTypeReference(CreateTypeReference(elementNode), Convert.ToInt32(rankValue)));
+ } else if (tag == "referenceTo") {
+ XPathNavigator referedToNode = node.SelectSingleNode("*[1]");
+ return (new ReferenceTypeReference(CreateTypeReference(referedToNode)));
+ } else if (tag == "pointerTo") {
+ XPathNavigator pointedToNode = node.SelectSingleNode("*[1]");
+ return (new PointerTypeReference(CreateTypeReference(pointedToNode)));
+ } else if (tag == "template") {
+ string nameValue = node.GetAttribute("name", String.Empty);
+ string indexValue = node.GetAttribute("index", String.Empty);
+ string apiValue = node.GetAttribute("api", String.Empty);
+ if ((!String.IsNullOrEmpty(apiValue)) && (!String.IsNullOrEmpty(indexValue))) {
+ return (new IndexedTemplateTypeReference(apiValue, Convert.ToInt32(indexValue)));
+ } else {
+ return (new NamedTemplateTypeReference(nameValue));
+ }
+ }
+
+ throw new InvalidOperationException(String.Format("INVALID '{0}'", tag));
+
+ }
+
+ public static SimpleTypeReference CreateSimpleTypeReference (XPathNavigator node) {
+ if (node == null) throw new ArgumentNullException("node");
+ string api = node.GetAttribute("api", String.Empty);
+ SimpleTypeReference reference = new SimpleTypeReference(api);
+ return(reference);
+ }
+
+
+ private static SpecializedTypeReference CreateSpecializedTypeReference (XPathNavigator node) {
+ Stack<Specialization> specializations = new Stack<Specialization>();
+ XPathNavigator typeNode = node.Clone();
+ while (typeNode != null) {
+ specializations.Push(CreateSpecialization(typeNode));
+ typeNode = typeNode.SelectSingleNode("type");
+ }
+ SpecializedTypeReference reference = new SpecializedTypeReference(specializations.ToArray());
+ return (reference);
+ }
+
+ private static Specialization CreateSpecialization (XPathNavigator node) {
+ SimpleTypeReference template = CreateSimpleTypeReference(node);
+
+ List<TypeReference> arguments = new List<TypeReference>();
+ XPathNodeIterator specializationNodes = node.Select("specialization/*");
+ foreach (XPathNavigator specializationNode in specializationNodes) {
+ arguments.Add(CreateTypeReference(specializationNode));
+ }
+
+ Specialization specialization = new Specialization(template, arguments.ToArray());
+ return(specialization);
+ }
+
+
+ public static MemberReference CreateMemberReference (XPathNavigator node) {
+ string api = node.GetAttribute("api", String.Empty);
+ SimpleMemberReference member = new SimpleMemberReference(api);
+
+ bool isSpecialized = (bool)node.Evaluate("boolean(./type//specialization)");
+ if (isSpecialized) {
+ XPathNavigator typeNode = node.SelectSingleNode("type");
+ SpecializedTypeReference type = CreateSpecializedTypeReference(typeNode);
+ return( new SpecializedMemberReference(member, type) );
+ } else {
+ return(member);
+ }
+
+ }
+
+ /// <summary>
+ /// Create an object to store the information to generate the display string for an extension method
+ /// </summary>
+ /// <param name="node">xml node containing the extension method data</param>
+ /// <returns></returns>
+ public static ExtensionMethodReference CreateExtensionMethodReference(XPathNavigator node)
+ {
+ string methodName = (string)node.Evaluate(apiNameExpression);
+ Parameter[] parameters = CreateParameterList(node);
+ TypeReference[] templateArgumentReferences = null;
+ // List<TemplateName> templateNames = new List<TemplateName>();
+
+ // this selects templates/template or templates/type, because extension methods can have a mix of generic and specialization
+ // get the short name of each template param or template arg
+ XPathNodeIterator templateNodes = node.Select(methodTemplateArgsExpression);
+ if (templateNodes != null && templateNodes.Count > 0)
+ {
+ templateArgumentReferences = new TypeReference[templateNodes.Count];
+ int i = 0;
+ foreach (XPathNavigator templateNode in templateNodes)
+ {
+ templateArgumentReferences[i] = CreateTypeReference(templateNode);
+ i++;
+ }
+ }
+ ExtensionMethodReference extMethod = new ExtensionMethodReference(methodName, parameters, templateArgumentReferences);
+ return extMethod;
+ }
+
+ }
+
+ // ***** Logic for constructing references from code entity reference strings *****
+ // Anything that depends on the specific form the ID strings lives here
+
+ public static class TextReferenceUtilities {
+
+ public static Reference CreateReference (string api) {
+ if (String.IsNullOrEmpty(api)) throw new ArgumentException("api");
+
+ Reference reference = null;
+
+ char start = api[0];
+ if (start == 'N') {
+ reference = CreateNamespaceReference(api);
+ } else if (start == 'T') {
+ reference = CreateTypeReference(api);
+ } else {
+ //Console.WriteLine("Creating member reference");
+ reference = CreateMemberReference(api);
+ }
+
+ if (reference == null) {
+ return (new InvalidReference(api));
+ } else {
+ return (reference);
+ }
+
+ }
+
+ public static NamespaceReference CreateNamespaceReference (string api) {
+ if (ValidNamespace.IsMatch(api)) {
+ return( new NamespaceReference(api) );
+ } else {
+ return(null);
+ }
+ }
+
+ public static TypeReference CreateTypeReference (string api) {
+ if (ValidSimpleType.IsMatch(api)) {
+ // this is a reference to a "normal" simple type
+ return (CreateSimpleTypeReference(api));
+ } else if (ValidSpecializedType.IsMatch(api)) {
+ // this is a reference to a specialized type
+ return (CreateSpecializedTypeReference(api));
+ } else if (ValidDecoratedType.IsMatch(api)) {
+ // this is a reference to a type that is decorated or is a template
+ // process array, reference, and pointer decorations
+ char lastCharacter = api[api.Length-1];
+ if (lastCharacter == ']') {
+ // arrays
+ int lastBracketPosition = api.LastIndexOf('[');
+ int rank = api.Length - lastBracketPosition - 1;
+ string elementApi = api.Substring(0, lastBracketPosition);
+ TypeReference elementReference = CreateTypeReference(elementApi);
+ return( new ArrayTypeReference(elementReference, rank) );
+ } else if (lastCharacter == '@') {
+ // references
+ string referedApi = api.Substring(0, api.Length - 1);
+ TypeReference referedReference = CreateTypeReference(referedApi);
+ return (new ReferenceTypeReference(referedReference));
+ } else if (lastCharacter == '*') {
+ // pointers
+ string pointedApi = api.Substring(0, api.Length - 1);
+ TypeReference pointedReference = CreateTypeReference(pointedApi);
+ return (new PointerTypeReference(pointedReference));
+ }
+
+ // process templates
+ if (api.StartsWith("T:``")) {
+ int position = Convert.ToInt32(api.Substring(4));
+ if (genericTypeContext == null) {
+ return (new NamedTemplateTypeReference("UMP"));
+ } else {
+ return (new IndexedTemplateTypeReference(genericTypeContext.Id, position));
+ }
+ } else if (api.StartsWith("T:`")) {
+ int position = Convert.ToInt32(api.Substring(3));
+ if (genericTypeContext == null) {
+ return (new NamedTemplateTypeReference("UTP"));
+ } else {
+ return (new IndexedTemplateTypeReference(genericTypeContext.Id, position));
+ }
+ }
+
+ // we shouldn't get here, because one of those test should have been satisfied if the regex matched
+ throw new InvalidOperationException("Could not parse valid type expression");
+
+ } else {
+ return (null);
+ }
+ }
+
+ private static SimpleTypeReference CreateSimpleTypeReference (string api) {
+ return (new SimpleTypeReference(api));
+ }
+
+ private static SpecializedTypeReference CreateSpecializedTypeReference (string api) {
+
+ List<Specialization> specializations = new List<Specialization>();
+
+ string text = String.Copy(api);
+
+ // at the moment we are only handling one specialization; need to iterate
+
+ int specializationStart = text.IndexOf('{');
+ int specializationEnd = FindMatchingEndBracket(text, specializationStart);
+ string list = text.Substring(specializationStart + 1, specializationEnd - specializationStart - 1);
+ string[] types = SeperateTypes(list);
+ string template = text.Substring(0, specializationStart) + String.Format("`{0}", types.Length);
+
+
+ SimpleTypeReference templateReference = CreateSimpleTypeReference(template);
+ TypeReference[] argumentReferences = new TypeReference[types.Length];
+ for (int i = 0; i < types.Length; i++) {
+ argumentReferences[i] = CreateTypeReference(types[i]);
+ }
+ Specialization specialization = new Specialization(templateReference, argumentReferences);
+
+ specializations.Add(specialization);
+
+ // end iteration
+
+ return (new SpecializedTypeReference(specializations.ToArray()));
+ }
+
+ //private static Regex tr = new Regex(@"^(M:([_a-zA-Z0-9]+\.)*([_a-zA-Z0-9]+(\{.+\})?\.)*[_a-zA-Z0-9]+(\{.+\})?\.([_a-zA-Z0-9]+(\{[^\.]+\})?#)*[_a-zA-Z0-9]+(``\d+)?(\((((([_a-zA-Z0-9]+\.)*([_a-zA-Z0-9]+(\{.+\})?\.)*[_a-zA-Z0-9]+(\{.+\})?)|(`\d+)|(``\d+))(@|\*|(\[\]))*,)*((([_a-zA-Z0-9]+\.)*([_a-zA-Z0-9]+(\{.+\})?\.)*[_a-zA-Z0-9]+(\{.+\})?)|(`\d+)|(``\d+))(@|\*|(\[\]))*\))?(~((([_a-zA-Z0-9]+\.)*([_a-zA-Z0-9]+(\{.+\})?\.)*[_a-zA-Z0-9]+(\{.+\})?)|(`\d+)|(``\d+))(@|\*|(\[\]))*)?)$", RegexOptions.Compiled);
+ //private static Regex tr = new Regex(@"^(M:([_a-zA-Z0-9]+\.)*([_a-zA-Z0-9]+(\{[^:\(\)\s]+\})?\.)*[_a-zA-Z0-9]+(\{[^:\(\)\s]+\})?\.[_a-zA-Z0-9]+(``\d+)?(\((((([_a-zA-Z0-9]+\.)*([_a-zA-Z0-9]+(\{[^:\(\)\s]+\})?\.)*[_a-zA-Z0-9]+(\{[^:\(\)\s]+\})?)|(`\d+)|(``\d+))(@|\*|(\[\]))*,)*((([_a-zA-Z0-9]+\.)*([_a-zA-Z0-9]+(\{[^:\(\)\s]+\})?\.)*[_a-zA-Z0-9]+(\{[^:\(\)\s]+\})?)|(`\d+)|(``\d+))(@|\*|(\[\]))*\))?)$", RegexOptions.Compiled);
+ private static Regex tr = new Regex(@"^(M:([_a-zA-Z0-9]+\.)*[_a-zA-Z0-9]+\.[_a-zA-Z0-9]+(``\d+)?(\((((([_a-zA-Z0-9]+\.)*[_a-zA-Z0-9]+)|(`\d+)|(``\d+))(@|\*|(\[\]))*,)*((([_a-zA-Z0-9]+\.)*[_a-zA-Z0-9]+)|(`\d+)|(``\d+))(@|\*|(\[\]))*\))?)$", RegexOptions.Compiled);
+
+ public static MemberReference CreateMemberReference (string api) {
+ //Console.WriteLine("Testing");
+ //Console.WriteLine(tr.ToString());
+ //Console.WriteLine(api);
+ //Console.WriteLine(tr.IsMatch(api));
+ //Console.WriteLine("Tested");
+ if (ValidSimpleMember.IsMatch(api)) {
+ //Console.WriteLine("Is valid simple member");
+ // this is just a normal member of a simple type
+ return (new SimpleMemberReference(api));
+ } else if (ValidSpecializedMember.IsMatch(api)) {
+ //Console.WriteLine("Is valid specialized member");
+ //Console.WriteLine("cer = {0}", api);
+ // this is a member of a specialized type; we need to extract:
+ // (1) the underlying specialized type, (2) the member name, (3) the arguments
+ //Console.WriteLine("Extracting data");
+
+ // seperate the member prefix
+ int colonPosition = api.IndexOf(':');
+ string prefix = api.Substring(0, colonPosition);
+ string text = api.Substring(colonPosition + 1);
+
+ // get the arguments
+ string arguments = String.Empty;
+ int startParenthesisPosition = text.IndexOf('(');
+ if (startParenthesisPosition > 0) {
+ int endParenthesisPosition = text.LastIndexOf(')');
+ arguments = text.Substring(startParenthesisPosition + 1, endParenthesisPosition - startParenthesisPosition - 1);
+ text = text.Substring(0, startParenthesisPosition);
+ }
+
+ // seperate the type and member name
+ int lastDotPosition;
+ int firstHashPosition = text.IndexOf('#');
+ if (firstHashPosition > 0) {
+ // if this is an EII, the boundry is at the last dot before the hash
+ lastDotPosition = text.LastIndexOf('.', firstHashPosition);
+ } else {
+ // otherwise, the boundry is at the last dot
+ lastDotPosition = text.LastIndexOf('.');
+ }
+ string name = text.Substring(lastDotPosition+1);
+ text = text.Substring(0, lastDotPosition);
+ //Console.WriteLine("type = {0}", "T:" + text);
+
+ // text now contains a specialized generic type; use it to create a reference
+ SpecializedTypeReference type = CreateSpecializedTypeReference("T:" + text);
+
+ // If there are no arguments...
+ // we simply create a reference to a member whoose identifier we construct in the specialized type
+ if (String.IsNullOrEmpty(arguments)) {
+ string typeId = type.Specializations[type.Specializations.Length - 1].TemplateType.Id;
+ string memberId = String.Format("{0}:{1}.{2}", prefix, typeId.Substring(2), name);
+ SimpleMemberReference member = new SimpleMemberReference(memberId);
+ return (new SpecializedMemberReference(member, type));
+ }
+
+ // If there are arguments... life is not so simple. We can't be sure we can identify the
+ // corresponding member of the template type because any particular type that appears in
+ // the argument might have come from the template or it might have come from the specialization.
+ // We need to create a special kind of reference to handle this situation.
+ //Console.WriteLine("Specialized member with arguments '{0}'", api);
+ string[] parameterTypeCers = SeperateTypes(arguments);
+ TypeReference[] parameterTypes = new TypeReference[parameterTypeCers.Length];
+ for (int i = 0; i < parameterTypeCers.Length; i++) {
+ parameterTypes[i] = CreateTypeReference(parameterTypeCers[i]);
+ }
+ return (new SpecializedMemberWithParametersReference(prefix, type, name, parameterTypes));
+
+ } else {
+ //Console.WriteLine("No match");
+ return (null);
+ //throw new InvalidOperationException(String.Format("Invalid member '{0}'", api));
+ }
+
+ }
+
+ // Template context logic
+
+ private static SimpleTypeReference genericTypeContext = null;
+
+ private static SimpleMemberReference genericMemberContext = null;
+
+ public static void SetGenericContext (string cer) {
+ //Console.WriteLine("context = {0}", cer);
+
+ // re-set the context
+ genericTypeContext = null;
+ genericMemberContext = null;
+
+ // get the new context
+ Reference context = CreateReference(cer);
+ if (context == null) return;
+
+ // if it is a type context, set it to be the type context
+ SimpleTypeReference typeContext = context as SimpleTypeReference;
+ if (typeContext != null) {
+ genericTypeContext = typeContext;
+ return;
+ }
+
+ // if it is a member context, set it to be the member context and use it to obtain a type context, too
+ SimpleMemberReference memberContext = context as SimpleMemberReference;
+ if (memberContext != null) {
+ genericMemberContext = memberContext;
+
+ string typeId, memberName, arguments;
+ DecomposeMemberIdentifier(memberContext.Id, out typeId, out memberName, out arguments);
+ genericTypeContext = CreateSimpleTypeReference(typeId);
+ return;
+ }
+
+ }
+
+ public static SimpleTypeReference GenericContext {
+ get {
+ return (genericTypeContext);
+ }
+ }
+
+ // Code entity reference validation logic
+
+ // iterate -> specializedTypePattern -> decoratedTypePattern -> decoratedTypeListPattern
+ // to get a patterns that enforce the contents of specialization brackets
+
+ static TextReferenceUtilities () {
+
+ string namePattern = @"[_a-zA-Z0-9]+";
+
+ // namespace patterns
+
+ string namespacePattern = String.Format(@"({0}\.)*({0})?", namePattern);
+
+ string optionalNamespacePattern = String.Format(@"({0}\.)*", namePattern);
+
+ // type patterns
+
+ string simpleTypePattern = String.Format(@"{0}({1}(`\d+)?\.)*{1}(`\d+)?", optionalNamespacePattern, namePattern);
+
+ //string specializedTypePattern = String.Format(@"{0}({1}(\{{.+\}})?\.)*{1}(\{{.+\}})?", optionalNamespacePattern, namePattern);
+ string specializedTypePattern = String.Format(@"({0}(\{{.+\}})?\.)*{0}(\{{.+\}})?", namePattern);
+
+ string baseTypePattern = String.Format(@"({0})|({1})", simpleTypePattern, specializedTypePattern);
+
+ string decoratedTypePattern = String.Format(@"(({0})|(`\d+)|(``\d+))(@|\*|(\[\]))*", specializedTypePattern);
+
+ string decoratedTypeListPattern = String.Format(@"({0},)*{0}", decoratedTypePattern);
+
+ string explicitInterfacePattern = String.Format(@"({0}(\{{[^\.]+\}})?#)*", namePattern);
+
+ // members of non-specialized types
+
+ string simpleFieldPattern = String.Format(@"{0}\.{1}", simpleTypePattern, namePattern);
+
+ string simpleEventPattern = String.Format(@"{0}\.{1}{2}", simpleTypePattern, explicitInterfacePattern, namePattern);
+
+ string simplePropertyPattern = String.Format(@"{0}\.{1}{2}(\({3}\))?", simpleTypePattern, explicitInterfacePattern, namePattern, decoratedTypeListPattern);
+
+ string simpleMethodPattern = String.Format(@"{0}\.{1}{2}(``\d+)?(\({3}\))?(~{4})?", simpleTypePattern, explicitInterfacePattern, namePattern, decoratedTypeListPattern, decoratedTypePattern);
+
+ string simpleConstructorPattern = String.Format(@"{0}\.#ctor(\({1}\))?", simpleTypePattern, decoratedTypeListPattern);
+
+ string simpleOverloadPattern = String.Format(@"{0}\.{1}{2}", simpleTypePattern, explicitInterfacePattern, namePattern);
+
+ string simpleConstructorOverloadPattern = String.Format(@"{0}\.#ctor", simpleTypePattern);
+
+ // members of specialized types
+
+ string specializedFieldPattern = String.Format(@"{0}\.{1}", specializedTypePattern, namePattern);
+
+ string specializedEventPattern = String.Format(@"{0}\.{1}{2}", specializedTypePattern, explicitInterfacePattern, namePattern);
+
+ string specializedPropertyPattern = String.Format(@"{0}\.{1}{2}(\({3}\))?", specializedTypePattern, explicitInterfacePattern, namePattern, decoratedTypeListPattern);
+
+ string specializedMethodPattern = String.Format(@"{0}\.{1}{2}(``\d+)?(\({3}\))?(~{4})?", specializedTypePattern, explicitInterfacePattern, namePattern, decoratedTypeListPattern, decoratedTypePattern);
+
+ string specializedOverloadPattern = String.Format(@"{0}\.{1}{2}", specializedTypePattern, explicitInterfacePattern, namePattern);
+
+ // create regexes using this patterns
+
+ ValidNamespace = new Regex( String.Format(@"^N:{0}$", namespacePattern), RegexOptions.Compiled );
+
+ ValidSimpleType = new Regex(String.Format(@"^T:{0}$", simpleTypePattern), RegexOptions.Compiled);
+
+ ValidDecoratedType = new Regex(String.Format(@"^T:{0}$", decoratedTypePattern), RegexOptions.Compiled);
+
+ ValidSpecializedType = new Regex(String.Format(@"^T:{0}$", specializedTypePattern), RegexOptions.Compiled);
+
+ ValidSimpleMember = new Regex(String.Format(@"^((M:{0})|(M:{1})|(P:{2})|(F:{3})|(E:{4})|(Overload:{5})|(Overload:{6}))$", simpleMethodPattern, simpleConstructorPattern, simplePropertyPattern, simpleFieldPattern, simpleEventPattern, simpleOverloadPattern, simpleConstructorOverloadPattern));
+
+ ValidSpecializedMember = new Regex(String.Format(@"^((M:{0})|(P:{1})|(F:{2})|(E:{3})|(Overload:{4}))$", specializedMethodPattern, specializedPropertyPattern, specializedFieldPattern, specializedEventPattern, specializedOverloadPattern));
+
+ ValidTest = new Regex(String.Format(@"^M:{0}\.{1}$", simpleTypePattern, namePattern));
+
+ }
+
+ private static Regex ValidNamespace;
+
+ private static Regex ValidSimpleType;
+
+ private static Regex ValidDecoratedType;
+
+ private static Regex ValidSpecializedType;
+
+ private static Regex ValidSimpleMember;
+
+ private static Regex ValidSpecializedMember;
+
+ private static Regex ValidTest;
+
+ // Code entity reference string manipulation utilities
+
+ internal static string[] SeperateTypes (string typelist) {
+ List<string> types = new List<string>();
+
+ int start = 0;
+ int specializationCount = 0;
+ for (int index = 0; index < typelist.Length; index++) {
+ switch (typelist[index]) {
+ case '{':
+ case '[':
+ specializationCount++;
+ break;
+ case '}':
+ case ']':
+ specializationCount--;
+ break;
+ case ',':
+ if (specializationCount == 0) {
+ types.Add("T:" + typelist.Substring(start, index - start).Trim());
+ start = index + 1;
+ }
+ break;
+ }
+ }
+ types.Add("T:" + typelist.Substring(start).Trim());
+ return (types.ToArray());
+ }
+
+ internal static void DecomposeMemberIdentifier (string memberCer, out string typeCer, out string memberName, out string arguments) {
+
+ // drop the member prefix
+ int colonPosition = memberCer.IndexOf(':');
+ string text = memberCer.Substring(colonPosition + 1);
+
+ // get the arguments
+ arguments = String.Empty;
+ int startParenthesisPosition = text.IndexOf('(');
+ if (startParenthesisPosition > 0) {
+ int endParenthesisPosition = text.LastIndexOf(')');
+ arguments = text.Substring(startParenthesisPosition + 1, endParenthesisPosition - startParenthesisPosition - 1);
+ text = text.Substring(0, startParenthesisPosition);
+ }
+
+ // seperate the type and member name
+ int lastDotPosition;
+ int firstHashPosition = text.IndexOf('#');
+ if (firstHashPosition > 0) {
+ // if this is an EII, the boundry is at the last dot before the hash
+ lastDotPosition = text.LastIndexOf('.', firstHashPosition);
+ } else {
+ // otherwise, the boundry is at the last dot
+ lastDotPosition = text.LastIndexOf('.');
+ }
+
+ memberName = text.Substring(lastDotPosition + 1);
+ typeCer = "T:" + text.Substring(0, lastDotPosition);
+ }
+
+ private static int FindMatchingEndBracket (string text, int position) {
+
+ if (text == null) throw new ArgumentNullException("text");
+ if ((position < 0) || (position >= text.Length)) throw new ArgumentOutOfRangeException("position", String.Format("The position {0} is not within the given text string.", position));
+ if (text[position] != '{') throw new InvalidOperationException(String.Format("Position {0} of the string '{1}' does not contain and ending curly bracket.", position, text));
+
+ int count = 1;
+ for (int index = position + 1; index < text.Length; index++) {
+ if (text[index] == '{') {
+ count++;
+ } else if (text[index] == '}') {
+ count--;
+ }
+
+ if (count == 0) return (index);
+ }
+
+ throw new FormatException("No opening brace matches the closing brace.");
+
+ }
+
+ // Writing link text for unresolved simple references
+
+ internal static void WriteNamespaceReference (NamespaceReference space, DisplayOptions options, XmlWriter writer) {
+ writer.WriteString(space.Id.Substring(2));
+ }
+
+ internal static void WriteSimpleTypeReference (SimpleTypeReference type, DisplayOptions options, XmlWriter writer) {
+
+ // this logic won't correctly deal with nested types, but type cer strings simply don't include that
+ // infomation, so this is out best guess under the assumption of a non-nested type
+
+ string cer = type.Id;
+
+ // get the name
+ string name;
+ int lastDotPosition = cer.LastIndexOf('.');
+ if (lastDotPosition > 0) {
+ // usually, the name will start after the last dot
+ name = cer.Substring(lastDotPosition + 1);
+ } else {
+ // but if there is no dot, this is a type in the default namespace and the name is everything after the colon
+ name = cer.Substring(2);
+ }
+
+ // remove any generic tics from the name
+ int tickPosition = name.IndexOf('`');
+ if (tickPosition > 0) name = name.Substring(0, tickPosition);
+
+ if ((options & DisplayOptions.ShowContainer) > 0) {
+ // work out namespace
+ }
+
+ writer.WriteString(name);
+
+ if ((options & DisplayOptions.ShowTemplates) > 0) {
+ // work out templates
+ }
+
+ }
+
+ internal static void WriteSimpleMemberReference (SimpleMemberReference member, DisplayOptions options, XmlWriter writer, LinkTextResolver resolver) {
+
+ string cer = member.Id;
+
+ string typeCer, memberName, arguments;
+ DecomposeMemberIdentifier(cer, out typeCer, out memberName, out arguments);
+
+ if ((options & DisplayOptions.ShowContainer) > 0) {
+ SimpleTypeReference type = CreateSimpleTypeReference(typeCer);
+ WriteSimpleTypeReference(type, options & ~DisplayOptions.ShowContainer, writer);
+ }
+
+ // change this so that we deal with EII names correctly, too
+ writer.WriteString(memberName);
+
+ if ((options & DisplayOptions.ShowParameters) > 0) {
+ string[] parameterTypeCers;
+ if (String.IsNullOrEmpty(arguments)) {
+ Parameter[] parameters = new Parameter[0];
+ resolver.WriteMethodParameters(parameters, writer);
+ } else {
+ parameterTypeCers = SeperateTypes(arguments);
+ Parameter[] parameters = new Parameter[parameterTypeCers.Length];
+ for (int i = 0; i < parameterTypeCers.Length; i++) {
+ TypeReference parameterType = CreateTypeReference(parameterTypeCers[i]);
+ if (parameterType == null) {
+ parameterType = new NamedTemplateTypeReference("UAT");
+ }
+ parameters[i] = new Parameter(String.Empty, parameterType);
+ }
+ resolver.WriteMethodParameters(parameters, writer);
+ }
+ }
+
+ }
+
+ }
+
+ // ***** Link text writing logic *****
+
+ public class LinkTextResolver {
+
+ public LinkTextResolver (TargetCollection targets) {
+ this.targets = targets;
+ }
+
+ private TargetCollection targets;
+
+ public void WriteTarget (Target target, DisplayOptions options, XmlWriter writer) {
+ if (target == null) throw new ArgumentNullException("target");
+ if (writer == null) throw new ArgumentNullException("writer");
+
+ NamespaceTarget space = target as NamespaceTarget;
+ if (space != null) {
+ WriteNamespaceTarget(space, options, writer);
+ return;
+ }
+
+ TypeTarget type = target as TypeTarget;
+ if (type != null) {
+ WriteTypeTarget(type, options, writer);
+ return;
+ }
+
+ MemberTarget member = target as MemberTarget;
+ if (member != null) {
+ WriteMemberTarget(member, options, writer);
+ return;
+ }
+
+ throw new InvalidOperationException();
+ }
+
+ public void WriteNamespaceTarget (NamespaceTarget space, DisplayOptions options, XmlWriter writer) {
+ if (space == null) throw new ArgumentNullException("target");
+ if (writer == null) throw new ArgumentNullException("writer");
+ writer.WriteString(space.Name);
+ }
+
+ public void WriteTypeTarget (TypeTarget type, DisplayOptions options, XmlWriter writer) {
+ if (type == null) throw new ArgumentNullException("type");
+ if (writer == null) throw new ArgumentNullException("writer");
+ WriteTypeTarget(type, options, true, writer);
+ }
+
+ private void WriteTypeTarget (TypeTarget type, DisplayOptions options, bool showOuterType, XmlWriter writer) {
+
+ // write namespace, if containers are requested
+ if ((options & DisplayOptions.ShowContainer) > 0) {
+ WriteNamespace(type.Namespace, DisplayOptions.Default, writer);
+ WriteSeperator(writer);
+ }
+
+ // write outer type, if one exists
+ if (showOuterType && (type.OuterType != null)) {
+ WriteSimpleType(type.OuterType, DisplayOptions.Default, writer);
+ WriteSeperator(writer);
+ }
+
+ // write the type name
+ writer.WriteString(type.Name);
+
+ // write if template parameters, if they exist and we are requested
+ if ((options & DisplayOptions.ShowTemplates) > 0) {
+ WriteTemplateParameters(type.Templates, writer);
+ }
+ }
+
+ public void WriteMemberTarget (MemberTarget target, DisplayOptions options, XmlWriter writer) {
+ WriteMemberTarget(target, options, writer, null);
+ }
+
+
+ private void WriteMemberTarget (MemberTarget target, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+ if (target == null) throw new ArgumentNullException("target");
+ if (writer == null) throw new ArgumentNullException("writer");
+
+ if ((options & DisplayOptions.ShowContainer) > 0) {
+ TypeReference type = target.Type;
+ WriteType(type, options & ~DisplayOptions.ShowContainer, writer);
+ MethodTarget methodTarget = target as MethodTarget;
+ if (methodTarget != null) {
+ if (methodTarget.conversionOperator) {
+ writer.WriteString(" ");
+ } else {
+ WriteSeperator(writer);
+ }
+ } else {
+ WriteSeperator(writer);
+ }
+ }
+
+ // special logic for writing methods
+ MethodTarget method = target as MethodTarget;
+ if (method != null) {
+ WriteMethod(method, options, writer, dictionary);
+ return;
+ }
+
+ // special logic for writing properties
+ PropertyTarget property = target as PropertyTarget;
+ if (property != null) {
+ WriteProperty(property, options, writer);
+ return;
+ }
+
+ // special logic for writing constructors
+ ConstructorTarget constructor = target as ConstructorTarget;
+ if (constructor != null) {
+ WriteConstructor(constructor, options, writer);
+ return;
+ }
+
+ // special logic for writing events
+ EventTarget trigger = target as EventTarget;
+ if (trigger != null) {
+ WriteEvent(trigger, options, writer);
+ return;
+ }
+
+ // by default, just write name
+ writer.WriteString(target.Name);
+ }
+
+ public void WriteReference (Reference reference, DisplayOptions options, XmlWriter writer) {
+ if (reference == null) throw new ArgumentNullException("reference");
+ if (writer == null) throw new ArgumentNullException("writer");
+
+ NamespaceReference space = reference as NamespaceReference;
+ if (space != null) {
+ WriteNamespace(space, options, writer);
+ return;
+ }
+
+ TypeReference type = reference as TypeReference;
+ if (type != null) {
+ WriteType(type, options, writer);
+ return;
+ }
+
+ MemberReference member = reference as MemberReference;
+ if (member != null) {
+ WriteMember(member, options, writer);
+ return;
+ }
+
+ ExtensionMethodReference extMethod = reference as ExtensionMethodReference;
+ if (extMethod != null)
+ {
+ WriteExtensionMethod(extMethod, options, writer);
+ return;
+ }
+
+ InvalidReference invalid = reference as InvalidReference;
+ if (invalid != null) {
+ WriteInvalid(invalid, options, writer);
+ return;
+ }
+
+ throw new InvalidOperationException();
+ }
+
+ public void WriteNamespace (NamespaceReference spaceReference, DisplayOptions options, XmlWriter writer) {
+ if (spaceReference == null) throw new ArgumentNullException("spaceReference");
+ if (writer == null) throw new ArgumentNullException("writer");
+
+ NamespaceTarget spaceTarget = spaceReference.Resolve(targets) as NamespaceTarget;
+ if (spaceTarget != null) {
+ WriteNamespaceTarget(spaceTarget, options, writer);
+ } else {
+ TextReferenceUtilities.WriteNamespaceReference(spaceReference, options, writer);
+ }
+ }
+
+ public void WriteType (TypeReference type, DisplayOptions options, XmlWriter writer) {
+ WriteType(type, options, writer, null);
+ }
+
+ private void WriteType (TypeReference type, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+
+ if (type == null) throw new ArgumentNullException("type");
+ if (writer == null) throw new ArgumentNullException("writer");
+
+ //Console.WriteLine("type {0}", type.GetType().FullName);
+
+ SimpleTypeReference simple = type as SimpleTypeReference;
+ if (simple != null) {
+ WriteSimpleType(simple, options, writer);
+ return;
+ }
+
+ SpecializedTypeReference specialized = type as SpecializedTypeReference;
+ if (specialized != null) {
+ WriteSpecializedType(specialized, options, writer);
+ return;
+ }
+
+ ArrayTypeReference array = type as ArrayTypeReference;
+ if (array != null) {
+ WriteArrayType(array, options, writer, dictionary);
+ return;
+ }
+
+ ReferenceTypeReference reference = type as ReferenceTypeReference;
+ if (reference != null) {
+ WriteReferenceType(reference, options, writer, dictionary);
+ return;
+ }
+
+ PointerTypeReference pointer = type as PointerTypeReference;
+ if (pointer != null) {
+ WritePointerType(pointer, options, writer, dictionary);
+ return;
+ }
+
+ TemplateTypeReference template = type as TemplateTypeReference;
+ if (template != null) {
+ WriteTemplateType(template, options, writer, dictionary);
+ return;
+ }
+
+ throw new InvalidOperationException("Unknown type reference type");
+
+ }
+
+ public void WriteSimpleType (SimpleTypeReference simple, DisplayOptions options, XmlWriter writer) {
+ WriteSimpleType(simple, options, true, writer);
+ }
+
+ private void WriteSimpleType (SimpleTypeReference simple, DisplayOptions options, bool showOuterType, XmlWriter writer) {
+ TypeTarget type = simple.Resolve(targets) as TypeTarget;
+ if (type != null) {
+ WriteTypeTarget(type, options, showOuterType, writer);
+ } else {
+ TextReferenceUtilities.WriteSimpleTypeReference(simple, options, writer);
+ }
+ }
+
+ private static void WriteTemplateParameters (string[] templates, XmlWriter writer) {
+
+ if (templates.Length == 0) return;
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString("<");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString("(Of ");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("<");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString("(");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "fs");
+ writer.WriteString("<'");
+ writer.WriteEndElement();
+
+ writer.WriteEndElement();
+
+ for (int i = 0; i < templates.Length; i++) {
+ if (i > 0) writer.WriteString(", ");
+ writer.WriteString(templates[i]);
+ }
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString(">");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString(")");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString(">");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString(")");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "fs");
+ writer.WriteString(">");
+ writer.WriteEndElement();
+
+ writer.WriteEndElement();
+ }
+
+ private void WriteSpecializedType (SpecializedTypeReference special, DisplayOptions options, XmlWriter writer) {
+
+ Specialization[] specializations = special.Specializations;
+ for (int i = 0; i < specializations.Length; i++) {
+ if (i == 0) {
+ WriteSpecialization(specializations[0], options, writer);
+ } else {
+ WriteSeperator(writer);
+ WriteSpecialization(specializations[i], options & ~DisplayOptions.ShowContainer, writer);
+ }
+
+ }
+
+ }
+
+ private void WriteSpecialization (Specialization specialization, DisplayOptions options, XmlWriter writer) {
+ // write the type itself (without outer types, because those will be written be other calls to this routine)
+ WriteSimpleType(specialization.TemplateType, (options & ~DisplayOptions.ShowTemplates), false, writer);
+
+ // then write the template arguments
+ WriteTemplateArguments(specialization.Arguments, writer);
+ }
+
+ private void WriteTemplateArguments (TypeReference[] specialization, XmlWriter writer) {
+
+ if (specialization.Length == 0) return;
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString("<");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString("(Of ");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("<");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "fs");
+ writer.WriteString("<'");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString("(");
+ writer.WriteEndElement();
+
+ writer.WriteEndElement();
+
+ for (int i = 0; i < specialization.Length; i++) {
+ if (i > 0) writer.WriteString(", ");
+ WriteType(specialization[i], DisplayOptions.Default, writer);
+ }
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString(">");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString(")");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString(">");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "fs");
+ writer.WriteString(">");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString(")");
+ writer.WriteEndElement();
+ writer.WriteEndElement();
+ }
+
+ private void WriteArrayType (ArrayTypeReference reference, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ // C++ array notation (left)
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("array<");
+ writer.WriteEndElement();
+ writer.WriteEndElement(); // end of <span class="languageSpecificText"> element
+
+ // the underlying type
+ WriteType(reference.ElementType, options, writer, dictionary);
+
+ // C++ array notation (right)
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ if (reference.Rank > 1) {
+ writer.WriteString("," + reference.Rank.ToString());
+ }
+ writer.WriteString(">");
+ writer.WriteEndElement();
+
+ // C# array notation
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString("[");
+ for (int i = 1; i < reference.Rank; i++) { writer.WriteString(","); }
+ writer.WriteString("]");
+ writer.WriteEndElement();
+
+ // VB array notation
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString("(");
+ for (int i = 1; i < reference.Rank; i++) { writer.WriteString(","); }
+ writer.WriteString(")");
+ writer.WriteEndElement();
+
+ // neutral array notation
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString("[");
+ for (int i = 1; i < reference.Rank; i++) { writer.WriteString(","); }
+ writer.WriteString("]");
+ writer.WriteEndElement();
+
+ // F# array notation
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "fs");
+ writer.WriteString("[");
+ for (int i = 1; i < reference.Rank; i++) { writer.WriteString(","); }
+ writer.WriteString("]");
+ writer.WriteEndElement();
+
+
+ writer.WriteEndElement(); // end of <span class="languageSpecificText"> element
+ }
+
+ private static void WriteSeperator (XmlWriter writer) {
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ // C# seperator
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString(".");
+ writer.WriteEndElement();
+
+ // VB seperator
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString(".");
+ writer.WriteEndElement();
+
+ // C++ seperator
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("::");
+ writer.WriteEndElement();
+
+ // neutral seperator
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString(".");
+ writer.WriteEndElement();
+
+ // F# seperator
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "fs");
+ writer.WriteString(".");
+ writer.WriteEndElement();
+
+ writer.WriteEndElement();
+ }
+
+ private void WritePointerType (PointerTypeReference pointer, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+ WriteType(pointer.PointedToType, options, writer, dictionary);
+ writer.WriteString("*");
+ }
+
+ private void WriteReferenceType (ReferenceTypeReference reference, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+ WriteType(reference.ReferedToType, options, writer, dictionary);
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ // add % in C++
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("%");
+ writer.WriteEndElement();
+ writer.WriteEndElement();
+ }
+
+ private void WriteTemplateType (TemplateTypeReference template, DisplayOptions options, XmlWriter writer) {
+ WriteTemplateType(template, options, writer, null);
+ }
+
+ private void WriteTemplateType (TemplateTypeReference template, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+
+ /*
+ Console.WriteLine("template type {0}", template.GetType().FullName);
+ if (dictionary != null) {
+ foreach (IndexedTemplateTypeReference it in dictionary.Keys) {
+ Console.WriteLine("index = {0}, api = {1} ({3}) -> {2}", it.Index, it.TemplateId, dictionary[it].GetType().FullName, it.GetHashCode());
+ }
+ }
+ */
+
+ // if we have the name, just write it
+ NamedTemplateTypeReference namedTemplate = template as NamedTemplateTypeReference;
+ if (namedTemplate != null) {
+ writer.WriteString(namedTemplate.Name);
+ return;
+ }
+
+ IndexedTemplateTypeReference indexedTemplate = template as IndexedTemplateTypeReference;
+ if (indexedTemplate != null) {
+ //Console.WriteLine("index = {0}, api = {1} ({2})", indexedTemplate.Index, indexedTemplate.TemplateId, indexedTemplate.GetHashCode());
+ //if ((dictionary != null) && (!dictionary.ContainsKey(indexedTemplate))) Console.WriteLine("not in dictionary");
+ if ((dictionary != null) && (dictionary.ContainsKey(indexedTemplate))) {
+ //Console.WriteLine("Substituted {0}", dictionary[indexedTemplate].GetType().FullName);
+ WriteType(dictionary[indexedTemplate], options, writer);
+ } else {
+ //Console.WriteLine("Getting name for id='{0}' and index={1}", indexedTemplate.TemplateId, indexedTemplate.Index);
+ writer.WriteString(GetTemplateName(indexedTemplate.TemplateId, indexedTemplate.Index));
+ }
+ return;
+ }
+
+ TypeTemplateTypeReference typeTemplate = template as TypeTemplateTypeReference;
+ if (typeTemplate != null) {
+
+ TypeReference value = null;
+ if (dictionary != null) {
+ IndexedTemplateTypeReference key = new IndexedTemplateTypeReference(typeTemplate.TemplateType.Id, typeTemplate.Position);
+ if (dictionary.ContainsKey(key)) value = dictionary[key];
+ }
+
+ if (value == null) {
+ writer.WriteString(GetTypeTemplateName(typeTemplate.TemplateType, typeTemplate.Position));
+ } else {
+ WriteType(value, options, writer);
+ }
+
+ return;
+
+ }
+
+ throw new InvalidOperationException();
+ }
+
+ private string GetTemplateName (string templateId, int position) {
+ Target target = targets[templateId];
+
+ if (target == null) {
+ return ("UTT");
+ } else {
+
+ TypeTarget type = target as TypeTarget;
+ if (type != null) {
+ string[] templates = type.Templates;
+ if (templates.Length > position) {
+ return(templates[position]);
+ } else {
+ return ("UTT");
+ }
+ }
+
+ MethodTarget method = target as MethodTarget;
+ if (method != null) {
+ string[] templates = method.Templates;
+ if (templates.Length > position) {
+ return (templates[position]);
+ } else {
+ return ("UTT");
+ }
+ }
+
+ return ("UTT");
+ }
+ }
+
+ private string GetTypeTemplateName (SimpleTypeReference type, int position) {
+ TypeTarget target = type.Resolve(targets) as TypeTarget;
+ if (target != null) {
+ string[] templates = target.Templates;
+ if (templates.Length > position) {
+ return (templates[position]);
+ } else if (target.OuterType != null) {
+ return (GetTypeTemplateName(target.OuterType, position));
+ } else {
+ return ("UTT");
+ }
+ } else {
+ throw new InvalidOperationException(String.Format("Unknown type reference '{0}'", type.Id));
+ }
+ }
+
+ public void WriteExtensionMethod(ExtensionMethodReference extMethod, DisplayOptions options, XmlWriter writer)
+ {
+ if (extMethod == null) throw new ArgumentNullException("extMethod");
+ if (writer == null) throw new ArgumentNullException("writer");
+
+ // write the unqualified method name
+ writer.WriteString(extMethod.Name);
+
+ // if this is a generic method, write any template params or args
+ if (extMethod.TemplateArgs != null && extMethod.TemplateArgs.Length > 0)
+ {
+ WriteTemplateArguments(extMethod.TemplateArgs, writer);
+ }
+
+ // write parameters
+ if ((options & DisplayOptions.ShowParameters) > 0)
+ {
+ Parameter[] parameters = extMethod.Parameters;
+ WriteMethodParameters(extMethod.Parameters, writer);
+ }
+ }
+
+ public void WriteMember (MemberReference member, DisplayOptions options, XmlWriter writer) {
+
+ if (member == null) throw new ArgumentNullException("member");
+ if (writer == null) throw new ArgumentNullException("writer");
+
+ SimpleMemberReference simple = member as SimpleMemberReference;
+ if (simple != null) {
+ WriteSimpleMember(simple, options, writer);
+ return;
+ }
+
+ SpecializedMemberReference special = member as SpecializedMemberReference;
+ if (special != null) {
+ WriteSpecializedMember(special, options, writer);
+ return;
+ }
+
+ SpecializedMemberWithParametersReference ugly = member as SpecializedMemberWithParametersReference;
+ if (ugly != null) {
+ WriteSpecializedMemberWithParameters(ugly, options, writer);
+ return;
+ }
+
+ throw new InvalidOperationException();
+
+ }
+
+ private void WriteSpecializedMember (SpecializedMemberReference member, DisplayOptions options, XmlWriter writer) {
+
+ if ((options & DisplayOptions.ShowContainer) > 0) {
+ WriteType(member.SpecializedType, options & ~DisplayOptions.ShowContainer, writer);
+ WriteSeperator(writer);
+ }
+
+ Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary = member.SpecializedType.GetSpecializationDictionary();
+ WriteSimpleMember(member.TemplateMember, options & ~DisplayOptions.ShowContainer, writer, dictionary);
+
+ }
+
+ private void WriteSimpleMember (SimpleMemberReference member, DisplayOptions options, XmlWriter writer) {
+ WriteSimpleMember(member, options, writer, null);
+ }
+
+ private void WriteSimpleMember (SimpleMemberReference member, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+ MemberTarget target = member.Resolve(targets) as MemberTarget;
+ if (target != null) {
+ WriteMemberTarget(target, options, writer, dictionary);
+ } else {
+ TextReferenceUtilities.WriteSimpleMemberReference(member, options, writer, this);
+ //throw new InvalidOperationException(String.Format("Unknown member target '{0}'", member.Id));
+ }
+
+ }
+
+ private void WriteProcedureName (ProcedureTarget target, DisplayOptions options, XmlWriter writer) {
+ MemberReference implements = target.ExplicitlyImplements;
+ if (implements == null) {
+ if (target.conversionOperator) {
+ WriteConversionOperator(target, writer);
+ } else {
+ writer.WriteString(target.Name);
+ }
+ } else {
+ WriteMember(implements, DisplayOptions.ShowContainer, writer);
+ }
+ }
+
+ private void WriteMethod (MethodTarget target, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+
+ WriteProcedureName(target, options, writer);
+
+ if ((options & DisplayOptions.ShowTemplates) > 0) {
+ // if this is a generic method, write any template params or args
+ if (target.TemplateArgs != null && target.TemplateArgs.Length > 0)
+ {
+ WriteTemplateArguments(target.TemplateArgs, writer);
+ }
+ }
+
+ if ((options & DisplayOptions.ShowParameters) > 0) {
+ Parameter[] parameters = target.Parameters;
+
+ if (target.ConversionOperator) {
+ TypeReference returns = target.returnType;
+ WriteConversionOperatorParameters(parameters, returns, writer, dictionary);
+ } else {
+ WriteMethodParameters(parameters, writer, dictionary);
+ }
+ }
+
+ }
+
+ private void WriteConversionOperator(ProcedureTarget target, XmlWriter writer)
+ {
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString(target.Name);
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ if (target.name == "Explicit") {
+ writer.WriteString("Narrowing");
+ } else if (target.name == "Implicit") {
+ writer.WriteString("Widening");
+ }
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString(target.name);
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString(target.name);
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "fs");
+ writer.WriteString(target.name);
+ writer.WriteEndElement();
+
+ writer.WriteEndElement();
+ }
+
+ internal void WriteMethodParameters (Parameter[] parameters, XmlWriter writer) {
+ WriteMethodParameters(parameters, writer, null);
+ }
+
+
+ private void WriteMethodParameters (Parameter[] parameters, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+ if (parameters.Length > 0) {
+ writer.WriteString("(");
+
+ // show parameters
+ // we need to deal with type template substitutions!
+ for (int i = 0; i < parameters.Length; i++) {
+ if (i > 0) writer.WriteString(", ");
+ WriteType(parameters[i].Type, DisplayOptions.Default, writer, dictionary);
+ }
+
+ writer.WriteString(")");
+ } else {
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ // when there are no parameters, VB shows no parenthesis
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString("()");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("()");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString("()");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "fs");
+ writer.WriteString("()");
+ writer.WriteEndElement();
+
+ writer.WriteEndElement();
+
+ }
+ }
+
+ private void WriteConversionOperatorParameters(Parameter[] parameters, TypeReference returns, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary)
+ {
+ if (parameters.Length > 0 || returns != null) writer.WriteString("(");
+
+ if (parameters.Length > 0) WriteType(parameters[0].Type, DisplayOptions.Default, writer, dictionary);
+
+ if (parameters.Length > 0 && returns != null) writer.WriteString(" to ");
+
+ if (returns != null) WriteType(returns, DisplayOptions.Default, writer, dictionary);
+
+ if (parameters.Length > 0 || returns != null) writer.WriteString(")");
+
+ if (parameters.Length == 0 && returns == null)
+ {
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ // when there are no parameters, VB shows no parenthesis
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString("()");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("()");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString("()");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "fs");
+ writer.WriteString("()");
+ writer.WriteEndElement();
+
+ writer.WriteEndElement();
+ }
+ }
+
+ private void WriteProperty (PropertyTarget target, DisplayOptions options, XmlWriter writer) {
+
+ WriteProcedureName(target, options, writer);
+
+ if ((options & DisplayOptions.ShowParameters) > 0) {
+
+ Parameter[] parameters = target.Parameters;
+
+ // VB only shows parenthesis when there are parameters
+ if (parameters.Length > 0) {
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString("[");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString("(");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("[");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString("(");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "fs");
+ writer.WriteString(" ");
+ writer.WriteEndElement();
+
+ writer.WriteEndElement();
+
+ // show parameters
+ // we need to deal with type template substitutions!
+ for (int i = 0; i < parameters.Length; i++) {
+ if (i > 0) writer.WriteString(", ");
+ WriteType(parameters[i].Type, DisplayOptions.Default, writer);
+ }
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString("]");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString(")");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("]");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString(")");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "fs");
+ writer.WriteString(" ");
+ writer.WriteEndElement();
+
+ writer.WriteEndElement();
+ }
+
+ }
+
+ }
+
+ private void WriteEvent (EventTarget trigger, DisplayOptions options, XmlWriter writer) {
+ WriteProcedureName(trigger, options, writer);
+ }
+
+ private void WriteConstructor (ConstructorTarget constructor, DisplayOptions options, XmlWriter writer) {
+
+
+ WriteType(constructor.Type, options & ~DisplayOptions.ShowContainer, writer);
+
+ if ((options & DisplayOptions.ShowParameters) > 0) {
+ Parameter[] parameters = constructor.Parameters;
+ WriteMethodParameters(parameters, writer);
+ }
+
+ }
+
+ private void WriteSpecializedMemberWithParameters (SpecializedMemberWithParametersReference ugly, DisplayOptions options, XmlWriter writer) {
+
+ if ((options & DisplayOptions.ShowContainer) > 0) {
+ WriteSpecializedType(ugly.SpecializedType, options & ~DisplayOptions.ShowContainer, writer);
+ WriteSeperator(writer);
+ }
+
+ writer.WriteString(ugly.MemberName);
+
+ if ((options & DisplayOptions.ShowParameters) > 0) {
+
+ writer.WriteString("(");
+
+ TypeReference[] parameterTypes = ugly.ParameterTypes;
+ for (int i = 0; i < parameterTypes.Length; i++) {
+ //Console.WriteLine("i = {0}, type = {1}", i, parameterTypes[i].GetType().FullName);
+ if (i > 0) writer.WriteString(", ");
+ WriteType(parameterTypes[i], DisplayOptions.Default, writer);
+ }
+
+ writer.WriteString(")");
+ }
+
+ }
+
+ private static void WriteInvalid (InvalidReference invalid, DisplayOptions options, XmlWriter writer) {
+ writer.WriteString("[" + invalid.Id + "]");
+ }
+
+ }
+
+ [Flags]
+ public enum DisplayOptions {
+
+ ShowContainer = 1,
+ ShowTemplates = 2,
+ ShowParameters = 4,
+
+ Default = 6
+
+ }
+
+ public enum LinkType2 {
+ None,
+ Self,
+ Local,
+ Index,
+ LocalOrIndex,
+ Msdn
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Targets.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Targets.cs
new file mode 100644
index 0000000..656da13
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Targets.cs
@@ -0,0 +1,156 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using System.Xml;
+using System.Xml.XPath;
+
+namespace BuildComponents {
+
+ public partial class Target {
+
+ internal string id;
+
+ public string Id {
+ get {
+ return (id);
+ }
+ }
+ }
+
+ // Namespace
+
+ public partial class NamespaceTarget : Target {
+
+ internal string name;
+
+ public string Name {
+ get {
+ return (name);
+ }
+ }
+
+ }
+
+ // Type
+
+ public partial class TypeTarget : Target {
+
+ // apidata
+
+ protected string subgroup;
+
+ // containers
+
+ protected NamespaceReference containingNamespace;
+
+ protected SimpleTypeReference containingType;
+
+ protected string containingAssembly;
+
+ // other
+
+ public NamespaceReference Namespace {
+ get {
+ return (containingNamespace);
+ }
+ }
+
+ public SimpleTypeReference OuterType {
+ get {
+ return (containingType);
+ }
+ }
+
+ }
+
+ // Construction of targets from Xml
+
+ public partial class Target {
+
+ public static Target Create (XmlReader api) {
+
+ string id = api.GetAttribute("id");
+
+ Target target = null;
+ api.ReadToFollowing("apidata");
+ string group = api.GetAttribute("group");
+ switch (group) {
+ case "namespace":
+ target = NamespaceTarget.Create(api);
+ break;
+ }
+
+ target.id = id;
+
+ return (target);
+ }
+
+ protected static XPathExpression apiNameExpression = XPathExpression.Compile("string(apidata/@name)");
+
+
+ }
+
+ public partial class NamespaceTarget {
+
+ public static new NamespaceTarget Create (XmlReader apidata) {
+ NamespaceTarget target = new NamespaceTarget();
+ string name = apidata.GetAttribute("name");
+
+ // This is not locale-independent.
+ if (String.IsNullOrEmpty(target.name)) name = "(Default Namespace)";
+
+ target.name = name;
+
+ return (target);
+ }
+
+ public static NamespaceTarget Create (XPathNavigator api) {
+
+ NamespaceTarget target = new NamespaceTarget();
+ target.name = (string)api.Evaluate(apiNameExpression);
+
+ // This is not locale-independent.
+ if (String.IsNullOrEmpty(target.name)) target.name = "(Default Namespace)";
+
+ return (target);
+ }
+
+ }
+
+
+ public partial class TypeTarget {
+
+ public static new TypeTarget Create (XmlReader api) {
+
+ api.ReadToFollowing("apidata");
+ //string subgroup = api.GetAttribute("subgroup");
+
+ api.ReadToFollowing("typedata");
+ //string visibilityValue = api.GetAttribute("visibility");
+ //string abstractValue = api.GetAttribute("abstract");
+ //string sealedValue = api.GetAttribute("sealed");
+ //string serializableValue = api.GetAttribute("serealizable");
+
+ api.ReadToFollowing("library");
+ string containingAssemblyValue = api.GetAttribute("assembly");
+
+ api.ReadToFollowing("namespace");
+ NamespaceReference containingNamespace = NamespaceReference.Create(api);
+
+ TypeTarget target = new TypeTarget();
+ target.containingAssembly = containingAssemblyValue;
+ target.containingNamespace = containingNamespace;
+
+ return (target);
+
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TaskGrabberComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TaskGrabberComponent.cs
new file mode 100644
index 0000000..d03fa15
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TaskGrabberComponent.cs
@@ -0,0 +1,371 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Xml;
+using System.Xml.XPath;
+using System.IO;
+
+// still have problems with spaces
+
+namespace Microsoft.Ddue.Tools {
+
+ public class TaskGrabberComponent : BuildComponent {
+
+ private XmlNamespaceManager nsManager = new XmlNamespaceManager(new NameTable());
+
+ private XPathExpression valueQuery = null;
+ private XPathExpression keyQuery = null;
+
+ private string xpathFromConfig = string.Empty;
+
+ private Dictionary<string, List<string>> bKeywordMap = new Dictionary<string, List<string>>();
+
+ private Dictionary<string, string> index = new Dictionary<string, string>();
+
+ // what to copy
+ private List<CopySet> copySets = new List<CopySet>();
+
+ public TaskGrabberComponent(BuildAssembler assembler, XPathNavigator configuration)
+ : base(assembler, configuration)
+ {
+ XPathNavigator keywordsNode = configuration.SelectSingleNode("keywords");
+ if (keywordsNode == null)
+ return;
+
+ string filespec = keywordsNode.GetAttribute("files", String.Empty);
+ filespec = Environment.ExpandEnvironmentVariables(filespec);
+ string keywordXPath = keywordsNode.GetAttribute("keyword", String.Empty);
+ string topicXPath = keywordsNode.GetAttribute("topic", String.Empty);
+ if (String.IsNullOrEmpty(keywordXPath) || String.IsNullOrEmpty(topicXPath) || String.IsNullOrEmpty(filespec))
+ return;
+
+ xpathFromConfig = keywordXPath;
+
+ string[] keywordFiles = null;
+ if (File.Exists(filespec))
+ {
+ // we're loading a single file
+ AddBKeywords(filespec, topicXPath, keywordXPath);
+ }
+ else
+ {
+ // must be loading a set of files
+ if (Directory.Exists(filespec))
+ {
+ // if they specified a directory, transform all the files in the directory
+ keywordFiles = Directory.GetFiles(filespec);
+ }
+ else
+ {
+ // it's not a file or a directory, maybe it's a path with wildcards
+ string directoryPath = Path.GetDirectoryName(filespec);
+ string filePath = Path.GetFileName(filespec);
+ keywordFiles = Directory.GetFiles(directoryPath, filePath);
+ }
+ foreach (string file in keywordFiles)
+ {
+ // load targets from each file
+ AddBKeywords(file, topicXPath, keywordXPath);
+ }
+ }
+
+ // set up the context
+ // put in a default entry for ddue
+ nsManager.AddNamespace("ddue", "http://ddue.schemas.microsoft.com/authoring/2003/6");
+ // look for context nodes, which could override the default
+ XPathNodeIterator contextNodes = configuration.Select("context");
+ foreach (XPathNavigator contextNode in contextNodes)
+ {
+ string prefix = contextNode.GetAttribute("prefix", String.Empty);
+ string uri = contextNode.GetAttribute("name", String.Empty);
+ nsManager.AddNamespace(prefix, uri);
+ }
+
+
+ // set up the index of source files
+ XPathNodeIterator sourceNodes = configuration.Select("source");
+ foreach (XPathNavigator sourceNode in sourceNodes)
+ {
+ string valueXPath = sourceNode.GetAttribute("value", String.Empty);
+ string keyXPath = sourceNode.GetAttribute("key", String.Empty);
+ if (String.IsNullOrEmpty(valueXPath) || String.IsNullOrEmpty(keyXPath))
+ {
+ WriteMessage(MessageLevel.Error, "@key and @value must be set in the 'source' node.");
+ return;
+ }
+
+ keyQuery = XPathExpression.Compile(keyXPath);
+ valueQuery = XPathExpression.Compile(valueXPath);
+
+ // search the data directories for entries
+ XPathNodeIterator dataNodes = sourceNode.Select("data");
+ foreach (XPathNavigator dataNode in dataNodes)
+ {
+ string dataFiles = dataNode.GetAttribute("files", String.Empty);
+ dataFiles = Environment.ExpandEnvironmentVariables(dataFiles);
+ if ((dataFiles == null) || (dataFiles.Length == 0)) throw new ConfigurationErrorsException("When instantiating a CopyFromDirectory component, you must specify a directory path using the files attribute.");
+ WriteMessage(MessageLevel.Info, String.Format("Searching for files that match '{0}'.", dataFiles));
+ int fileCount = ParseDocuments(dataFiles);
+ WriteMessage(MessageLevel.Info, String.Format("Found {0} files.", fileCount));
+ }
+ WriteMessage(MessageLevel.Info, String.Format("Indexed {0} elements.", index.Count));
+
+ }
+
+ // get the copy commands
+ XPathNodeIterator copyNodes = configuration.Select("copy");
+ foreach (XPathNavigator copyNode in copyNodes)
+ {
+ string sourceXPath = copyNode.GetAttribute("source", String.Empty);
+ string targetXPath = copyNode.GetAttribute("target", String.Empty);
+ if (String.IsNullOrEmpty(sourceXPath) || String.IsNullOrEmpty(targetXPath))
+ {
+ WriteMessage(MessageLevel.Error, "@source and @target must be set in the 'copy' node.");
+ return;
+ }
+
+ copySets.Add(new CopySet(sourceXPath, targetXPath, nsManager));
+ }
+
+ }
+
+ private string currentKey = string.Empty;
+
+ public override void Apply (XmlDocument document, string key) {
+ currentKey = key;
+
+ XPathNavigator targetDoc = document.CreateNavigator();
+ foreach (CopySet copySet in copySets)
+ {
+ XPathExpression targetExpression = copySet.GetTargetExpression(targetDoc, key);
+
+ // get the target nodes in the document
+ XPathNavigator targetNode = targetDoc.SelectSingleNode(targetExpression);
+ while (targetNode != null)
+ {
+ string targetId = targetNode.Value;
+ int pound = (string.IsNullOrEmpty(targetId)) ? -1 : targetId.IndexOf("#");
+ string bkeyword = (pound == -1) ? "" : targetId.Substring(pound + 1);
+ if (bkeyword == "")
+ {
+ WriteMessage(MessageLevel.Warn, string.Format("Invalid id '{0}' in topic '{1}'.", targetId, currentKey));
+ // delete this target and get the next target node
+ targetNode.DeleteSelf();
+ targetNode = targetDoc.SelectSingleNode(targetExpression);
+ continue;
+ }
+
+ List<string> idList;
+ if (!bKeywordMap.TryGetValue(bkeyword, out idList))
+ {
+ WriteMessage(MessageLevel.Warn, string.Format("B-keyword not found '{0}' in topic '{1}'.", targetId, currentKey));
+ // delete this target and get the next target node
+ targetNode.DeleteSelf();
+ targetNode = targetDoc.SelectSingleNode(targetExpression);
+ continue;
+ }
+ if (idList.Count > 1)
+ Console.Write("");
+
+ // create a 'tasks' node to replace the target
+ XPathNavigator tasksNode = document.CreateElement("tasks").CreateNavigator();
+ tasksNode.CreateAttribute(string.Empty, "bkeyword", string.Empty, bkeyword);
+ foreach (string topicId in idList)
+ {
+ //create a task node for this source topic
+ XPathNavigator taskNode = document.CreateElement("task").CreateNavigator();
+ taskNode.CreateAttribute(string.Empty, "topicId", string.Empty, topicId);
+
+ // get the source document for the topic id
+ string filepath;
+ if (!index.TryGetValue(topicId, out filepath))
+ {
+ WriteMessage(MessageLevel.Warn, string.Format("No file found for topicId '{0}' for B-keyword '{1}'. Source topic: '{2}'.", topicId, bkeyword, currentKey));
+ continue;
+ }
+
+ XPathNavigator sourceDoc = new XPathDocument(filepath).CreateNavigator();
+ XPathNavigator sourceNode = sourceDoc.SelectSingleNode(valueQuery);
+
+ if (sourceNode == null) continue;
+ XPathNodeIterator sources = sourceNode.Select(copySet.SourceExpression);
+
+ // append the source nodes to the target node
+ if (sources.Count > 0)
+ {
+ foreach (XPathNavigator source in sources)
+ taskNode.AppendChild(source);
+ }
+ tasksNode.AppendChild(taskNode);
+ }
+ targetNode.ReplaceSelf(tasksNode);
+ // get the next target node
+ targetNode = targetDoc.SelectSingleNode(targetExpression);
+ }
+ }
+ }
+
+ public int ParseDocuments(string wildcardPath)
+ {
+ string directoryPart = Path.GetDirectoryName(wildcardPath);
+ if (String.IsNullOrEmpty(directoryPart)) directoryPart = Environment.CurrentDirectory;
+ directoryPart = Path.GetFullPath(directoryPart);
+ string filePart = Path.GetFileName(wildcardPath);
+ string[] files = Directory.GetFiles(directoryPart, filePart);
+ foreach (string file in files)
+ ParseDocument(file);
+ return (files.Length);
+ }
+
+ private void ParseDocument(string file)
+ {
+ try
+ {
+ XPathDocument document = new XPathDocument(file);
+
+ // set context for the xpath expression
+ valueQuery.SetContext(nsManager);
+ keyQuery.SetContext(nsManager);
+
+ XPathNodeIterator valueNodes = document.CreateNavigator().Select(valueQuery);
+ foreach (XPathNavigator valueNode in valueNodes)
+ {
+ XPathNavigator keyNode = valueNode.SelectSingleNode(keyQuery);
+ if (keyNode == null) continue;
+ string key = keyNode.Value;
+
+ // log multiple occurences of a single id
+ if (index.ContainsKey(key))
+ {
+ WriteMessage(MessageLevel.Warn, String.Format("Entries for the key '{0}' occur in both '{1}' and '{2}'. The first entry will be used.", key, index[key], file));
+ }
+ else
+ {
+ index[key] = file;
+ }
+
+ }
+ }
+ catch (Exception e)
+ {
+ WriteMessage(MessageLevel.Error, e.Message);
+ }
+ }
+
+ private XPathDocument GetDocument(string identifier)
+ {
+ string file = index[identifier];
+ XPathDocument document = new XPathDocument(file);
+ return (document);
+ }
+
+ private void AddBKeywords(string file, string topicXPath, string keywordXPath)
+ {
+ XPathDocument document = new XPathDocument(file);
+ XPathNodeIterator targetNodes = document.CreateNavigator().Select(topicXPath);
+ foreach (XPathNavigator targetNode in targetNodes)
+ {
+ string topicId = targetNode.GetAttribute("id", string.Empty);
+ if (string.IsNullOrEmpty(topicId))
+ continue;
+ foreach (XPathNavigator keywordNode in targetNode.Select(keywordXPath))
+ {
+ string keyword = keywordNode.Value;
+ if (string.IsNullOrEmpty(keyword))
+ continue;
+ AddValueToListDictionary(bKeywordMap, keyword, topicId);
+ }
+ }
+ }
+
+ public static void AddValueToListDictionary<K, V>(Dictionary<K, List<V>> dict, K key, V value)
+ {
+ List<V> list;
+ try
+ {
+ if (!dict.TryGetValue(key, out list))
+ {
+ list = new List<V>();
+ dict.Add(key, list);
+ }
+ list.Add(value);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Exception adding to dictionary {0}", key);
+ Console.WriteLine(e);
+ throw;
+ }
+ }
+
+ }
+
+ internal class CopySet
+ {
+
+ public CopySet(string sourceXPath, string targetXPath, XmlNamespaceManager nsMgr)
+ : this(null, sourceXPath, targetXPath, nsMgr)
+ {
+ }
+
+ public CopySet(IndexedFileCache cache, string sourceXPath, string targXPath, XmlNamespaceManager nsMgr)
+ {
+ this.fileCache = cache;
+ this.namespaceMgr = nsMgr;
+ source = XPathExpression.Compile(sourceXPath);
+ source.SetContext(nsMgr);
+ if (targXPath.Contains("{0}"))
+ {
+ targetXPath = targXPath;
+ }
+ else
+ {
+ target = XPathExpression.Compile(targXPath);
+ target.SetContext(nsMgr);
+ }
+ }
+
+ private IndexedFileCache fileCache;
+ public IndexedFileCache FileCache
+ {
+ get
+ {
+ return (fileCache);
+ }
+ }
+
+ private XPathExpression source;
+ public XPathExpression SourceExpression
+ {
+ get
+ {
+ return (source);
+ }
+ }
+
+ private XmlNamespaceManager namespaceMgr;
+
+ private string targetXPath = string.Empty;
+ private XPathExpression target = null;
+ public XPathExpression GetTargetExpression(XPathNavigator targetDoc, string key)
+ {
+ if (target == null)
+ {
+ XPathExpression keyedTargetExpression = targetDoc.Compile(string.Format(targetXPath, key));
+ keyedTargetExpression.SetContext(namespaceMgr);
+ return keyedTargetExpression;
+ }
+
+ return target;
+ }
+
+
+ }
+
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TransformComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TransformComponent.cs
new file mode 100644
index 0000000..712ceb1
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TransformComponent.cs
@@ -0,0 +1,153 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class TransformComponent : BuildComponent {
+
+ public TransformComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ // load the transforms
+ XPathNodeIterator transform_nodes = configuration.Select("transform");
+ foreach (XPathNavigator transform_node in transform_nodes) {
+
+ // load the transform
+ string file = transform_node.GetAttribute("file", String.Empty);
+ if (String.IsNullOrEmpty(file)) WriteMessage(MessageLevel.Error, "Each transform element must specify a file attribute.");
+ file = Environment.ExpandEnvironmentVariables(file);
+
+ Transform transform = null;
+ try {
+ transform = new Transform(file);
+ } catch (IOException e) {
+ WriteMessage(MessageLevel.Error, String.Format("The transform file '{0}' could not be loaded. The error message is: {1}", file, BuildComponentUtilities.GetExceptionMessage(e)));
+ } catch (XmlException e) {
+ WriteMessage(MessageLevel.Error, String.Format("The transform file '{0}' is not a valid XML file. The error message is: {1}", file, BuildComponentUtilities.GetExceptionMessage(e)));
+ } catch (XsltException e) {
+ WriteMessage(MessageLevel.Error, String.Format("The XSL transform '{0}' contains an error. The error message is: {1}", file, BuildComponentUtilities.GetExceptionMessage(e)));
+ }
+
+
+ transforms.Add(transform);
+
+
+ // load any arguments
+ XPathNodeIterator argument_nodes = transform_node.Select("argument");
+ foreach (XPathNavigator argument_node in argument_nodes) {
+ string key = argument_node.GetAttribute("key", String.Empty);
+ if ((key == null) || (key.Length == 0)) WriteMessage(MessageLevel.Error, "When creating a transform argument, you must specify a key using the key attribute");
+
+ // set "expand-value" attribute to true to expand environment variables embedded in "value".
+ string expand_attr = argument_node.GetAttribute("expand-value", String.Empty);
+ bool expand_value = String.IsNullOrEmpty(expand_attr) ? false : Convert.ToBoolean(expand_attr);
+
+ string value = argument_node.GetAttribute("value", String.Empty);
+ if ((value != null) && (value.Length > 0)) {
+ transform.Arguments.AddParam(key, String.Empty, expand_value ? Environment.ExpandEnvironmentVariables(value) : value);
+ }
+ else {
+ transform.Arguments.AddParam(key, String.Empty, argument_node.Clone());
+ }
+ }
+
+ }
+
+ }
+
+ // the stored transforms
+
+ private List<Transform> transforms = new List<Transform>();
+
+ // the action of the component
+
+ public override void Apply (XmlDocument document, string key) {
+
+ // iterate over transforms
+ foreach (Transform transform in transforms) {
+
+ // add the key as a parameter to the arguments
+ transform.Arguments.RemoveParam("key", String.Empty);
+ transform.Arguments.AddParam("key", String.Empty, key);
+
+ // create a buffer into which output can be written
+ using (MemoryStream buffer = new MemoryStream()) {
+
+
+ // do the transform, routing output to the buffer
+ XmlWriterSettings settings = transform.Xslt.OutputSettings;
+ XmlWriter writer = XmlWriter.Create(buffer, settings);
+ try {
+ transform.Xslt.Transform(document, transform.Arguments, writer);
+ } catch (XsltException e) {
+ WriteMessage(MessageLevel.Error, String.Format("A error ocurred while executing the transform '{0}', on line {1}, at position {2}. The error message was: {3}", e.SourceUri, e.LineNumber, e.LinePosition, (e.InnerException == null) ? e.Message : e.InnerException.Message));
+ } catch (XmlException e) {
+ WriteMessage(MessageLevel.Error, String.Format("A error ocurred while executing the transform '{0}', on line {1}, at position {2}. The error message was: {3}", e.SourceUri, e.LineNumber, e.LinePosition, (e.InnerException == null) ? e.Message : e.InnerException.Message));
+ } finally {
+ writer.Close();
+ }
+
+ // replace the document by the contents of the buffer
+ buffer.Seek(0, SeekOrigin.Begin);
+
+ // some settings to ensure that we don't try to go get, parse, and validate using any referenced schemas or DTDs
+ XmlReaderSettings readerSettings = new XmlReaderSettings();
+ readerSettings.ProhibitDtd = false;
+ readerSettings.XmlResolver = null;
+
+ XmlReader reader = XmlReader.Create(buffer, readerSettings);
+ try {
+ document.Load(reader);
+ } catch (XmlException e) {
+ WriteMessage(MessageLevel.Error, String.Format("A error ocurred while executing the transform '{0}', on line {1}, at position {2}. The error message was: {3}", e.SourceUri, e.LineNumber, e.LinePosition, (e.InnerException == null) ? e.Message : e.InnerException.Message));
+ } finally {
+ reader.Close();
+ }
+
+ }
+ }
+
+ }
+
+ }
+
+
+ // a represenataion of a transform action
+
+ internal class Transform {
+
+ public Transform (string file) {
+ // The transforms presumably come from a trusted source, so there's no reason
+ // not to enable scripting and the document function. The latter is used to read topic
+ // info files for the conceptual WebDocs build.
+ xslt.Load(file, new XsltSettings(true, true), new XmlUrlResolver());
+ }
+
+ private XslCompiledTransform xslt = new XslCompiledTransform();
+
+ private XsltArgumentList arguments = new XsltArgumentList();
+
+ public XslCompiledTransform Xslt {
+ get {
+ return(xslt);
+ }
+ }
+
+ public XsltArgumentList Arguments {
+ get {
+ return(arguments);
+ }
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ValidateComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ValidateComponent.cs
new file mode 100644
index 0000000..aeb8854
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ValidateComponent.cs
@@ -0,0 +1,47 @@
+// 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.
+
+using System;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class ValidateComponent : BuildComponent {
+
+ private XmlSchemaSet schemas = new XmlSchemaSet();
+
+ public ValidateComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+
+ XPathNodeIterator schema_nodes = configuration.Select("schema");
+ foreach (XPathNavigator schema_node in schema_nodes) {
+ string file = schema_node.GetAttribute("file", String.Empty);
+ schemas.Add(null, file);
+ }
+
+ }
+
+ public override void Apply (XmlDocument document, string key) {
+
+ // set the validate schema
+ document.Schemas = schemas;
+
+ // create a validation handler
+ ValidationEventHandler handler = new ValidationEventHandler(LogValidationError);
+
+ // validate the document
+ document.Validate(handler);
+
+ }
+
+ private void LogValidationError (Object o, ValidationEventArgs e) {
+ string message = String.Format("ValidationError: {0}", e.Message);
+ WriteMessage(MessageLevel.Warn, message);
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/WdxResolveConceptualLinksComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/WdxResolveConceptualLinksComponent.cs
new file mode 100644
index 0000000..a827164
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/WdxResolveConceptualLinksComponent.cs
@@ -0,0 +1,299 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Text.RegularExpressions;
+using System.Web;
+
+
+namespace Microsoft.Ddue.Tools {
+
+ /// <summary>
+ /// WdxResolveConceptualLinksComponent handles conceptual links where the target is a GUID. All other kinds
+ /// of targets are considered invalid. NOTE: This is an experimental version for WebDocs.
+ /// </summary>
+ public class WdxResolveConceptualLinksComponent : BuildComponent {
+
+ const int MaxTargetCacheSize = 1000;
+
+ TargetSetList targetSets = new TargetSetList();
+ XPathExpression baseUrl;
+ string invalidLinkFormat = "<span class='nolink'>{1}</span>";
+ string brokenLinkFormat = "<a href='http://msdn2.microsoft.com/en-us/library/{0}'>{1}</a>";
+ string defaultFormat = "<a href='{0}'>{1}</a>";
+
+ public WdxResolveConceptualLinksComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) {
+ //System.Diagnostics.Debugger.Break();
+
+ string av; // temporary attribute values
+
+ // base-url is an xpath expression that is used to lookup the url that relative links need to be
+ // relative to. The lookup is done against the current document. This attribute is needed only if
+ // one of the targets uses relative links that are not in the current directory. If not specified,
+ // the target uses the url from the meta data unchanged.
+ av = configuration.GetAttribute("base-url", String.Empty);
+ if (!String.IsNullOrEmpty(av))
+ baseUrl = CompileXPathExpression(av);
+
+ // invalid-link-format specifies a string format to be used for invalid (target is not a valid GUID)
+ // links. The string formatter is called with parameter {0} set to the target attribute of the link,
+ // and parameter {1} set to the tag content from the source document. A reasonable default is used
+ // if the value is not specified.
+ av = configuration.GetAttribute("invalid-link-format", String.Empty);
+ if (!String.IsNullOrEmpty(av))
+ invalidLinkFormat = av;
+
+ // broken-link-format specifies a string format to be used for broken links (target GUID lookup
+ // failed in all targets). The string formatter is called with parameter {0} set to the target attribute
+ // of the link, and parameter {1} set to the tag content from the source document. A reasonable
+ // default is used if the value is not specified.
+ av = configuration.GetAttribute("broken-link-format", String.Empty);
+ if (!String.IsNullOrEmpty(av))
+ brokenLinkFormat = av;
+
+ // <targets> specifies a lookup solution for each possible set of link targets. Each target must
+ // specify either a lookup file or error condition (invalid-link, broken-link).
+ XPathNodeIterator targetsNodes = configuration.Select("targets");
+ foreach (XPathNavigator targetsNode in targetsNodes) {
+
+ // lookup-file specifies the meta data file used for looking up URLs and titles. The value will
+ // go through environment variable expansion during setup and then through string formatting after
+ // computing the url, with parameter {0} set to the link target GUID. This attribute is required.
+ string lookupFile = targetsNode.GetAttribute("lookup-file", String.Empty);
+ if (string.IsNullOrEmpty(lookupFile))
+ WriteMessage(MessageLevel.Error, "Each target must have a lookup-file attribute.");
+ else
+ lookupFile = Environment.ExpandEnvironmentVariables(lookupFile);
+
+ // check-file-exists if specified ensures that the link target file exists; if it doesn't exist we
+ // take the broken link action.
+ string checkFileExists = targetsNode.GetAttribute("check-file-exists", String.Empty);
+ if (!String.IsNullOrEmpty(checkFileExists))
+ checkFileExists = Environment.ExpandEnvironmentVariables(checkFileExists);
+
+ // url is an xpath expression that is used to lookup the link url in the meta data file. The default
+ // value can be used to lookup the url in .cmp.xml files.
+ av = targetsNode.GetAttribute("url", String.Empty);
+ XPathExpression url = String.IsNullOrEmpty(av) ?
+ XPathExpression.Compile("concat(/metadata/topic/@id,'.htm')") :
+ XPathExpression.Compile(av);
+
+ // text is an xpath expression that is used to lookup the link text in the meta data file. The default
+ // value can be used to lookup the link text in .cmp.xml files.
+ av = targetsNode.GetAttribute("text", string.Empty);
+ XPathExpression text = String.IsNullOrEmpty(av) ?
+ XPathExpression.Compile("string(/metadata/topic/title)") :
+ XPathExpression.Compile(av);
+
+ // relative-url determines whether the links from this target set are relative to the current page
+ // and need to be adjusted to the base directory.
+ av = targetsNode.GetAttribute("relative-url", String.Empty);
+ bool relativeUrl = String.IsNullOrEmpty(av) ? false : Convert.ToBoolean(av);;
+
+ // format is a format string that is used to generate the link. Parameter {0} is the url;
+ // parameter {1} is the text. The default creates a standard HTML link.
+ string format = targetsNode.GetAttribute("format", String.Empty);
+ if (String.IsNullOrEmpty(format))
+ format = defaultFormat;
+
+ // target looks OK
+ targetSets.Add(new TargetSet(lookupFile, checkFileExists, url, text, relativeUrl, format));
+ }
+
+ WriteMessage(MessageLevel.Info, String.Format("Collected {0} targets directories.", targetSets.Count));
+ }
+
+ public override void Apply(XmlDocument document, string key) {
+ // Run through all conceptual nodes, make sure the target is a valid GUID, attempt to resolve the target
+ // to a link using one of the TargetSet definitions, and then replace the node with the result. Errors
+ // will be dealt with as follows: 1) bad target (GUID) -> output invalidLinkFormat; 2) broken link (cannot
+ // resolve target or the URL is empty) -> output brokenLinkFormat; 3) missing text -> just delete the node
+ // and don't output anything (presumably there's no point in creating a link that nobody can see). In all
+ // three cases we'll log the problem as a warning.
+ string docBaseUrl = baseUrl == null ? null : BuildComponentUtilities.EvalXPathExpr(document, baseUrl, "key", key);
+ XPathNavigator[] linkNodes = BuildComponentUtilities.ConvertNodeIteratorToArray(document.CreateNavigator().Select(conceptualLinks));
+ foreach (XPathNavigator node in linkNodes) {
+ string targetGuid = node.GetAttribute("target", String.Empty);
+ string url = targetGuid;
+ string text = node.ToString();
+ string format;
+ if (validGuid.IsMatch(url)) {
+ format = brokenLinkFormat;
+ Target t = targetSets.Lookup(targetGuid);
+ if (t == null) {
+ WriteMessage(MessageLevel.Warn, String.Format("Conceptual link not found in target sets; target={0}", targetGuid));
+ }
+ else {
+ if (!String.IsNullOrEmpty(t.Url)) {
+ format = t.TargetSet.Format;
+ url = (docBaseUrl != null && t.TargetSet.RelativeUrl) ?
+ BuildComponentUtilities.GetRelativePath(t.Url, docBaseUrl) : t.Url;
+ if (!String.IsNullOrEmpty(t.Text))
+ text = t.Text;
+ }
+ else
+ WriteMessage(MessageLevel.Warn, String.Format("Conceptual link found in target set, but meta data does not specify a url; target={0}", targetGuid));
+ }
+ }
+ else
+ format = invalidLinkFormat;
+
+ if (String.IsNullOrEmpty(text)) {
+ node.DeleteSelf();
+ WriteMessage(MessageLevel.Warn, String.Format("Skipping conceptual link without text; target={0}", url));
+ }
+ else {
+ node.OuterXml = String.Format(format, url, text);
+ }
+ }
+ }
+
+ private static XPathExpression conceptualLinks = XPathExpression.Compile("//conceptualLink");
+ private static Regex validGuid = new Regex(@"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", RegexOptions.Compiled);
+
+
+ #region HelperFunctions
+
+ public XPathExpression CompileXPathExpression(string xpath) {
+ XPathExpression expression = null;
+ try {
+ expression = XPathExpression.Compile(xpath);
+ }
+ catch (ArgumentException e) {
+ WriteMessage(MessageLevel.Error, String.Format("'{0}' is not a valid XPath expression. The error message is: {1}", xpath, e.Message));
+ }
+ catch (XPathException e) {
+ WriteMessage(MessageLevel.Error, String.Format("'{0}' is not a valid XPath expression. The error message is: {1}", xpath, e.Message));
+ }
+ return (expression);
+ }
+
+ #endregion HelperFunctions
+
+
+ #region DataStructures
+
+ //
+ // Internal data structures to support WdxResolveConceptualLinksComponent
+ //
+
+ class TargetSet {
+ string lookupFile;
+ string checkFileExists;
+ XPathExpression url;
+ XPathExpression text;
+
+ bool relativeUrl;
+ public bool RelativeUrl {
+ get { return relativeUrl; }
+ }
+
+ string format;
+ public string Format {
+ get { return format; }
+ }
+
+ public TargetSet(string lookupFile, string checkFileExists, XPathExpression url, XPathExpression text, bool relativeUrl, string format) {
+ if (lookupFile == null)
+ throw new ArgumentNullException("lookupFile");
+ this.lookupFile = lookupFile;
+
+ this.checkFileExists = checkFileExists;
+
+ if (url == null)
+ throw new ArgumentNullException("url");
+ this.url = url;
+
+ if (text == null)
+ throw new ArgumentNullException("text");
+ this.text = text;
+
+ this.relativeUrl = relativeUrl;
+
+ if (format == null)
+ throw new ArgumentNullException("format");
+ this.format = format;
+ }
+
+ public Target Lookup(string targetGuid) {
+ string lookupFilePathName = String.Format(lookupFile, targetGuid);
+ if (File.Exists(lookupFilePathName) &&
+ (checkFileExists == null || File.Exists(String.Format(checkFileExists, targetGuid)))) {
+ XPathDocument document = new XPathDocument(lookupFilePathName);
+ return new Target(this,
+ (string)document.CreateNavigator().Evaluate(url),
+ (string)document.CreateNavigator().Evaluate(text));
+ }
+ return null;
+ }
+ }
+
+ class TargetSetList {
+ List<TargetSet> targetSets = new List<TargetSet>();
+ Dictionary<string, Target> targetCache = new Dictionary<string, Target>();
+
+ public TargetSetList() {
+ }
+
+ public void Add(TargetSet targetSet) {
+ if (targetSet == null)
+ throw new ArgumentNullException("targetSet");
+ this.targetSets.Add(targetSet);
+ }
+
+ public int Count {
+ get { return targetSets.Count; }
+ }
+
+ public Target Lookup(string targetGuid) {
+ Target t = null;
+ if (!targetCache.TryGetValue(targetGuid, out t)) {
+ foreach (TargetSet ts in targetSets) {
+ t = ts.Lookup(targetGuid);
+ if (t != null) {
+ if (targetCache.Count >= MaxTargetCacheSize)
+ targetCache.Clear();
+ targetCache.Add(targetGuid, t);
+ break;
+ }
+ }
+ }
+ return t;
+ }
+ }
+
+ class Target {
+ TargetSet targetSet;
+ public TargetSet TargetSet {
+ get { return targetSet; }
+ }
+
+ string url;
+ public string Url {
+ get { return url; }
+ }
+
+ string text;
+ public string Text {
+ get { return text; }
+ }
+
+ public Target(TargetSet targetSet, string url, string text) {
+ if (targetSet == null)
+ throw new ArgumentNullException("targetSet");
+ this.targetSet = targetSet;
+ this.url = url;
+ this.text = text;
+ }
+ }
+
+ #endregion DataStructures
+ }
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/CopyComponents/CopyComponents.csproj b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/CopyComponents.csproj
new file mode 100644
index 0000000..7cf0bb0
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/CopyComponents.csproj
@@ -0,0 +1,80 @@
+<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.Web.Services" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="GlobalSuppressions.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="InheritDocumentationComponent.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\BuildAssemblerLibrary\BuildAssemblerLibrary.csproj">
+ <Project>{399E78F8-4954-409E-991A-37DA9D0579CC}</Project>
+ <Name>BuildAssemblerLibrary</Name>
+ </ProjectReference>
+ <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/GlobalSuppressions.cs b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/GlobalSuppressions.cs
new file mode 100644
index 0000000..210bf57
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/GlobalSuppressions.cs
@@ -0,0 +1,17 @@
+// 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.
+
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+//
+// To add a suppression to this file, right-click the message in the
+// Error List, point to "Suppress Message(s)", and click
+// "In Project Suppression File".
+// You do not need to add suppressions to this file manually.
+
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ddue", Scope = "namespace", Target = "Microsoft.Ddue.Tools")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")]
diff --git a/tools/Sandcastle/Source/BuildAssembler/CopyComponents/InheritDocumentationComponent.cs b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/InheritDocumentationComponent.cs
new file mode 100644
index 0000000..9df1282
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/InheritDocumentationComponent.cs
@@ -0,0 +1,373 @@
+// ------------------------------------------------------------------------------------------------
+// <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
+ }
+}
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..c834f96
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/Properties/AssemblyInfo.cs
@@ -0,0 +1,46 @@
+//--------------------------------------------------------------------------
+// <copyright file="AssemblyInfo.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 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("")]
+
+[assembly: System.CLSCompliant(true)]
+
+// 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.5.10626.00")]
+[assembly: AssemblyFileVersion("2.5.10626.00")]
diff --git a/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/AspNetSyntax.cs b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/AspNetSyntax.cs
new file mode 100644
index 0000000..8f25f1b
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/AspNetSyntax.cs
@@ -0,0 +1,210 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+
+ public class AspNetSyntaxGenerator : SyntaxGenerator {
+
+ public AspNetSyntaxGenerator (XPathNavigator configuration) : base(configuration) {
+ }
+
+ protected static XPathExpression nameExpression = XPathExpression.Compile("string(apidata/@name)");
+ protected static XPathExpression groupExpression = XPathExpression.Compile("string(apidata/@group)");
+ protected static XPathExpression subgroupExpression = XPathExpression.Compile("string(apidata/@subgroup)");
+
+ protected static XPathExpression containingTypeExpression = XPathExpression.Compile("containers/type");
+ protected static XPathExpression declaringTypeExpression = XPathExpression.Compile("string(containers/type/@api)");
+ protected static XPathExpression propertyTypeExpression = XPathExpression.Compile("string(returns/type/@api)");
+ protected static XPathExpression propertyIsSettable = XPathExpression.Compile("boolean(propertydata/@set='true')");
+ protected static XPathExpression eventHandlerTypeExpression = XPathExpression.Compile("string(eventhandler/type/@api)");
+
+ protected static XPathExpression typeIsWebControl = XPathExpression.Compile("boolean(family/ancestors/type[@api='T:System.Web.UI.Control'])");
+
+ protected static XPathExpression propertyIsInnerProperty = XPathExpression.Compile("boolean(attributes/attribute[type/@api='T:System.Web.UI.PersistenceModeAttribute' and argument/enumValue/field/@name='InnerProperty'])");
+
+ protected static XPathExpression containingNamespaceExpression = XPathExpression.Compile("string(containers/namespace/@api)");
+
+ private string language = "AspNet";
+
+ public string Language {
+ get {
+ return (language);
+ }
+ }
+
+ public override void WriteSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string group = (string)reflection.Evaluate(groupExpression);
+ string subgroup = (string)reflection.Evaluate(subgroupExpression);
+
+ if (group == "type" && subgroup == "class") {
+ string prefix = WebControlPrefix(reflection);
+ if (!String.IsNullOrEmpty(prefix)) {
+ WriteClassSyntax(reflection, writer, prefix);
+ }
+ }
+
+ if (group == "member") {
+
+ string prefix = null;
+ XPathNavigator containingType = reflection.SelectSingleNode(containingTypeExpression);
+ if (containingType != null) prefix = WebControlPrefix(containingType);
+
+ if (!String.IsNullOrEmpty(prefix)) {
+ if (subgroup == "property") {
+ WritePropertySyntax(reflection, writer, prefix);
+ } else if (subgroup == "event") {
+ WriteEventSyntax(reflection, writer, prefix);
+ }
+ }
+ }
+
+
+ }
+
+ private string WebControlPrefix (XPathNavigator reflection) {
+ if ((bool)reflection.Evaluate(typeIsWebControl)) {
+ string name = (string)reflection.Evaluate(nameExpression);
+ string space = (string)reflection.Evaluate(containingNamespaceExpression);
+ if ((space == "N:System.Web.UI") && ((name == "Page") || (name == "ScriptControl") || (name == "UserControl"))) {
+ return (null);
+ } else {
+ if (space == "N:System.Web.UI.MobileControls") {
+ return ("mobile");
+ } else {
+ return ("asp");
+ }
+ }
+ } else {
+ return (null);
+ }
+ }
+
+ private void WriteClassSyntax (XPathNavigator reflection, SyntaxWriter writer, string prefix) {
+
+ string name = (string)reflection.Evaluate(nameExpression);
+
+ writer.WriteStartBlock(Language);
+
+ writer.WriteString("<");
+ writer.WriteString(prefix);
+ writer.WriteString(":");
+ writer.WriteString(name);
+ writer.WriteString(" />");
+
+ writer.WriteEndBlock();
+
+ }
+
+ private void WritePropertySyntax (XPathNavigator reflection, SyntaxWriter writer, string prefix) {
+
+ bool set = (bool) reflection.Evaluate(propertyIsSettable);
+ if (!set) return;
+
+ string name = (string) reflection.Evaluate(nameExpression);
+ string declaringType = (string) reflection.Evaluate(declaringTypeExpression);
+ string propertyType = (string) reflection.Evaluate(propertyTypeExpression);
+
+ bool isInnerProperty = (bool)reflection.Evaluate(propertyIsInnerProperty);
+
+ writer.WriteStartBlock(Language);
+
+ if (isInnerProperty) {
+
+ // inner property logic
+
+ writer.WriteString("<");
+ writer.WriteString(prefix);
+ writer.WriteString(":");
+ writer.WriteReferenceLink(declaringType);
+ writer.WriteString(">");
+
+ writer.WriteLine();
+ writer.WriteString("\t");
+
+ writer.WriteString("<");
+ writer.WriteString(name);
+ writer.WriteString(">");
+ if (String.IsNullOrEmpty(propertyType)) {
+ writer.WriteParameter("value");
+ } else {
+ if (propertyType == "T:System.Boolean") {
+ writer.WriteString("True|False");
+ } else {
+ writer.WriteReferenceLink(propertyType);
+ }
+ }
+ writer.WriteString("</");
+ writer.WriteString(name);
+ writer.WriteString(">");
+
+ writer.WriteLine();
+
+ writer.WriteString("</");
+ writer.WriteString(prefix);
+ writer.WriteString(":");
+ writer.WriteReferenceLink(declaringType);
+ writer.WriteString(">");
+
+ } else {
+
+ // normal property logic
+
+ writer.WriteString("<");
+ writer.WriteString(prefix);
+ writer.WriteString(":");
+ writer.WriteReferenceLink(declaringType);
+ writer.WriteString(" ");
+ writer.WriteString(name);
+ writer.WriteString("=\"");
+ if (String.IsNullOrEmpty(propertyType)) {
+ writer.WriteParameter("value");
+ } else {
+ if (propertyType == "T:System.Boolean") {
+ writer.WriteString("True|False");
+ } else {
+ writer.WriteReferenceLink(propertyType);
+ }
+ }
+ writer.WriteString("\" />");
+
+ }
+
+ writer.WriteEndBlock();
+
+ }
+
+ private void WriteEventSyntax (XPathNavigator reflection, SyntaxWriter writer, string prefix) {
+
+ string name = (string)reflection.Evaluate(nameExpression);
+ string declaringType = (string)reflection.Evaluate(declaringTypeExpression);
+ string handlerType = (string)reflection.Evaluate(eventHandlerTypeExpression);
+
+ writer.WriteStartBlock(Language);
+
+ writer.WriteString("<");
+ writer.WriteString(prefix);
+ writer.WriteString(":");
+ writer.WriteReferenceLink(declaringType);
+ writer.WriteString(" ");
+ writer.WriteString("On");
+ writer.WriteString(name);
+ writer.WriteString("=\"");
+ writer.WriteReferenceLink(handlerType);
+ writer.WriteString("\" />");
+
+ writer.WriteEndBlock();
+
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/CPlusPlusDeclarationSyntax.cs b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/CPlusPlusDeclarationSyntax.cs
new file mode 100644
index 0000000..56c6316
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/CPlusPlusDeclarationSyntax.cs
@@ -0,0 +1,1065 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+
+ public class CPlusPlusDeclarationSyntaxGenerator : SyntaxGeneratorTemplate {
+
+ public CPlusPlusDeclarationSyntaxGenerator (XPathNavigator configuration) : base(configuration) {
+ if (String.IsNullOrEmpty(Language)) Language = "ManagedCPlusPlus";
+ }
+
+ // namespace: done
+ public override void WriteNamespaceSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = reflection.Evaluate(apiNameExpression).ToString();
+
+ writer.WriteKeyword("namespace");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+
+ }
+
+ public override void WriteClassSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = reflection.Evaluate(apiNameExpression).ToString();
+ bool isAbstract = (bool) reflection.Evaluate(apiIsAbstractTypeExpression);
+ bool isSealed = (bool) reflection.Evaluate(apiIsSealedTypeExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", true, writer);
+ WriteAttributes(reflection, writer);
+
+ WriteGenericTemplates(reflection, writer);
+
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("ref class");
+ writer.WriteString(" ");
+
+ writer.WriteIdentifier(name);
+
+ if (isAbstract) {
+ writer.WriteString(" ");
+ writer.WriteKeyword("abstract");
+ }
+ if (isSealed) {
+ writer.WriteString(" ");
+ writer.WriteKeyword("sealed");
+ }
+
+ WriteBaseClassAndImplementedInterfaces(reflection, writer);
+
+ }
+
+ // structure: add base type declaration
+ public override void WriteStructureSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", true, writer);
+ WriteAttributes(reflection, writer);
+
+ WriteGenericTemplates(reflection, writer);
+
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("value class");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteImplementedInterfaces(reflection, writer);
+
+ }
+
+ public override void WriteInterfaceSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+
+ WriteAttributes(reflection, writer);
+
+ WriteGenericTemplates(reflection, writer);
+
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("interface class");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteImplementedInterfaces(reflection, writer);
+
+ }
+
+ // delegate: done
+ public override void WriteDelegateSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", true, writer);
+ WriteAttributes(reflection, writer);
+
+ WriteGenericTemplates(reflection, writer);
+
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("delegate");
+ writer.WriteString(" ");
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteMethodParameters(reflection, writer);
+
+ }
+
+
+ public override void WriteEnumerationSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", true, writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("enum class");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+
+ // *** ENUM BASE ***
+
+ }
+
+ public override void WriteConstructorSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiContainingTypeNameExpression);
+ bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression);
+
+ WriteAttributes(reflection, writer);
+
+ WriteVisibility(reflection, writer);
+ writer.WriteString(":");
+ writer.WriteLine();
+
+ if (isStatic) {
+ writer.WriteKeyword("static");
+ writer.WriteString(" ");
+ }
+
+ writer.WriteIdentifier(name);
+
+ WriteMethodParameters(reflection, writer);
+
+ }
+
+
+ public override void WriteNormalMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ string typeSubgroup = (string) reflection.Evaluate(apiContainingTypeSubgroupExpression);
+ bool isExplicit = (bool) reflection.Evaluate(apiIsExplicitImplementationExpression);
+
+ WriteAttributes(reflection, writer);
+
+ if (typeSubgroup == "interface") {
+ WriteGenericTemplates(reflection, writer);
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteMethodParameters(reflection, writer);
+ } else {
+ WriteProcedureVisibility(reflection, writer);
+ WriteGenericTemplates(reflection, writer);
+ WritePrefixProcedureModifiers(reflection, writer);
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteMethodParameters(reflection, writer);
+ WritePostfixProcedureModifiers(reflection, writer);
+ }
+ WriteExplicitImplementations(reflection, writer);
+
+ }
+
+ private void WriteExplicitImplementations (XPathNavigator reflection, SyntaxWriter writer) {
+ bool isExplicit = (bool)reflection.Evaluate(apiIsExplicitImplementationExpression);
+ if (isExplicit) {
+ writer.WriteString(" = ");
+
+ XPathNodeIterator implements = reflection.Select(apiImplementedMembersExpression);
+ while (implements.MoveNext()) {
+ XPathNavigator implement = implements.Current;
+ //string id = (string)implement.GetAttribute("api", String.Empty);
+ XPathNavigator contract = implement.SelectSingleNode(memberDeclaringTypeExpression);
+
+ if (implements.CurrentPosition > 1) writer.WriteString(", ");
+ WriteTypeReference(contract, false, writer);
+ writer.WriteString("::");
+ WriteMemberReference(implement, writer);
+ // writer.WriteReferenceLink(id);
+ }
+ }
+ }
+
+ public override void WriteOperatorSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ string name = (string) reflection.Evaluate(apiNameExpression);
+
+ string identifier;
+ switch (name) {
+ case "UnaryPlus":
+ identifier = "+";
+ break;
+ case "UnaryNegation":
+ identifier = "-";
+ break;
+ case "Increment":
+ identifier = "++";
+ break;
+ case "Decrement":
+ identifier = "--";
+ break;
+ // unary logical operators
+ case "LogicalNot":
+ identifier = "!";
+ break;
+ // binary comparison operators
+ case "Equality":
+ identifier = "==";
+ break;
+ case "Inequality":
+ identifier = "!=";
+ break;
+ case "LessThan":
+ identifier = "<";
+ break;
+ case "GreaterThan":
+ identifier = ">";
+ break;
+ case "LessThanOrEqual":
+ identifier = "<=";
+ break;
+ case "GreaterThanOrEqual":
+ identifier = ">=";
+ break;
+ // binary math operators
+ case "Addition":
+ identifier = "+";
+ break;
+ case "Subtraction":
+ identifier = "-";
+ break;
+ case "Multiply":
+ identifier = "*";
+ break;
+ case "Division":
+ identifier = "/";
+ break;
+ case "Modulus":
+ identifier = "%";
+ break;
+ // binary logical operators
+ case "BitwiseAnd":
+ identifier = "&";
+ break;
+ case "BitwiseOr":
+ identifier = "|";
+ break;
+ case "ExclusiveOr":
+ identifier = "^";
+ break;
+ // bit-array operators
+ case "OnesComplement":
+ identifier = "~";
+ break;
+ case "LeftShift":
+ identifier = "<<";
+ break;
+ case "RightShift":
+ identifier = ">>";
+ break;
+ // others
+ case "Comma":
+ identifier = ",";
+ break;
+ case "MemberSelection":
+ identifier = "->";
+ break;
+ case "AddressOf":
+ identifier = "&";
+ break;
+ case "PointerDereference":
+ identifier = "*";
+ break;
+ case "Assign":
+ identifier = "=";
+ break;
+ // unrecognized operator
+ default:
+ identifier = null;
+ break;
+ }
+
+ if (identifier == null) {
+ writer.WriteMessage("UnsupportedOperator_" + Language);
+ } else {
+
+ WriteProcedureVisibility(reflection, writer);
+ WritePrefixProcedureModifiers(reflection, writer);
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("operator");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(identifier);
+ WriteMethodParameters(reflection, writer);
+ }
+
+ }
+
+ public override void WriteCastSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ string name = (string)reflection.Evaluate(apiNameExpression);
+
+ WritePrefixProcedureModifiers(reflection, writer);
+ if (name == "Implicit") {
+ writer.WriteKeyword("implicit operator");
+ } else if (name == "Explicit") {
+ writer.WriteKeyword("explicit operator");
+ } else {
+ throw new InvalidOperationException("invalid cast type: " + name);
+ }
+ writer.WriteString(" ");
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ WriteMethodParameters(reflection, writer);
+
+ }
+
+ public override void WritePropertySyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ string typeSubgroup = (string) reflection.Evaluate(apiContainingTypeSubgroupExpression);
+ bool isDefault = (bool)reflection.Evaluate(apiIsDefaultMemberExpression);
+ bool hasGetter = (bool) reflection.Evaluate(apiIsReadPropertyExpression);
+ bool hasSetter = (bool) reflection.Evaluate(apiIsWritePropertyExpression);
+ bool isExplicit = (bool) reflection.Evaluate(apiIsExplicitImplementationExpression);
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+
+ WriteAttributes(reflection, writer);
+ WriteProcedureVisibility(reflection, writer);
+ WritePrefixProcedureModifiers(reflection, writer);
+ writer.WriteKeyword("property");
+ writer.WriteString(" ");
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+
+ // if is default member, write default, otherwise write name
+ if (isDefault) {
+ writer.WriteKeyword("default");
+ } else {
+ writer.WriteIdentifier(name);
+ }
+
+ if (parameters.Count > 0) {
+ writer.WriteString("[");
+ WriteParameters(parameters.Clone(), false, writer);
+ writer.WriteString("]");
+ }
+
+ writer.WriteString(" {");
+ writer.WriteLine();
+
+ if (hasGetter) {
+ writer.WriteString("\t");
+
+ //write the get visibility
+ string getVisibility = (string)reflection.Evaluate(apiGetVisibilityExpression);
+ if (!String.IsNullOrEmpty(getVisibility))
+ {
+ WriteVisibility(getVisibility, writer);
+ writer.WriteString(":");
+ writer.WriteString(" ");
+ }
+
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("get");
+ writer.WriteString(" ");
+
+ writer.WriteString("(");
+ WriteParameters(parameters.Clone(), false, writer);
+ writer.WriteString(")");
+
+ WritePostfixProcedureModifiers(reflection, writer);
+ if (isExplicit) {
+ XPathNavigator implement = reflection.SelectSingleNode(apiImplementedMembersExpression);
+ XPathNavigator contract = implement.SelectSingleNode(memberDeclaringTypeExpression);
+ //string id = (string) implement.GetAttribute("api", String.Empty);
+
+ writer.WriteString(" = ");
+ WriteTypeReference(contract, false, writer);
+ writer.WriteString("::");
+ WriteMemberReference(implement, writer);
+ //writer.WriteReferenceLink(id);
+ writer.WriteString("::");
+ writer.WriteKeyword("get");
+ }
+ writer.WriteString(";");
+ writer.WriteLine();
+ }
+
+ if (hasSetter) {
+ writer.WriteString("\t");
+
+ // write the set visibility
+ string setVisibility = (string)reflection.Evaluate(apiSetVisibilityExpression);
+ if (!String.IsNullOrEmpty(setVisibility))
+ {
+ WriteVisibility(setVisibility, writer);
+ writer.WriteString(":");
+ writer.WriteString(" ");
+ }
+
+ writer.WriteKeyword("void");
+ writer.WriteString(" ");
+ writer.WriteKeyword("set");
+ writer.WriteString(" ");
+
+ writer.WriteString("(");
+ if (parameters.Count > 0) {
+ WriteParameters(parameters.Clone(), false, writer);
+ writer.WriteString(", ");
+ }
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteParameter("value");
+ writer.WriteString(")");
+
+ WritePostfixProcedureModifiers(reflection, writer);
+ if (isExplicit) {
+ XPathNavigator implement = reflection.SelectSingleNode(apiImplementedMembersExpression);
+ XPathNavigator contract = implement.SelectSingleNode(memberDeclaringTypeExpression);
+ //string id = (string) implement.GetAttribute("api", String.Empty);
+
+ writer.WriteString(" = ");
+ WriteTypeReference(contract, false, writer);
+ writer.WriteString("::");
+ WriteMemberReference(implement, writer);
+ //writer.WriteReferenceLink(id);
+ writer.WriteString("::");
+ writer.WriteKeyword("set");
+ }
+ writer.WriteString(";");
+ writer.WriteLine();
+ }
+
+
+ writer.WriteString("}");
+ }
+
+ public override void WriteEventSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ XPathNavigator handler = reflection.SelectSingleNode(apiHandlerOfEventExpression);
+
+ WriteAttributes(reflection, writer);
+ WriteProcedureVisibility(reflection, writer);
+ WritePrefixProcedureModifiers(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("event");
+ writer.WriteString(" ");
+ WriteTypeReference(handler, writer);
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ writer.WriteString(" {");
+ writer.WriteLine();
+
+ writer.WriteString("\t");
+ writer.WriteKeyword("void");
+ writer.WriteString(" ");
+ writer.WriteKeyword("add");
+ writer.WriteString(" (");
+ WriteTypeReference(handler, writer);
+ writer.WriteString(" ");
+ writer.WriteParameter("value");
+ writer.WriteString(")");
+ writer.WriteString(";");
+ writer.WriteLine();
+
+ writer.WriteString("\t");
+ writer.WriteKeyword("void");
+ writer.WriteString(" ");
+ writer.WriteKeyword("remove");
+ writer.WriteString(" (");
+ WriteTypeReference(handler, writer);
+ writer.WriteString(" ");
+ writer.WriteParameter("value");
+ writer.WriteString(")");
+ writer.WriteString(";");
+ writer.WriteLine();
+
+
+ writer.WriteString("}");
+
+ }
+
+ public override void WriteFieldSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression);
+ bool isLiteral = (bool) reflection.Evaluate(apiIsLiteralFieldExpression);
+ bool isInitOnly = (bool) reflection.Evaluate(apiIsInitOnlyFieldExpression);
+ bool isSerialized = (bool) reflection.Evaluate(apiIsSerializedFieldExpression);
+
+ if (!isSerialized) WriteAttribute("T:System.NonSerializedAttribute", true, writer);
+ WriteAttributes(reflection, writer);
+
+ WriteVisibility(reflection, writer);
+ writer.WriteString(":");
+ writer.WriteLine();
+ if (isStatic) {
+ if (isLiteral) {
+ writer.WriteKeyword("literal");
+ } else {
+ writer.WriteKeyword("static");
+ }
+ writer.WriteString(" ");
+ }
+ if (isInitOnly) {
+ writer.WriteKeyword("initonly");
+ writer.WriteString(" ");
+ }
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+
+ }
+
+ private void WritePrefixProcedureModifiers (XPathNavigator reflection, SyntaxWriter writer) {
+
+ // interface members don't get modified
+ string typeSubgroup = (string) reflection.Evaluate(apiContainingTypeSubgroupExpression);
+ if (typeSubgroup == "interface") return;
+
+ bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression);
+ bool isVirtual = (bool) reflection.Evaluate(apiIsVirtualExpression);
+
+ if (isStatic) {
+ writer.WriteKeyword("static");
+ writer.WriteString(" ");
+ } else if (isVirtual) {
+ writer.WriteKeyword("virtual");
+ writer.WriteString(" ");
+ }
+
+ }
+
+ private void WritePostfixProcedureModifiers (XPathNavigator reflection, SyntaxWriter writer) {
+
+ // interface members don't get modified
+ string typeSubgroup = (string) reflection.Evaluate(apiContainingTypeSubgroupExpression);
+ if (typeSubgroup == "interface") return;
+
+ bool isVirtual = (bool) reflection.Evaluate(apiIsVirtualExpression);
+ bool isAbstract = (bool) reflection.Evaluate(apiIsAbstractProcedureExpression);
+ bool isFinal = (bool) reflection.Evaluate(apiIsFinalExpression);
+ bool isOverride = (bool) reflection.Evaluate(apiIsOverrideExpression);
+
+ if (isVirtual) {
+ if (isAbstract) {
+ writer.WriteString(" ");
+ writer.WriteKeyword("abstract");
+ }
+ if (isOverride) {
+ writer.WriteString(" ");
+ writer.WriteKeyword("override");
+ }
+ if (isFinal) {
+ writer.WriteString(" ");
+ writer.WriteKeyword("sealed");
+ }
+ }
+ }
+
+ // Visibility
+
+ private void WriteProcedureVisibility (XPathNavigator reflection, SyntaxWriter writer) {
+ string typeSubgroup = (string) reflection.Evaluate(apiContainingTypeSubgroupExpression);
+ if (typeSubgroup != "interface") {
+ WriteVisibility(reflection, writer);
+ writer.WriteString(":");
+ writer.WriteLine();
+ }
+
+ }
+
+ private void WriteVisibility(XPathNavigator reflection, SyntaxWriter writer) {
+
+ string visibility = reflection.Evaluate(apiVisibilityExpression).ToString();
+ WriteVisibility(visibility, writer);
+ }
+
+ private void WriteVisibility (string visibility, SyntaxWriter writer) {
+
+ switch (visibility) {
+ case "public":
+ writer.WriteKeyword("public");
+ break;
+ case "family":
+ writer.WriteKeyword("protected");
+ break;
+ case "family or assembly":
+ writer.WriteKeyword("protected public");
+ break;
+ case "family and assembly":
+ writer.WriteKeyword("protected private");
+ break;
+ case "assembly":
+ writer.WriteKeyword("internal");
+ break;
+ case "private":
+ writer.WriteKeyword("private");
+ break;
+ }
+
+ }
+
+ // Generics
+
+ private void WriteGenericTemplates (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator templateNodes = (XPathNodeIterator) reflection.Evaluate(apiTemplatesExpression);
+ if (templateNodes.Count == 0) return;
+ XPathNavigator[] templates = ConvertIteratorToArray(templateNodes);
+ if (templates.Length == 0) return;
+
+ // generic declaration
+ writer.WriteKeyword("generic");
+ writer.WriteString("<");
+ for (int i=0; i<templates.Length; i++) {
+ XPathNavigator template = templates[i];
+ string name = (string) template.Evaluate(templateNameExpression);
+ if (i> 0) writer.WriteString(", ");
+ writer.WriteKeyword("typename");
+ writer.WriteString(" ");
+ writer.WriteString(name);
+ }
+ writer.WriteString(">");
+ writer.WriteLine();
+
+ // generic constraints
+ foreach (XPathNavigator template in templates) {
+ bool constrained = (bool) template.Evaluate(templateIsConstrainedExpression);
+ if (!constrained) continue;
+
+ string name = (string) template.Evaluate(templateNameExpression);
+
+ writer.WriteKeyword("where");
+ writer.WriteString(" ");
+ writer.WriteString(name);
+ writer.WriteString(" : ");
+
+ bool value = (bool) template.Evaluate(templateIsValueTypeExpression);
+ bool reference = (bool) template.Evaluate(templateIsReferenceTypeExpression);
+ bool constructor = (bool) template.Evaluate(templateIsConstructableExpression);
+ XPathNodeIterator constraints = template.Select(templateConstraintsExpression);
+
+ // keep track of whether there is a previous constraint, so we know whether to put a comma
+ bool previous = false;
+
+ if (value) {
+ if (previous) writer.WriteString(", ");
+ writer.WriteKeyword("value class");
+ previous = true;
+ }
+
+ if (reference) {
+ if (previous) writer.WriteString(", ");
+ writer.WriteKeyword("ref class");
+ previous = true;
+ }
+
+ if (constructor) {
+ if (previous) writer.WriteString(", ");
+ writer.WriteKeyword("gcnew");
+ writer.WriteString("()");
+ previous = true;
+ }
+
+ foreach (XPathNavigator constraint in constraints) {
+ if (previous) writer.WriteString(", ");
+ WriteTypeReference(constraint, false, writer);
+ previous = true;
+ }
+
+ writer.WriteLine();
+
+ }
+
+ }
+
+ // Interfaces
+
+ private void WriteImplementedInterfaces (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator implements = reflection.Select(apiImplementedInterfacesExpression);
+
+ if (implements.Count == 0) return;
+ writer.WriteString(" : ");
+ while (implements.MoveNext()) {
+ XPathNavigator implement = implements.Current;
+ WriteTypeReference(implement, false, writer);
+ if (implements.CurrentPosition < implements.Count) {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition) {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ }
+
+ }
+
+ private void WriteBaseClassAndImplementedInterfaces (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNavigator baseClass = reflection.SelectSingleNode(apiBaseClassExpression);
+ XPathNodeIterator implements = reflection.Select(apiImplementedInterfacesExpression);
+
+ bool hasBaseClass = (baseClass != null) && !((bool) baseClass.Evaluate(typeIsObjectExpression));
+ bool hasImplementedInterfaces = (implements.Count > 0);
+
+ if (hasBaseClass || hasImplementedInterfaces) {
+
+ writer.WriteString(" : ");
+ if (hasBaseClass) {
+ writer.WriteKeyword("public");
+ writer.WriteString(" ");
+ WriteTypeReference(baseClass, false, writer);
+ if (hasImplementedInterfaces) {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition) {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ }
+
+ while (implements.MoveNext()) {
+ XPathNavigator implement = implements.Current;
+ WriteTypeReference(implement, false, writer);
+ if (implements.CurrentPosition < implements.Count) {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition) {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ }
+
+ }
+
+ }
+
+ // Return Value
+
+ private void WriteReturnValue (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNavigator type = reflection.SelectSingleNode(apiReturnTypeExpression);
+
+ if (type == null) {
+ writer.WriteKeyword("void");
+ } else {
+ WriteTypeReference(type, writer);
+ }
+ }
+
+
+ private void WriteMethodParameters (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+
+ writer.WriteString("(");
+ if (parameters.Count > 0) {
+ writer.WriteLine();
+ WriteParameters(parameters, true, writer);
+ }
+ writer.WriteString(")");
+
+ }
+
+ private void WriteParameters (XPathNodeIterator parameters, bool multiline, SyntaxWriter writer) {
+
+ while (parameters.MoveNext()) {
+ XPathNavigator parameter = parameters.Current;
+
+ XPathNavigator type = parameter.SelectSingleNode(parameterTypeExpression);
+ string name = (string) parameter.Evaluate(parameterNameExpression);
+ bool isIn = (bool) parameter.Evaluate(parameterIsInExpression);
+ bool isOut = (bool) parameter.Evaluate(parameterIsOutExpression);
+ bool isParamArray = (bool) parameter.Evaluate(parameterIsParamArrayExpression);
+
+ if (multiline) {
+ writer.WriteString("\t");
+ }
+ if (isIn) {
+ WriteAttribute("T:System.Runtime.InteropServices.InAttribute", false, writer);
+ writer.WriteString(" ");
+ }
+ if (isOut) {
+ WriteAttribute("T:System.Runtime.InteropServices.OutAttribute", false, writer);
+ writer.WriteString(" ");
+ }
+ if (isParamArray) writer.WriteString("... ");
+ WriteTypeReference(type, writer);
+ writer.WriteString(" ");
+ writer.WriteParameter(name);
+
+ if (parameters.CurrentPosition < parameters.Count) writer.WriteString(", ");
+ if (multiline) writer.WriteLine();
+ }
+
+ }
+
+ // Type references
+
+ private void WriteTypeReference (XPathNavigator reference, SyntaxWriter writer) {
+ WriteTypeReference(reference, true, writer);
+ }
+
+ private void WriteTypeReference (XPathNavigator reference, bool handle, SyntaxWriter writer) {
+ switch (reference.LocalName) {
+ case "arrayOf":
+ XPathNavigator element = reference.SelectSingleNode(typeExpression);
+ int rank = Convert.ToInt32( reference.GetAttribute("rank",String.Empty) );
+ writer.WriteKeyword("array");
+ writer.WriteString("<");
+ WriteTypeReference(element, writer);
+ if (rank > 1) {
+ writer.WriteString(",");
+ writer.WriteString(rank.ToString());
+ }
+ writer.WriteString(">");
+ if (handle) writer.WriteString("^");
+ break;
+ case "pointerTo":
+ XPathNavigator pointee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(pointee, writer);
+ writer.WriteString("*");
+ break;
+ case "referenceTo":
+ XPathNavigator referee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(referee, writer);
+ writer.WriteString("%");
+ break;
+ case "type":
+ string id = reference.GetAttribute("api", String.Empty);
+ bool isRef = (reference.GetAttribute("ref", String.Empty) == "true");
+ WriteNormalTypeReference(id, writer);
+ XPathNodeIterator typeModifiers = reference.Select(typeModifiersExpression);
+ while (typeModifiers.MoveNext()) {
+ WriteTypeReference(typeModifiers.Current, writer);
+ }
+ if (handle && isRef) writer.WriteString("^");
+
+ break;
+ case "template":
+ string name = reference.GetAttribute("name", String.Empty);
+ writer.WriteString(name);
+ XPathNodeIterator modifiers = reference.Select(typeModifiersExpression);
+ while (modifiers.MoveNext()) {
+ WriteTypeReference(modifiers.Current, writer);
+ }
+ break;
+ case "specialization":
+ writer.WriteString("<");
+ XPathNodeIterator arguments = reference.Select(specializationArgumentsExpression);
+ while (arguments.MoveNext()) {
+ if (arguments.CurrentPosition > 1) writer.WriteString(", ");
+ WriteTypeReference(arguments.Current, writer);
+ }
+ writer.WriteString(">");
+ break;
+ }
+ }
+
+ private void WriteNormalTypeReference (string reference, SyntaxWriter writer) {
+ switch (reference) {
+ case "T:System.Void":
+ writer.WriteReferenceLink(reference, "void");
+ break;
+ case "T:System.Boolean":
+ writer.WriteReferenceLink(reference, "bool");
+ break;
+ case "T:System.Byte":
+ writer.WriteReferenceLink(reference, "unsigned char");
+ break;
+ case "T:System.SByte":
+ writer.WriteReferenceLink(reference, "signed char");
+ break;
+ case "T:System.Char":
+ writer.WriteReferenceLink(reference, "wchar_t");
+ break;
+ case "T:System.Int16":
+ writer.WriteReferenceLink(reference, "short");
+ break;
+ case "T:System.Int32":
+ writer.WriteReferenceLink(reference, "int");
+ break;
+ case "T:System.Int64":
+ writer.WriteReferenceLink(reference, "long long");
+ break;
+ case "T:System.UInt16":
+ writer.WriteReferenceLink(reference, "unsigned short");
+ break;
+ case "T:System.UInt32":
+ writer.WriteReferenceLink(reference, "unsigned int");
+ break;
+ case "T:System.UInt64":
+ writer.WriteReferenceLink(reference, "unsigned long long");
+ break;
+ case "T:System.Single":
+ writer.WriteReferenceLink(reference, "float");
+ break;
+ case "T:System.Double":
+ writer.WriteReferenceLink(reference, "double");
+ break;
+ default:
+ writer.WriteReferenceLink(reference);
+ break;
+ }
+ }
+
+ // Attributes
+
+ private void WriteAttribute (string reference, bool newline, SyntaxWriter writer) {
+ writer.WriteString("[");
+ writer.WriteReferenceLink(reference);
+ writer.WriteString("]");
+ if (newline) writer.WriteLine();
+ }
+
+ private void WriteAttributes (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator attributes = (XPathNodeIterator) reflection.Evaluate(apiAttributesExpression);
+
+ foreach (XPathNavigator attribute in attributes) {
+
+ XPathNavigator type = attribute.SelectSingleNode(typeExpression);
+
+ writer.WriteString("[");
+ WriteTypeReference(type, false, writer);
+
+
+ XPathNodeIterator arguments = (XPathNodeIterator) attribute.Select(attributeArgumentsExpression);
+ XPathNodeIterator assignments = (XPathNodeIterator) attribute.Select(attributeAssignmentsExpression);
+
+ if ((arguments.Count > 0) || (assignments.Count > 0)) {
+ writer.WriteString("(");
+ while (arguments.MoveNext()) {
+ XPathNavigator argument = arguments.Current;
+ if (arguments.CurrentPosition > 1) {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition) {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ WriteValue(argument, writer);
+ }
+ if ((arguments.Count > 0) && (assignments.Count > 0)) writer.WriteString(", ");
+ while (assignments.MoveNext()) {
+ XPathNavigator assignment = assignments.Current;
+ if (assignments.CurrentPosition > 1) {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition) {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ writer.WriteString((string) assignment.Evaluate(assignmentNameExpression));
+ writer.WriteString(" = ");
+ WriteValue(assignment, writer);
+
+ }
+ writer.WriteString(")");
+ }
+
+ writer.WriteString("]");
+ writer.WriteLine();
+ }
+
+ }
+
+ private void WriteValue (XPathNavigator parent, SyntaxWriter writer) {
+
+ XPathNavigator type = parent.SelectSingleNode(attributeTypeExpression);
+ XPathNavigator value = parent.SelectSingleNode(valueExpression);
+ if (value == null) Console.WriteLine("null value");
+
+ switch (value.LocalName) {
+ case "nullValue":
+ writer.WriteKeyword("nullptr");
+ break;
+ case "typeValue":
+ writer.WriteKeyword("typeof");
+ writer.WriteString("(");
+ WriteTypeReference(value.SelectSingleNode(typeExpression), false, writer);
+ writer.WriteString(")");
+ break;
+ case "enumValue":
+ XPathNodeIterator fields = value.SelectChildren(XPathNodeType.Element);
+ while (fields.MoveNext()) {
+ string name = fields.Current.GetAttribute("name", String.Empty);
+ if (fields.CurrentPosition > 1) writer.WriteString("|");
+ WriteTypeReference(type, writer);
+ writer.WriteString("::");
+ writer.WriteString(name);
+ }
+ break;
+ case "value":
+ string text = value.Value;
+ string typeId = type.GetAttribute("api", String.Empty);
+ switch (typeId) {
+ case "T:System.String":
+ writer.WriteString("L\"");
+ writer.WriteString(text);
+ writer.WriteString("\"");
+ break;
+ case "T:System.Boolean":
+ bool bool_value = Convert.ToBoolean(text);
+ if (bool_value) {
+ writer.WriteKeyword("true");
+ } else {
+ writer.WriteKeyword("false");
+ }
+ break;
+ case "T:System.Char":
+ writer.WriteString(@"L'");
+ writer.WriteString(text);
+ writer.WriteString(@"'");
+ break;
+ }
+ break;
+ }
+
+ }
+
+ private void WriteMemberReference (XPathNavigator member, SyntaxWriter writer) {
+ string api = member.GetAttribute("api", String.Empty);
+ writer.WriteReferenceLink(api);
+ }
+
+ private static XPathNavigator[] ConvertIteratorToArray (XPathNodeIterator iterator) {
+ XPathNavigator[] result = new XPathNavigator[iterator.Count];
+ for (int i=0; i<result.Length; i++) {
+ iterator.MoveNext();
+ result[i] = iterator.Current.Clone();
+ }
+ return(result);
+ }
+
+
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/CSharpDeclarationSyntax.cs b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/CSharpDeclarationSyntax.cs
new file mode 100644
index 0000000..3b5922d
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/CSharpDeclarationSyntax.cs
@@ -0,0 +1,982 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+
+ public class CSharpDeclarationSyntaxGenerator : SyntaxGeneratorTemplate {
+
+ public CSharpDeclarationSyntaxGenerator (XPathNavigator configuration) : base(configuration) {
+ if (String.IsNullOrEmpty(Language)) Language = "CSharp";
+ }
+
+ // namespace: done
+ public override void WriteNamespaceSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = reflection.Evaluate(apiNameExpression).ToString();
+
+ writer.WriteKeyword("namespace");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ }
+
+ // class: done
+ public override void WriteClassSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = reflection.Evaluate(apiNameExpression).ToString();
+ bool isAbstract = (bool) reflection.Evaluate(apiIsAbstractTypeExpression);
+ bool isSealed = (bool) reflection.Evaluate(apiIsSealedTypeExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ if (isAbstract) {
+ if (isSealed) {
+ writer.WriteKeyword("static");
+ } else {
+ writer.WriteKeyword("abstract");
+ }
+ writer.WriteString(" ");
+ } else {
+ if (isSealed) {
+ writer.WriteKeyword("sealed");
+ writer.WriteString(" ");
+ }
+ }
+ writer.WriteKeyword("class");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteGenericTemplates(reflection, writer);
+ WriteBaseClassAndImplementedInterfaces(reflection, writer);
+ WriteGenericTemplateConstraints(reflection, writer);
+
+ }
+
+
+ // structure: done
+ public override void WriteStructureSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("struct");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteGenericTemplates(reflection, writer);
+ WriteImplementedInterfaces(reflection, writer);
+ WriteGenericTemplateConstraints(reflection, writer);
+
+ }
+
+ // interface: done
+ public override void WriteInterfaceSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("interface");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteGenericTemplates(reflection, writer, true); // interfaces need co/contravariance info
+ WriteImplementedInterfaces(reflection, writer);
+ WriteGenericTemplateConstraints(reflection, writer);
+
+ }
+
+ // delegate: done
+ public override void WriteDelegateSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("delegate");
+ writer.WriteString(" ");
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteGenericTemplates(reflection, writer, true); // delegates need co/contravariance info
+ WriteMethodParameters(reflection, writer);
+ WriteGenericTemplateConstraints(reflection, writer);
+
+ }
+
+ // enumeration: still need to handle non-standard base
+ public override void WriteEnumerationSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("enum");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ }
+
+ // constructor: done
+ public override void WriteConstructorSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiContainingTypeNameExpression);
+ bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression);
+
+ WriteAttributes(reflection, writer);
+ if (isStatic) {
+ writer.WriteKeyword("static");
+ } else {
+ WriteVisibility(reflection, writer);
+ }
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteMethodParameters(reflection, writer);
+
+ }
+
+ // normal method: done
+ public override void WriteNormalMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+
+ bool isExplicit = (bool) reflection.Evaluate(apiIsExplicitImplementationExpression);
+
+ WriteAttributes(reflection, writer);
+ if (!isExplicit) WriteProcedureModifiers(reflection, writer);
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+
+ if (isExplicit) {
+ XPathNavigator member = reflection.SelectSingleNode(apiImplementedMembersExpression);
+ //string memberName = (string) member.Evaluate(nameExpression);
+ //string id = member.GetAttribute("api", String.Empty);
+ XPathNavigator contract = member.SelectSingleNode(memberDeclaringTypeExpression);
+ WriteTypeReference(contract, writer);
+ writer.WriteString(".");
+ WriteMemberReference(member, writer);
+ //writer.WriteReferenceLink(id);
+ } else {
+ writer.WriteIdentifier(name);
+ }
+ WriteGenericTemplates(reflection, writer);
+ WriteMethodParameters(reflection, writer);
+ WriteGenericTemplateConstraints(reflection, writer);
+
+ }
+
+ // operator: done
+ public override void WriteOperatorSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ string name = (string) reflection.Evaluate(apiNameExpression);
+
+ string identifier;
+ switch (name) {
+ // unary math operators
+ case "UnaryPlus":
+ identifier = "+";
+ break;
+ case "UnaryNegation":
+ identifier = "-";
+ break;
+ case "Increment":
+ identifier = "++";
+ break;
+ case "Decrement":
+ identifier = "--";
+ break;
+ // unary logical operators
+ case "LogicalNot":
+ identifier = "!";
+ break;
+ case "True":
+ identifier = "true";
+ break;
+ case "False":
+ identifier = "false";
+ break;
+ // binary comparison operators
+ case "Equality":
+ identifier = "==";
+ break;
+ case "Inequality":
+ identifier = "!=";
+ break;
+ case "LessThan":
+ identifier = "<";
+ break;
+ case "GreaterThan":
+ identifier = ">";
+ break;
+ case "LessThanOrEqual":
+ identifier = "<=";
+ break;
+ case "GreaterThanOrEqual":
+ identifier = ">=";
+ break;
+ // binary math operators
+ case "Addition":
+ identifier = "+";
+ break;
+ case "Subtraction":
+ identifier = "-";
+ break;
+ case "Multiply":
+ identifier = "*";
+ break;
+ case "Division":
+ identifier = "/";
+ break;
+ case "Modulus":
+ identifier = "%";
+ break;
+ // binary logical operators
+ case "BitwiseAnd":
+ identifier = "&";
+ break;
+ case "BitwiseOr":
+ identifier = "|";
+ break;
+ case "ExclusiveOr":
+ identifier = "^";
+ break;
+ // bit-array operators
+ case "OnesComplement":
+ identifier = "~";
+ break;
+ case "LeftShift":
+ identifier = "<<";
+ break;
+ case "RightShift":
+ identifier = ">>";
+ break;
+ // unrecognized operator
+ default:
+ identifier = null;
+ break;
+ }
+ if (identifier == null) {
+ writer.WriteMessage("UnsupportedOperator_" + Language);
+ } else {
+ WriteProcedureModifiers(reflection, writer);
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("operator");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(identifier);
+ WriteMethodParameters(reflection, writer);
+ }
+ }
+
+ // cast: done
+ public override void WriteCastSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+
+ WriteProcedureModifiers(reflection, writer);
+ if (name == "Implicit") {
+ writer.WriteKeyword("implicit operator");
+ } else if (name == "Explicit") {
+ writer.WriteKeyword("explicit operator");
+ } else {
+ throw new InvalidCastException("Invalid cast.");
+ }
+ writer.WriteString(" ");
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ WriteMethodParameters(reflection, writer);
+
+ }
+
+ public override void WritePropertySyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ bool isDefault = (bool)reflection.Evaluate(apiIsDefaultMemberExpression);
+ bool isGettable = (bool)reflection.Evaluate(apiIsReadPropertyExpression);
+ bool isSettable = (bool)reflection.Evaluate(apiIsWritePropertyExpression);
+ bool isExplicit = (bool)reflection.Evaluate(apiIsExplicitImplementationExpression);
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+
+ WriteAttributes(reflection, writer);
+ if (!isExplicit) WriteProcedureModifiers(reflection, writer);
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+
+ if (isExplicit)
+ {
+ XPathNavigator member = reflection.SelectSingleNode(apiImplementedMembersExpression);
+ XPathNavigator contract = member.SelectSingleNode(memberDeclaringTypeExpression);
+ WriteTypeReference(contract, writer);
+ writer.WriteString(".");
+ if (parameters.Count > 0)
+ {
+ // In C#, EII property with parameters is an indexer; use 'this' instead of the property's name
+ writer.WriteKeyword("this");
+ }
+ else
+ {
+ WriteMemberReference(member, writer);
+ }
+ }
+ else
+ {
+ // In C#, any property with parameters is an indexer, which is declared using 'this' instead of the property's name
+ if (isDefault || parameters.Count > 0)
+ {
+ writer.WriteKeyword("this");
+ }
+ else
+ {
+ writer.WriteIdentifier(name);
+ }
+ }
+
+ WritePropertyParameters(reflection, writer);
+ writer.WriteString(" {");
+ if (isGettable)
+ {
+ writer.WriteString(" ");
+ string getVisibility = (string)reflection.Evaluate(apiGetVisibilityExpression);
+ if (!String.IsNullOrEmpty(getVisibility))
+ {
+ WriteVisibility(getVisibility, writer);
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword("get");
+ writer.WriteString(";");
+ }
+ if (isSettable)
+ {
+ writer.WriteString(" ");
+ string setVisibility = (string)reflection.Evaluate(apiSetVisibilityExpression);
+ if (!String.IsNullOrEmpty(setVisibility))
+ {
+ WriteVisibility(setVisibility, writer);
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword("set");
+ writer.WriteString(";");
+ }
+ writer.WriteString(" }");
+ }
+
+ public override void WriteEventSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ XPathNavigator handler = reflection.SelectSingleNode(apiHandlerOfEventExpression);
+ bool isExplicit = (bool) reflection.Evaluate(apiIsExplicitImplementationExpression);
+
+ WriteAttributes(reflection, writer);
+ if (!isExplicit) WriteProcedureModifiers(reflection, writer);
+ writer.WriteString("event");
+ writer.WriteString(" ");
+ WriteTypeReference(handler, writer);
+ writer.WriteString(" ");
+
+ if (isExplicit) {
+ XPathNavigator member = reflection.SelectSingleNode(apiImplementedMembersExpression);
+ //string id = (string) member.GetAttribute("api", String.Empty);
+ XPathNavigator contract = member.SelectSingleNode(memberDeclaringTypeExpression);
+ WriteTypeReference(contract, writer);
+ writer.WriteString(".");
+ WriteMemberReference(member, writer);
+ //writer.WriteReferenceLink(id);
+ // writer.WriteIdentifier(memberName);
+ } else {
+ writer.WriteIdentifier(name);
+ }
+ }
+
+ private void WriteProcedureModifiers (XPathNavigator reflection, SyntaxWriter writer) {
+
+ // interface members don't get modified
+ string typeSubgroup = (string) reflection.Evaluate(apiContainingTypeSubgroupExpression);
+ if (typeSubgroup == "interface") return;
+
+ bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression);
+ bool isVirtual = (bool) reflection.Evaluate(apiIsVirtualExpression);
+ bool isAbstract = (bool) reflection.Evaluate(apiIsAbstractProcedureExpression);
+ bool isFinal = (bool) reflection.Evaluate(apiIsFinalExpression);
+ bool isOverride = (bool) reflection.Evaluate(apiIsOverrideExpression);
+
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ if (isStatic) {
+ writer.WriteKeyword("static");
+ writer.WriteString(" ");
+ } else {
+ if (isVirtual) {
+ if (isAbstract) {
+ writer.WriteKeyword("abstract");
+ writer.WriteString(" ");
+ } else if (isOverride) {
+ writer.WriteKeyword("override");
+ writer.WriteString(" ");
+ if (isFinal) {
+ writer.WriteKeyword("sealed");
+ writer.WriteString(" ");
+ }
+ } else {
+ if (!isFinal) {
+ writer.WriteKeyword("virtual");
+ writer.WriteString(" ");
+ }
+ }
+ }
+ }
+
+
+ }
+
+ public override void WriteFieldSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression);
+ bool isLiteral = (bool) reflection.Evaluate(apiIsLiteralFieldExpression);
+ bool isInitOnly = (bool) reflection.Evaluate(apiIsInitOnlyFieldExpression);
+ bool isSerialized = (bool) reflection.Evaluate(apiIsSerializedFieldExpression);
+
+ if (!isSerialized) WriteAttribute("T:System.NonSerializedAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ if (isStatic) {
+ if (isLiteral) {
+ writer.WriteKeyword("const");
+ } else {
+ writer.WriteKeyword("static");
+ }
+ writer.WriteString(" ");
+ }
+ if (isInitOnly) {
+ writer.WriteKeyword("readonly");
+ writer.WriteString(" ");
+ }
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+
+ }
+
+ // Visibility
+
+ private void WriteVisibility (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string visibility = reflection.Evaluate(apiVisibilityExpression).ToString();
+ WriteVisibility(visibility, writer);
+ }
+
+ private void WriteVisibility (string visibility, SyntaxWriter writer) {
+
+ switch (visibility) {
+ case "public":
+ writer.WriteKeyword("public");
+ break;
+ case "family":
+ writer.WriteKeyword("protected");
+ break;
+ case "family or assembly":
+ writer.WriteKeyword("protected internal");
+ break;
+ case "assembly":
+ writer.WriteKeyword("internal");
+ break;
+ case "private":
+ writer.WriteKeyword("private");
+ break;
+ case "family and assembly":
+ // this isn't handled in C#
+ break;
+ }
+
+ }
+
+
+ // Attributes
+
+ private void WriteAttribute (string reference, SyntaxWriter writer) {
+ writer.WriteString("[");
+ writer.WriteReferenceLink(reference);
+ writer.WriteString("]");
+ writer.WriteLine();
+ }
+
+
+ private void WriteAttributes (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator attributes = (XPathNodeIterator) reflection.Evaluate(apiAttributesExpression);
+
+ foreach (XPathNavigator attribute in attributes) {
+
+ XPathNavigator type = attribute.SelectSingleNode(attributeTypeExpression);
+ if (type.GetAttribute("api", String.Empty) == "T:System.Runtime.CompilerServices.ExtensionAttribute") continue;
+
+ writer.WriteString("[");
+ WriteTypeReference(type, writer);
+
+ XPathNodeIterator arguments = (XPathNodeIterator) attribute.Select(attributeArgumentsExpression);
+ XPathNodeIterator assignments = (XPathNodeIterator) attribute.Select(attributeAssignmentsExpression);
+
+ if ((arguments.Count > 0) || (assignments.Count > 0)) {
+ writer.WriteString("(");
+ while (arguments.MoveNext()) {
+ XPathNavigator argument = arguments.Current;
+ if (arguments.CurrentPosition > 1) {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition) {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ WriteValue(argument, writer);
+ }
+ if ((arguments.Count > 0) && (assignments.Count > 0)) writer.WriteString(", ");
+ while (assignments.MoveNext()) {
+ XPathNavigator assignment = assignments.Current;
+ if (assignments.CurrentPosition > 1) {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition) {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ writer.WriteString((string) assignment.Evaluate(assignmentNameExpression));
+ writer.WriteString(" = ");
+ WriteValue(assignment, writer);
+
+ }
+ writer.WriteString(")");
+ }
+
+ writer.WriteString("]");
+ writer.WriteLine();
+ }
+
+ }
+
+ private void WriteValue (XPathNavigator parent, SyntaxWriter writer) {
+
+ XPathNavigator type = parent.SelectSingleNode(attributeTypeExpression);
+ XPathNavigator value = parent.SelectSingleNode(valueExpression);
+ if (value == null) Console.WriteLine("null value");
+
+ switch (value.LocalName) {
+ case "nullValue":
+ writer.WriteKeyword("null");
+ break;
+ case "typeValue":
+ writer.WriteKeyword("typeof");
+ writer.WriteString("(");
+ WriteTypeReference(value.SelectSingleNode(typeExpression), writer);
+ writer.WriteString(")");
+ break;
+ case "enumValue":
+ XPathNodeIterator fields = value.SelectChildren(XPathNodeType.Element);
+ while (fields.MoveNext()) {
+ string name = fields.Current.GetAttribute("name", String.Empty);
+ if (fields.CurrentPosition > 1) writer.WriteString("|");
+ WriteTypeReference(type, writer);
+ writer.WriteString(".");
+ writer.WriteString(name);
+ }
+ break;
+ case "value":
+ string text = value.Value;
+ string typeId = type.GetAttribute("api", String.Empty);
+ switch (typeId) {
+ case "T:System.String":
+ writer.WriteString("\"");
+ writer.WriteString(text);
+ writer.WriteString("\"");
+ break;
+ case "T:System.Boolean":
+ bool bool_value = Convert.ToBoolean(text);
+ if (bool_value) {
+ writer.WriteKeyword("true");
+ } else {
+ writer.WriteKeyword("false");
+ }
+ break;
+ case "T:System.Char":
+ writer.WriteString("'");
+ writer.WriteString(text);
+ writer.WriteString("'");
+ break;
+ }
+ break;
+ }
+
+ }
+
+ // Interfaces
+
+ private void WriteImplementedInterfaces (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator implements = reflection.Select(apiImplementedInterfacesExpression);
+
+ if (implements.Count == 0) return;
+ writer.WriteString(" : ");
+ while (implements.MoveNext()) {
+ XPathNavigator implement = implements.Current;
+ WriteTypeReference(implement, writer);
+ if (implements.CurrentPosition < implements.Count) {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition) {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ }
+
+ }
+
+ private void WriteBaseClassAndImplementedInterfaces (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNavigator baseClass = reflection.SelectSingleNode(apiBaseClassExpression);
+ XPathNodeIterator implements = reflection.Select(apiImplementedInterfacesExpression);
+
+ bool hasBaseClass = (baseClass != null) && !((bool) baseClass.Evaluate(typeIsObjectExpression));
+ bool hasImplementedInterfaces = (implements.Count > 0);
+
+ if (hasBaseClass || hasImplementedInterfaces) {
+
+ writer.WriteString(" : ");
+ if (hasBaseClass) {
+ WriteTypeReference(baseClass, writer);
+ if (hasImplementedInterfaces)
+ {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition)
+ {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ }
+
+ while (implements.MoveNext()) {
+ XPathNavigator implement = implements.Current;
+ WriteTypeReference(implement, writer);
+ if (implements.CurrentPosition < implements.Count) {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition) {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ }
+
+ }
+
+ }
+
+ // Generics
+
+ private void WriteGenericTemplates (XPathNavigator reflection, SyntaxWriter writer) {
+
+ WriteGenericTemplates(reflection, writer, false);
+ }
+
+ private void WriteGenericTemplates(XPathNavigator reflection, SyntaxWriter writer, bool writeVariance)
+ {
+ XPathNodeIterator templates = (XPathNodeIterator)reflection.Evaluate(apiTemplatesExpression);
+
+ if (templates.Count == 0) return;
+ writer.WriteString("<");
+ while (templates.MoveNext())
+ {
+ XPathNavigator template = templates.Current;
+ if (writeVariance)
+ {
+ bool contravariant = (bool)template.Evaluate(templateIsContravariantExpression);
+ bool covariant = (bool)template.Evaluate(templateIsCovariantExpression);
+
+ if (contravariant)
+ {
+ writer.WriteKeyword("in");
+ writer.WriteString(" ");
+ }
+ if (covariant)
+ {
+ writer.WriteKeyword("out");
+ writer.WriteString(" ");
+ }
+ }
+ string name = template.GetAttribute("name", String.Empty);
+ writer.WriteString(name);
+ if (templates.CurrentPosition < templates.Count) writer.WriteString(", ");
+ }
+ writer.WriteString(">");
+
+ }
+
+ private void WriteGenericTemplateConstraints (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator templates = reflection.Select(apiTemplatesExpression);
+
+ if (templates.Count == 0) return;
+
+ writer.WriteLine();
+ foreach (XPathNavigator template in templates) {
+
+ bool constrained = (bool) template.Evaluate(templateIsConstrainedExpression);
+ if (constrained) {
+ string name = (string) template.Evaluate(templateNameExpression);
+
+ writer.WriteKeyword("where");
+ writer.WriteString(" ");
+ writer.WriteString(name);
+ writer.WriteString(" : ");
+ } else {
+ continue;
+ }
+
+ bool value = (bool) template.Evaluate(templateIsValueTypeExpression);
+ bool reference = (bool) template.Evaluate(templateIsReferenceTypeExpression);
+ bool constructor = (bool) template.Evaluate(templateIsConstructableExpression);
+ XPathNodeIterator constraints = template.Select(templateConstraintsExpression);
+
+ // keep track of whether there is a previous constraint, so we know whether to put a comma
+ bool previous = false;
+
+ if (value) {
+ if (previous) writer.WriteString(", ");
+ writer.WriteKeyword("struct");
+ previous = true;
+ }
+
+ if (reference) {
+ if (previous) writer.WriteString(", ");
+ writer.WriteKeyword("class");
+ previous = true;
+ }
+
+ if (constructor) {
+ if (previous) writer.WriteString(", ");
+ writer.WriteKeyword("new");
+ writer.WriteString("()");
+ previous = true;
+ }
+
+ foreach (XPathNavigator constraint in constraints) {
+ if (previous) writer.WriteString(", ");
+ WriteTypeReference(constraint, writer);
+ previous = true;
+ }
+ writer.WriteLine();
+ }
+
+ }
+
+ // Parameters
+
+ private void WriteMethodParameters (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+
+ writer.WriteString("(");
+ if (parameters.Count > 0) {
+ writer.WriteLine();
+ WriteParameters(parameters, reflection, writer);
+ }
+ writer.WriteString(")");
+
+ }
+
+ private void WritePropertyParameters (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+
+ if (parameters.Count == 0) return;
+
+ writer.WriteString("[");
+ writer.WriteLine();
+ WriteParameters(parameters, reflection, writer);
+ writer.WriteString("]");
+
+ }
+
+
+ private void WriteParameters (XPathNodeIterator parameters, XPathNavigator reflection, SyntaxWriter writer) {
+
+ bool isExtension = (bool) reflection.Evaluate(apiIsExtensionMethod);
+
+
+ while (parameters.MoveNext()) {
+ XPathNavigator parameter = parameters.Current;
+
+ string name = (string) parameter.Evaluate(parameterNameExpression);
+ XPathNavigator type = parameter.SelectSingleNode(parameterTypeExpression);
+ bool isIn = (bool) parameter.Evaluate(parameterIsInExpression);
+ bool isOut = (bool) parameter.Evaluate(parameterIsOutExpression);
+ bool isRef = (bool) parameter.Evaluate(parameterIsRefExpression);
+ bool isParamArray = (bool) parameter.Evaluate(parameterIsParamArrayExpression);
+
+ writer.WriteString("\t");
+
+ if (isExtension && parameters.CurrentPosition == 1) {
+ writer.WriteKeyword("this");
+ writer.WriteString(" ");
+ }
+
+ if (isRef) {
+ if (isOut) {
+ writer.WriteKeyword("out");
+ } else {
+ writer.WriteKeyword("ref");
+ }
+ writer.WriteString(" ");
+ }
+
+ if (isParamArray) {
+ writer.WriteKeyword("params");
+ writer.WriteString(" ");
+ }
+
+ WriteTypeReference(type, writer);
+ writer.WriteString(" ");
+ writer.WriteParameter(name);
+
+ if (parameters.CurrentPosition < parameters.Count) writer.WriteString(",");
+ writer.WriteLine();
+ }
+
+ }
+
+ // Return Value
+
+ private void WriteReturnValue (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNavigator type = reflection.SelectSingleNode(apiReturnTypeExpression);
+
+ if (type == null) {
+ writer.WriteKeyword("void");
+ } else {
+ WriteTypeReference(type, writer);
+ }
+ }
+
+ // References
+
+ private void WriteTypeReference (XPathNavigator reference, SyntaxWriter writer) {
+ switch (reference.LocalName) {
+ case "arrayOf":
+ int rank = Convert.ToInt32( reference.GetAttribute("rank",String.Empty) );
+ XPathNavigator element = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(element, writer);
+ writer.WriteString("[");
+ for (int i=1; i<rank; i++) { writer.WriteString(","); }
+ writer.WriteString("]");
+ break;
+ case "pointerTo":
+ XPathNavigator pointee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(pointee, writer);
+ writer.WriteString("*");
+ break;
+ case "referenceTo":
+ XPathNavigator referee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(referee, writer);
+ break;
+ case "type":
+ string id = reference.GetAttribute("api", String.Empty);
+ WriteNormalTypeReference(id, writer);
+ XPathNodeIterator typeModifiers = reference.Select(typeModifiersExpression);
+ while (typeModifiers.MoveNext()) {
+ WriteTypeReference(typeModifiers.Current, writer);
+ }
+ break;
+ case "template":
+ string name = reference.GetAttribute("name", String.Empty);
+ writer.WriteString(name);
+ XPathNodeIterator modifiers = reference.Select(typeModifiersExpression);
+ while (modifiers.MoveNext()) {
+ WriteTypeReference(modifiers.Current, writer);
+ }
+ break;
+ case "specialization":
+ writer.WriteString("<");
+ XPathNodeIterator arguments = reference.Select(specializationArgumentsExpression);
+ while (arguments.MoveNext()) {
+ if (arguments.CurrentPosition > 1) writer.WriteString(", ");
+ WriteTypeReference(arguments.Current, writer);
+ }
+ writer.WriteString(">");
+ break;
+ }
+ }
+
+ private void WriteNormalTypeReference (string api, SyntaxWriter writer) {
+ switch (api) {
+ case "T:System.Void":
+ writer.WriteReferenceLink(api, "void");
+ break;
+ case "T:System.String":
+ writer.WriteReferenceLink(api, "string");
+ break;
+ case "T:System.Boolean":
+ writer.WriteReferenceLink(api, "bool");
+ break;
+ case "T:System.Byte":
+ writer.WriteReferenceLink(api, "byte");
+ break;
+ case "T:System.SByte":
+ writer.WriteReferenceLink(api, "sbyte");
+ break;
+ case "T:System.Char":
+ writer.WriteReferenceLink(api, "char");
+ break;
+ case "T:System.Int16":
+ writer.WriteReferenceLink(api, "short");
+ break;
+ case "T:System.Int32":
+ writer.WriteReferenceLink(api, "int");
+ break;
+ case "T:System.Int64":
+ writer.WriteReferenceLink(api, "long");
+ break;
+ case "T:System.UInt16":
+ writer.WriteReferenceLink(api, "ushort");
+ break;
+ case "T:System.UInt32":
+ writer.WriteReferenceLink(api, "uint");
+ break;
+ case "T:System.UInt64":
+ writer.WriteReferenceLink(api, "ulong");
+ break;
+ case "T:System.Single":
+ writer.WriteReferenceLink(api, "float");
+ break;
+ case "T:System.Double":
+ writer.WriteReferenceLink(api, "double");
+ break;
+ case "T:System.Decimal":
+ writer.WriteReferenceLink(api, "decimal");
+ break;
+ default:
+ writer.WriteReferenceLink(api);
+ break;
+ }
+ }
+
+ private void WriteMemberReference (XPathNavigator member, SyntaxWriter writer) {
+ string api = member.GetAttribute("api", String.Empty);
+ writer.WriteReferenceLink(api);
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/FSharpDeclarationSyntax.cs b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/FSharpDeclarationSyntax.cs
new file mode 100644
index 0000000..7f10807
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/FSharpDeclarationSyntax.cs
@@ -0,0 +1,988 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Xml.XPath;
+
+
+namespace Microsoft.Ddue.Tools
+{
+
+ public class FSharpDeclarationSyntaxGenerator : SyntaxGeneratorTemplate
+ {
+
+ public FSharpDeclarationSyntaxGenerator(XPathNavigator configuration)
+ : base(configuration)
+ {
+ if (String.IsNullOrEmpty(Language)) Language = "FSharp";
+ }
+
+ // namespace: done
+ public override void WriteNamespaceSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ string name = reflection.Evaluate(apiNameExpression).ToString();
+
+ writer.WriteKeyword("namespace");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ }
+
+ public override void WriteClassSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ WriteDotNetObject(reflection, writer, "class");
+ }
+
+ // TODO: Use apiContainingTypeSubgroupExpression instead of passing in class, struct, interface
+ public override void WriteStructureSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ WriteDotNetObject(reflection, writer, "struct");
+ }
+
+ public override void WriteInterfaceSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ WriteDotNetObject(reflection, writer, "interface");
+ }
+
+
+ public override void WriteDelegateSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ bool isSerializable = (bool)reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+
+ WriteAttributes(reflection, writer);
+
+ writer.WriteKeyword("type");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ writer.WriteString(" = ");
+ writer.WriteLine();
+ writer.WriteString(" ");
+ writer.WriteKeyword("delegate");
+ writer.WriteString(" ");
+ writer.WriteKeyword("of");
+ writer.WriteString(" ");
+
+ WriteParameters(reflection, writer);
+
+ writer.WriteKeyword("->");
+ writer.WriteString(" ");
+ WriteReturnValue(reflection, writer);
+
+ }
+
+ public override void WriteEnumerationSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ bool isSerializable = (bool)reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+ WriteAttributes(reflection, writer);
+ writer.WriteKeyword("type");
+ writer.WriteString(" ");
+ WriteVisibility(reflection, writer);
+ writer.WriteIdentifier(name);
+ }
+
+ public override void WriteConstructorSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ string name = (string)reflection.Evaluate(apiContainingTypeNameExpression);
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+
+ WriteAttributes(reflection, writer);
+
+ writer.WriteKeyword("new");
+ writer.WriteString(" : ");
+ WriteParameters(reflection, writer);
+ writer.WriteKeyword("->");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+
+ }
+
+ public override void WriteNormalMethodSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ bool isOverride = (bool)reflection.Evaluate(apiIsOverrideExpression);
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+ bool isVirtual = (bool)reflection.Evaluate(apiIsVirtualExpression) && !(bool)reflection.Evaluate(apiIsAbstractProcedureExpression);
+ int iterations = isVirtual ? 2 : 1;
+
+ for (int i = 0; i < iterations; i++)
+ {
+
+ WriteAttributes(reflection, writer);
+
+ WriteVisibility(reflection, writer);
+
+ if (isStatic)
+ {
+ writer.WriteKeyword("static");
+ writer.WriteString(" ");
+ }
+
+ if (isVirtual)
+ if (i == 0)
+ {
+ writer.WriteKeyword("abstract");
+ writer.WriteString(" ");
+ }
+ else
+ {
+ writer.WriteKeyword("override");
+ writer.WriteString(" ");
+ }
+ else
+ {
+ WriteMemberKeyword(reflection, writer);
+ }
+
+ writer.WriteIdentifier(name);
+ writer.WriteString(" : ");
+ WriteParameters(reflection, writer);
+ writer.WriteKeyword("->");
+ writer.WriteString(" ");
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ WriteGenericTemplateConstraints(reflection, writer);
+
+ if (i == 0)
+ writer.WriteLine();
+ }
+ }
+
+ public override void WriteOperatorSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ string identifier;
+
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+
+ switch (name)
+ {
+ // unary math operators
+ case "UnaryPlus":
+ identifier = "+";
+ break;
+ case "UnaryNegation":
+ identifier = "-";
+ break;
+ case "Increment":
+ identifier = "++";
+ break;
+ case "Decrement":
+ identifier = "--";
+ break;
+ // unary logical operators
+ case "LogicalNot":
+ identifier = "not";
+ break;
+ case "True":
+ identifier = "true";
+ break;
+ case "False":
+ identifier = "false";
+ break;
+ // binary comparison operators
+ case "Equality":
+ identifier = "=";
+ break;
+ case "Inequality":
+ identifier = "<>";
+ break;
+ case "LessThan":
+ identifier = "<";
+ break;
+ case "GreaterThan":
+ identifier = ">";
+ break;
+ case "LessThanOrEqual":
+ identifier = "<=";
+ break;
+ case "GreaterThanOrEqual":
+ identifier = ">=";
+ break;
+ // binary math operators
+ case "Addition":
+ identifier = "+";
+ break;
+ case "Subtraction":
+ identifier = "-";
+ break;
+ case "Multiply":
+ identifier = "*";
+ break;
+ case "Division":
+ identifier = "/";
+ break;
+ case "Modulus":
+ identifier = "%";
+ break;
+ // binary logical operators
+ case "BitwiseAnd":
+ identifier = "&&&";
+ break;
+ case "BitwiseOr":
+ identifier = "|||";
+ break;
+ case "ExclusiveOr":
+ identifier = "^^^";
+ break;
+ // bit-array operators
+ case "OnesComplement":
+ identifier = null; // No F# equiv.
+ break;
+ case "LeftShift":
+ identifier = "<<<";
+ break;
+ case "RightShift":
+ identifier = ">>>";
+ break;
+ // unrecognized operator
+ default:
+ identifier = null;
+ break;
+ }
+ if (identifier == null)
+ {
+ writer.WriteMessage("UnsupportedOperator_" + Language);
+ }
+ else
+ {
+ if (isStatic)
+ {
+ writer.WriteKeyword("static");
+ writer.WriteString(" ");
+ }
+
+ writer.WriteKeyword("let");
+ writer.WriteString(" ");
+ writer.WriteKeyword("inline");
+ writer.WriteKeyword(" ");
+
+ writer.WriteString("(");
+ writer.WriteIdentifier(identifier);
+ writer.WriteString(")");
+
+ WriteParameters(reflection, writer);
+ writer.WriteString(" : ");
+ WriteReturnValue(reflection, writer);
+
+ }
+ }
+
+ public override void WriteCastSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ writer.WriteMessage("UnsupportedCast_" + Language);
+ }
+
+ // DONE
+ public override void WritePropertySyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ bool isGettable = (bool)reflection.Evaluate(apiIsReadPropertyExpression);
+ bool isSettable = (bool)reflection.Evaluate(apiIsWritePropertyExpression);
+
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+ bool isVirtual = (bool)reflection.Evaluate(apiIsVirtualExpression) && !(bool)reflection.Evaluate(apiIsAbstractProcedureExpression);
+ int iterations = isVirtual ? 2 : 1;
+
+ for (int i = 0; i < iterations; i++)
+ {
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+
+ if (isStatic)
+ {
+ writer.WriteKeyword("static");
+ writer.WriteString(" ");
+ }
+
+ if (isVirtual)
+ if (i == 0)
+ {
+ writer.WriteKeyword("abstract");
+ writer.WriteString(" ");
+ }
+ else
+ {
+ writer.WriteKeyword("override");
+ writer.WriteString(" ");
+ }
+ else
+ {
+ WriteMemberKeyword(reflection, writer);
+ }
+
+ writer.WriteIdentifier(name);
+ writer.WriteString(" : ");
+ WriteReturnValue(reflection, writer);
+
+ if (isSettable)
+ {
+ writer.WriteString(" ");
+ writer.WriteKeyword("with");
+ writer.WriteString(" ");
+
+ string getVisibility = (string)reflection.Evaluate(apiGetVisibilityExpression);
+ if (!String.IsNullOrEmpty(getVisibility))
+ {
+ WriteVisibility(getVisibility, writer);
+ }
+
+ writer.WriteKeyword("get");
+ writer.WriteString(", ");
+
+ string setVisibility = (string)reflection.Evaluate(apiSetVisibilityExpression);
+ if (!String.IsNullOrEmpty(setVisibility))
+ {
+ WriteVisibility(setVisibility, writer);
+ }
+
+ writer.WriteKeyword("set");
+ }
+ if (i == 0)
+ writer.WriteLine();
+ }
+ }
+
+ public override void WriteEventSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ XPathNavigator handler = reflection.SelectSingleNode(apiHandlerOfEventExpression);
+ XPathNavigator args = reflection.SelectSingleNode(apiEventArgsExpression);
+ bool isVirtual = (bool)reflection.Evaluate(apiIsVirtualExpression) && !(bool)reflection.Evaluate(apiIsAbstractProcedureExpression);
+ int iterations = isVirtual ? 2 : 1;
+
+ for (int i = 0; i < iterations; i++)
+ {
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ if (isVirtual)
+ if (i == 0)
+ {
+ writer.WriteKeyword("abstract");
+ writer.WriteString(" ");
+ }
+ else
+ {
+ writer.WriteKeyword("override");
+ writer.WriteString(" ");
+ }
+ else
+ {
+ WriteMemberKeyword(reflection, writer);
+ }
+ writer.WriteIdentifier(name);
+ writer.WriteString(" : ");
+ writer.WriteReferenceLink("T:Microsoft.FSharp.Control.IEvent");
+
+ writer.WriteString("<");
+ WriteTypeReference(handler, writer);
+ writer.WriteString(",");
+ writer.WriteLine();
+ writer.WriteString(" ");
+ if (args == null)
+ {
+ writer.WriteReferenceLink("T:System.EventArgs");
+ }
+ else
+ {
+ WriteTypeReference(args, writer);
+ }
+ writer.WriteString(">");
+ if (i == 0)
+ writer.WriteLine();
+ }
+ }
+
+
+ public override void WriteFieldSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+ bool isLiteral = (bool)reflection.Evaluate(apiIsLiteralFieldExpression);
+ bool isInitOnly = (bool)reflection.Evaluate(apiIsInitOnlyFieldExpression);
+ bool isSerialized = (bool)reflection.Evaluate(apiIsSerializedFieldExpression);
+
+ if (!isSerialized) WriteAttribute("T:System.NonSerializedAttribute", writer);
+ WriteAttributes(reflection, writer);
+
+
+ if (isStatic)
+ {
+ writer.WriteKeyword("static");
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword("val");
+ writer.WriteString(" ");
+
+ if (!isInitOnly)
+ {
+ writer.WriteKeyword("mutable");
+ writer.WriteString(" ");
+ }
+
+ WriteVisibility(reflection, writer);
+
+ writer.WriteIdentifier(name);
+
+ writer.WriteString(": ");
+ WriteReturnValue(reflection, writer);
+
+ }
+
+
+ private void WriteDotNetObject(XPathNavigator reflection, SyntaxWriter writer,
+ string kind)
+ {
+ string name = reflection.Evaluate(apiNameExpression).ToString();
+ bool isSerializable = (bool)reflection.Evaluate(apiIsSerializableTypeExpression);
+ XPathNodeIterator implements = reflection.Select(apiImplementedInterfacesExpression);
+ XPathNavigator baseClass = reflection.SelectSingleNode(apiBaseClassExpression);
+ bool hasBaseClass = (baseClass != null) && !((bool)baseClass.Evaluate(typeIsObjectExpression));
+
+ // CLR considers interfaces abstract.
+ bool isAbstract = (bool)reflection.Evaluate(apiIsAbstractTypeExpression) && kind != "interface";
+ bool isSealed = (bool)reflection.Evaluate(apiIsSealedTypeExpression);
+
+ if (isAbstract)
+ WriteAttribute("T:Microsoft.FSharp.Core.AbstractClassAttribute", writer);
+ if (isSealed)
+ WriteAttribute("T:Microsoft.FSharp.Core.SealedAttribute", writer);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+ WriteAttributes(reflection, writer);
+
+ writer.WriteKeyword("type");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteGenericTemplates(reflection, writer);
+ writer.WriteString(" = ");
+
+ if (hasBaseClass || implements.Count != 0)
+ {
+ writer.WriteLine();
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword(kind);
+
+ if (hasBaseClass || implements.Count != 0)
+ {
+ writer.WriteLine();
+ }
+
+ if (hasBaseClass)
+ {
+ writer.WriteString(" ");
+ writer.WriteKeyword("inherit");
+ writer.WriteString(" ");
+ WriteTypeReference(baseClass, writer);
+ writer.WriteLine();
+ }
+
+
+ while (implements.MoveNext())
+ {
+ XPathNavigator implement = implements.Current;
+ writer.WriteString(" ");
+ writer.WriteKeyword("interface");
+ writer.WriteString(" ");
+ WriteTypeReference(implement, writer);
+ writer.WriteLine();
+ }
+
+ if (hasBaseClass || implements.Count != 0)
+ {
+ writer.WriteString(" ");
+ }
+ else
+ {
+ writer.WriteString(" ");
+ }
+
+ writer.WriteKeyword("end");
+
+ }
+
+ // Visibility
+
+ private void WriteVisibility(XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ string visibility = reflection.Evaluate(apiVisibilityExpression).ToString();
+ WriteVisibility(visibility, writer);
+ }
+
+
+ private Dictionary<string, string> visibilityDictionary = new Dictionary<string, string>()
+ {
+ { "public", null }, // Default in F#, so unnecessary.
+ { "family", null }, // Not supported in F#, section 8.8 in F# spec.
+ { "family or assembly", null }, // Not supported in F#, section 8.8 in F# spec.
+ { "family and assembly", null }, // Not supported in F#, section 8.8 in F# spec.
+ { "assembly", "internal" },
+ { "private", "private" },
+ };
+
+ // DONE
+ private void WriteVisibility(string visibility, SyntaxWriter writer)
+ {
+
+ if(visibilityDictionary.ContainsKey(visibility) && visibilityDictionary[visibility] != null)
+ {
+ writer.WriteKeyword(visibilityDictionary[visibility]);
+ writer.WriteString(" ");
+ }
+
+ }
+
+ // Write member | abstract | override
+ private void WriteMemberKeyword(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ bool isOverride = (bool)reflection.Evaluate(apiIsOverrideExpression);
+ bool isAbstract = (bool)reflection.Evaluate(apiIsAbstractProcedureExpression);
+
+ if (isOverride)
+ {
+ writer.WriteKeyword("override");
+ }
+ else if (isAbstract)
+ {
+ writer.WriteKeyword("abstract");
+ }
+ else
+ {
+ writer.WriteKeyword("member");
+ }
+ writer.WriteString(" ");
+
+ return;
+ }
+
+ // Attributes
+
+ private void WriteAttribute(string reference, SyntaxWriter writer)
+ {
+ writer.WriteString("[<");
+ writer.WriteReferenceLink(reference);
+ writer.WriteString(">]");
+ writer.WriteLine();
+ }
+
+
+ // Initial version
+ private void WriteAttributes(XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ XPathNodeIterator attributes = (XPathNodeIterator)reflection.Evaluate(apiAttributesExpression);
+
+ foreach (XPathNavigator attribute in attributes)
+ {
+
+ XPathNavigator type = attribute.SelectSingleNode(attributeTypeExpression);
+ if (type.GetAttribute("api", String.Empty) == "T:System.Runtime.CompilerServices.ExtensionAttribute") continue;
+
+ writer.WriteString("[<");
+ WriteTypeReference(type, writer);
+
+ XPathNodeIterator arguments = (XPathNodeIterator)attribute.Select(attributeArgumentsExpression);
+ XPathNodeIterator assignments = (XPathNodeIterator)attribute.Select(attributeAssignmentsExpression);
+
+ if ((arguments.Count > 0) || (assignments.Count > 0))
+ {
+ writer.WriteString("(");
+ while (arguments.MoveNext())
+ {
+ XPathNavigator argument = arguments.Current;
+ if (arguments.CurrentPosition > 1)
+ {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition)
+ {
+ writer.WriteLine();
+ writer.WriteString(" ");
+ }
+ }
+ WriteValue(argument, writer);
+ }
+ if ((arguments.Count > 0) && (assignments.Count > 0)) writer.WriteString(", ");
+ while (assignments.MoveNext())
+ {
+ XPathNavigator assignment = assignments.Current;
+ if (assignments.CurrentPosition > 1)
+ {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition)
+ {
+ writer.WriteLine();
+ writer.WriteString(" ");
+ }
+ }
+ writer.WriteString((string)assignment.Evaluate(assignmentNameExpression));
+ writer.WriteString(" = ");
+ WriteValue(assignment, writer);
+
+ }
+ writer.WriteString(")");
+ }
+
+ writer.WriteString(">]");
+ writer.WriteLine();
+ }
+
+ }
+
+ private void WriteValue(XPathNavigator parent, SyntaxWriter writer)
+ {
+
+ XPathNavigator type = parent.SelectSingleNode(attributeTypeExpression);
+ XPathNavigator value = parent.SelectSingleNode(valueExpression);
+ if (value == null) Console.WriteLine("null value");
+
+ switch (value.LocalName)
+ {
+ case "nullValue":
+ writer.WriteKeyword("null");
+ break;
+ case "typeValue":
+ writer.WriteKeyword("typeof");
+ writer.WriteString("(");
+ WriteTypeReference(value.SelectSingleNode(typeExpression), writer);
+ writer.WriteString(")");
+ break;
+ case "enumValue":
+ XPathNodeIterator fields = value.SelectChildren(XPathNodeType.Element);
+ while (fields.MoveNext())
+ {
+ string name = fields.Current.GetAttribute("name", String.Empty);
+ if (fields.CurrentPosition > 1) writer.WriteString("|");
+ WriteTypeReference(type, writer);
+ writer.WriteString(".");
+ writer.WriteString(name);
+ }
+ break;
+ case "value":
+ string text = value.Value;
+ string typeId = type.GetAttribute("api", String.Empty);
+ switch (typeId)
+ {
+ case "T:System.String":
+ writer.WriteString("\"");
+ writer.WriteString(text);
+ writer.WriteString("\"");
+ break;
+ case "T:System.Boolean":
+ bool bool_value = Convert.ToBoolean(text);
+ if (bool_value)
+ {
+ writer.WriteKeyword("true");
+ }
+ else
+ {
+ writer.WriteKeyword("false");
+ }
+ break;
+ case "T:System.Char":
+ writer.WriteString("'");
+ writer.WriteString(text);
+ writer.WriteString("'");
+ break;
+ }
+ break;
+ }
+ }
+
+
+ // Generics
+
+ private void WriteGenericTemplates(XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ XPathNodeIterator templates = (XPathNodeIterator)reflection.Evaluate(apiTemplatesExpression);
+
+ if (templates.Count == 0) return;
+ writer.WriteString("<");
+ while (templates.MoveNext())
+ {
+ XPathNavigator template = templates.Current;
+ string name = template.GetAttribute("name", String.Empty);
+ writer.WriteString("'");
+ writer.WriteString(name);
+ if (templates.CurrentPosition < templates.Count) writer.WriteString(", ");
+ }
+ WriteGenericTemplateConstraints(reflection, writer);
+ writer.WriteString(">");
+ }
+
+ private void WriteGenericTemplateConstraints(XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ XPathNodeIterator templates = reflection.Select(apiTemplatesExpression);
+
+ if (templates.Count == 0) return;
+
+ foreach (XPathNavigator template in templates)
+ {
+
+ bool constrained = (bool)template.Evaluate(templateIsConstrainedExpression);
+ if (constrained)
+ {
+ string name = (string)template.Evaluate(templateNameExpression);
+
+ writer.WriteString(" ");
+ writer.WriteKeyword("when");
+ writer.WriteString(" '");
+ writer.WriteString(name);
+ writer.WriteString(" : ");
+ }
+ else
+ {
+ continue;
+ }
+
+ bool value = (bool)template.Evaluate(templateIsValueTypeExpression);
+ bool reference = (bool)template.Evaluate(templateIsReferenceTypeExpression);
+ bool constructor = (bool)template.Evaluate(templateIsConstructableExpression);
+ XPathNodeIterator constraints = template.Select(templateConstraintsExpression);
+
+ // keep track of whether there is a previous constraint, so we know whether to put a comma
+ bool previous = false;
+
+ if (value)
+ {
+ if (previous) writer.WriteString(", ");
+ writer.WriteKeyword("struct");
+ previous = true;
+ }
+
+ if (reference)
+ {
+ if (previous) writer.WriteString(", ");
+ writer.WriteKeyword("not struct");
+ previous = true;
+ }
+
+ if (constructor)
+ {
+ if (previous) writer.WriteString(", ");
+ writer.WriteKeyword("new");
+ writer.WriteString("()");
+ previous = true;
+ }
+
+ foreach (XPathNavigator constraint in constraints)
+ {
+ if (previous) writer.WriteString(" and ");
+ WriteTypeReference(constraint, writer);
+ previous = true;
+ }
+
+ }
+
+ }
+
+ // Parameters
+
+ private void WriteParameters(XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+
+ if (parameters.Count > 0)
+ {
+ WriteParameters(parameters, reflection, writer);
+ }
+ else
+ {
+ writer.WriteKeyword("unit");
+ writer.WriteString(" ");
+ }
+ return;
+ }
+
+
+
+ private void WriteParameters(XPathNodeIterator parameters, XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ bool isExtension = (bool)reflection.Evaluate(apiIsExtensionMethod);
+ writer.WriteLine();
+
+
+ while (parameters.MoveNext())
+ {
+ XPathNavigator parameter = parameters.Current;
+
+ string name = (string)parameter.Evaluate(parameterNameExpression);
+ bool isOut = (bool)parameter.Evaluate(parameterIsOutExpression);
+ bool isRef = (bool)parameter.Evaluate(parameterIsRefExpression);
+ XPathNavigator type = parameter.SelectSingleNode(parameterTypeExpression);
+ writer.WriteString(" ");
+ writer.WriteParameter(name);
+ writer.WriteString(":");
+ WriteTypeReference(type, writer);
+ if (isOut || isRef)
+ {
+ writer.WriteString(" ");
+ writer.WriteKeyword("byref");
+ }
+ if (parameters.CurrentPosition != parameters.Count)
+ {
+ writer.WriteString(" * ");
+ writer.WriteLine();
+ }
+ else
+ {
+ writer.WriteString(" ");
+ }
+ }
+
+ }
+
+ // Return Value
+
+ private void WriteReturnValue(XPathNavigator reflection, SyntaxWriter writer)
+ {
+
+ XPathNavigator type = reflection.SelectSingleNode(apiReturnTypeExpression);
+
+ if (type == null)
+ {
+ writer.WriteKeyword("unit");
+ }
+ else
+ {
+ WriteTypeReference(type, writer);
+ }
+ }
+
+ // References
+
+ private void WriteTypeReference(XPathNavigator reference, SyntaxWriter writer)
+ {
+ switch (reference.LocalName)
+ {
+ case "arrayOf":
+ int rank = Convert.ToInt32(reference.GetAttribute("rank", String.Empty));
+ XPathNavigator element = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(element, writer);
+ writer.WriteString("[");
+ for (int i = 1; i < rank; i++) { writer.WriteString(","); }
+ writer.WriteString("]");
+ break;
+ case "pointerTo":
+ XPathNavigator pointee = reference.SelectSingleNode(typeExpression);
+ writer.WriteKeyword("nativeptr");
+ writer.WriteString("<");
+ WriteTypeReference(pointee, writer);
+ writer.WriteString(">");
+ break;
+ case "referenceTo":
+ XPathNavigator referee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(referee, writer);
+ break;
+ case "type":
+ string id = reference.GetAttribute("api", String.Empty);
+ WriteNormalTypeReference(id, writer);
+ XPathNodeIterator typeModifiers = reference.Select(typeModifiersExpression);
+ while (typeModifiers.MoveNext())
+ {
+ WriteTypeReference(typeModifiers.Current, writer);
+ }
+ break;
+ case "template":
+ string name = reference.GetAttribute("name", String.Empty);
+ writer.WriteString("'");
+ writer.WriteString(name);
+ XPathNodeIterator modifiers = reference.Select(typeModifiersExpression);
+ while (modifiers.MoveNext())
+ {
+ WriteTypeReference(modifiers.Current, writer);
+ }
+ break;
+ case "specialization":
+ writer.WriteString("<");
+ XPathNodeIterator arguments = reference.Select(specializationArgumentsExpression);
+ while (arguments.MoveNext())
+ {
+ if (arguments.CurrentPosition > 1) writer.WriteString(", ");
+ WriteTypeReference(arguments.Current, writer);
+ }
+ writer.WriteString(">");
+ break;
+ }
+ }
+
+ // DONE
+ private void WriteNormalTypeReference(string api, SyntaxWriter writer)
+ {
+ switch (api)
+ {
+ case "T:System.Void":
+ writer.WriteReferenceLink(api, "unit");
+ break;
+ case "T:System.String":
+ writer.WriteReferenceLink(api, "string");
+ break;
+ case "T:System.Boolean":
+ writer.WriteReferenceLink(api, "bool");
+ break;
+ case "T:System.Byte":
+ writer.WriteReferenceLink(api, "byte");
+ break;
+ case "T:System.SByte":
+ writer.WriteReferenceLink(api, "sbyte");
+ break;
+ case "T:System.Char":
+ writer.WriteReferenceLink(api, "char");
+ break;
+ case "T:System.Int16":
+ writer.WriteReferenceLink(api, "int16");
+ break;
+ case "T:System.Int32":
+ writer.WriteReferenceLink(api, "int");
+ break;
+ case "T:System.Int64":
+ writer.WriteReferenceLink(api, "int64");
+ break;
+ case "T:System.UInt16":
+ writer.WriteReferenceLink(api, "uint16");
+ break;
+ case "T:System.UInt32":
+ writer.WriteReferenceLink(api, "uint32");
+ break;
+ case "T:System.UInt64":
+ writer.WriteReferenceLink(api, "uint64");
+ break;
+ case "T:System.Single":
+ writer.WriteReferenceLink(api, "float32");
+ break;
+ case "T:System.Double":
+ writer.WriteReferenceLink(api, "float");
+ break;
+ case "T:System.Decimal":
+ writer.WriteReferenceLink(api, "decimal");
+ break;
+ default:
+ writer.WriteReferenceLink(api);
+ break;
+ }
+ }
+
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/GlobalSuppressions.cs b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/GlobalSuppressions.cs
new file mode 100644
index 0000000..e8a0676
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/GlobalSuppressions.cs
@@ -0,0 +1,301 @@
+// 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.
+
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+//
+// To add a suppression to this file, right-click the message in the
+// Error List, point to "Suppress Message(s)", and click
+// "In Project Suppression File".
+// You do not need to add suppressions to this file manually.
+
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ddue", Scope = "namespace", Target = "Microsoft.Ddue.Tools")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.AspNetSyntaxGenerator.#containingNamespaceExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.AspNetSyntaxGenerator.#containingTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.AspNetSyntaxGenerator.#declaringTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.AspNetSyntaxGenerator.#eventHandlerTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.AspNetSyntaxGenerator.#groupExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.AspNetSyntaxGenerator.#nameExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.AspNetSyntaxGenerator.#propertyIsSettable")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.AspNetSyntaxGenerator.#propertyTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.AspNetSyntaxGenerator.#subgroupExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.AspNetSyntaxGenerator.#typeIsWebControl")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.AspNetSyntaxGenerator.#propertyIsInnerProperty")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.AspNetSyntaxGenerator.#WebControlPrefix(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1722:IdentifiersShouldNotHaveIncorrectPrefix", Scope = "type", Target = "Microsoft.Ddue.Tools.CPlusPlusDeclarationSyntaxGenerator")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.CPlusPlusDeclarationSyntaxGenerator.#WriteAttribute(System.String,System.Boolean,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.CPlusPlusDeclarationSyntaxGenerator.#WriteMemberReference(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "isExplicit", Scope = "member", Target = "Microsoft.Ddue.Tools.CPlusPlusDeclarationSyntaxGenerator.#WriteNormalMethodSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.CPlusPlusDeclarationSyntaxGenerator.#WriteNormalTypeReference(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Ddue.Tools.CPlusPlusDeclarationSyntaxGenerator.#WriteOperatorSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.CPlusPlusDeclarationSyntaxGenerator.#WritePostfixProcedureModifiers(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.CPlusPlusDeclarationSyntaxGenerator.#WritePrefixProcedureModifiers(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "typeSubgroup", Scope = "member", Target = "Microsoft.Ddue.Tools.CPlusPlusDeclarationSyntaxGenerator.#WritePropertySyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#LoadConfiguration(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#WriteSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#WriteXamlXmlnsUri(System.String,System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.CPlusPlusDeclarationSyntaxGenerator.#WriteValue(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.CSharpDeclarationSyntaxGenerator.#WriteValue(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.JSharpDeclarationSyntaxGenerator.#WriteValue(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicDeclarationSyntaxGenerator.#WriteValue(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.CPlusPlusDeclarationSyntaxGenerator.#WriteTypeReference(System.Xml.XPath.XPathNavigator,System.Boolean,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.CSharpDeclarationSyntaxGenerator.#WriteTypeReference(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.DeclarationSyntaxGeneratorTemplate.#GetTemplateParameterName(System.String,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.JScriptDeclarationSyntaxGenerator.#WriteTypeReference(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.JSharpDeclarationSyntaxGenerator.#WriteTypeReference(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#WriteTypeReference(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicDeclarationSyntaxGenerator.#WriteTypeReference(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicUsageSyntaxGenerator.#WriteTypeReference(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#WriteTypeReference(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Int32.ToString", Scope = "member", Target = "Microsoft.Ddue.Tools.CPlusPlusDeclarationSyntaxGenerator.#WriteTypeReference(System.Xml.XPath.XPathNavigator,System.Boolean,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.DeclarationSyntaxGeneratorTemplate.#GetTemplateParameterName(System.String,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#ReadFullContainingTypeName(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#ReadFullTypeName(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#WriteAttachedPropertySyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object[])", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#WriteAttachedEventSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#ParseDocument(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.StartsWith(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.DeclarationSyntaxGeneratorTemplate.#GetTemplateParameterName(System.String,System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#CreateCamelCaseName(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.StartsWith(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#WriteNormalTypeReference(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "parentIs", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_parentIsExcludedSubClass")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "parentIs", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_parentIsExcludedSubClass")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "SubClass", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_excludedSubClass")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "SubClass", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_parentIsExcludedSubClass")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "SubClass", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_parentIsExcludedSubClass")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Constructable", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#templateIsConstructableExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ctor", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_noDefaultCtorWithTypeConverter")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ctor", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_noDefaultCtor")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Param", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#parameterIsParamArrayExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Seperate", Scope = "member", Target = "Microsoft.Ddue.Tools.DeclarationSyntaxGeneratorTemplate.#SeperateTypes(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Subsubgroup", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiSubsubgroupExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "typelist", Scope = "member", Target = "Microsoft.Ddue.Tools.DeclarationSyntaxGeneratorTemplate.#SeperateTypes(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_abstract")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_excludedSubClass")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_noDefaultCtor")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_noDefaultCtorWithTypeConverter")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_abstract")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_nonXaml")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_nonXamlParent")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_notPublic")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_noXamlSyntaxForInterfaceMembers")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_parentIsExcludedSubClass")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_abstract")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_abstractType")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_nonXaml")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_nonXamlParent")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_notPublic")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_noXamlSyntaxForInterfaceMembers")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_parentIsExcludedSubClass")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_readOnly")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#structXamlSyntax_attributeUsage")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#structXamlSyntax_nonXaml")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1708:IdentifiersShouldDifferByMoreThanCase", Scope = "type", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "abstract", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_abstract")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "abstract", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_abstract")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "abstract", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_abstract")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "abstract", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_abstractType")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "attribute", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#structXamlSyntax_attributeUsage")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "class", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_abstract")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "class", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_excludedSubClass")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "class", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_noDefaultCtor")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "class", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_noDefaultCtorWithTypeConverter")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "constructor", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#constructorOverviewXamlSyntax")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "delegate", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#delegateOverviewXamlSyntax")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "enumeration", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#enumerationOverviewXamlSyntax")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "event", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_abstract")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "event", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_nonXaml")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "event", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_nonXamlParent")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "event", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_notPublic")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "event", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_noXamlSyntaxForInterfaceMembers")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "event", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_parentIsExcludedSubClass")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "excluded", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_excludedSubClass")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "field", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#fieldOverviewXamlSyntax")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "ID", Scope = "type", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "ID", Scope = "type", Target = "Microsoft.Ddue.Tools.XamlHeadingID")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "interface", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#interfaceOverviewXamlSyntax")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "method", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#methodOverviewXamlSyntax")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "no", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_noDefaultCtor")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "no", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#classXamlSyntax_noDefaultCtorWithTypeConverter")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "no", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_noXamlSyntaxForInterfaceMembers")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "no", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_noXamlSyntaxForInterfaceMembers")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "non", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_nonXaml")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "non", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_nonXamlParent")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "non", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#nonXamlAssemblyBoilerplate")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "non", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_nonXaml")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "non", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_nonXamlParent")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "non", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#structXamlSyntax_nonXaml")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "not", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_notPublic")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "not", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_notPublic")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "parent", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#eventXamlSyntax_parentIsExcludedSubClass")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "parent", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_parentIsExcludedSubClass")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "property", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_abstract")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "property", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_abstractType")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "property", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_nonXaml")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "property", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_nonXamlParent")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "property", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_notPublic")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "property", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_noXamlSyntaxForInterfaceMembers")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "property", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_parentIsExcludedSubClass")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "property", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_readOnly")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "read", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#propertyXamlSyntax_readOnly")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "struct", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#structXamlSyntax_attributeUsage")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "struct", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlBoilerplateID.#structXamlSyntax_nonXaml")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "xaml", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlHeadingID.#xamlAttributeUsageHeading")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "xaml", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlHeadingID.#xamlContentElementUsageHeading")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "xaml", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlHeadingID.#xamlObjectElementUsageHeading")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "xaml", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlHeadingID.#xamlPropertyElementUsageHeading")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "xaml", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlHeadingID.#xamlSyntaxBoilerplateHeading")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.CPlusPlusDeclarationSyntaxGenerator.#WriteVisibility(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.CSharpDeclarationSyntaxGenerator.#WriteAttribute(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.CSharpDeclarationSyntaxGenerator.#WriteMemberReference(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.CSharpDeclarationSyntaxGenerator.#WriteNormalTypeReference(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.CSharpDeclarationSyntaxGenerator.#WriteGenericTemplates(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.CSharpDeclarationSyntaxGenerator.#WriteVisibility(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.JScriptDeclarationSyntaxGenerator.#WriteAttributeList(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.JScriptDeclarationSyntaxGenerator.#WriteAccessModifier(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#excludedAncestorList")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Ddue.Tools.CSharpDeclarationSyntaxGenerator.#WriteOperatorSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "isIn", Scope = "member", Target = "Microsoft.Ddue.Tools.CSharpDeclarationSyntaxGenerator.#WriteParameters(System.Xml.XPath.XPathNodeIterator,System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "reflection", Scope = "member", Target = "Microsoft.Ddue.Tools.JScriptDeclarationSyntaxGenerator.#WriteAttributeList(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "writer", Scope = "member", Target = "Microsoft.Ddue.Tools.JScriptDeclarationSyntaxGenerator.#WriteAttributeList(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "isSerialized", Scope = "member", Target = "Microsoft.Ddue.Tools.JScriptDeclarationSyntaxGenerator.#WriteFieldSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.JScriptDeclarationSyntaxGenerator.#WriteNormalTypeReference(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.JSharpDeclarationSyntaxGenerator.#WriteAttribute(System.String,Microsoft.Ddue.Tools.SyntaxWriter,System.Boolean)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.JSharpDeclarationSyntaxGenerator.#WriteNamedNormalMethodSyntax(System.String,System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.JSharpDeclarationSyntaxGenerator.#WriteNamedNormalMethodSyntax(System.String,System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "name", Scope = "member", Target = "Microsoft.Ddue.Tools.JSharpDeclarationSyntaxGenerator.#WriteNamedNormalMethodSyntax(System.String,System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "reflection", Scope = "member", Target = "Microsoft.Ddue.Tools.JSharpDeclarationSyntaxGenerator.#WriteNamedNormalMethodSyntax(System.String,System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "writer", Scope = "member", Target = "Microsoft.Ddue.Tools.JSharpDeclarationSyntaxGenerator.#WriteNamedNormalMethodSyntax(System.String,System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.JSharpDeclarationSyntaxGenerator.#WriteNormalTypeReference(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "reflection", Scope = "member", Target = "Microsoft.Ddue.Tools.JSharpDeclarationSyntaxGenerator.#WriteParameters(System.Xml.XPath.XPathNodeIterator,System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#HasAttribute(System.Xml.XPath.XPathNavigator,System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#ReadContainingTypeName(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#ReadNamespaceName(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#WriteIndentedNewLine(Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#WriteNormalTypeReference(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#WriteParameter(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#ReadTypeName(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "reference", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#WriteParameter(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "reference", Scope = "member", Target = "Microsoft.Ddue.Tools.ScriptSharpDeclarationSyntaxGenerator.#WritePropertySyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiAncestorsExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiAttributesExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiBaseClassExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiContainingAssemblyExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiContainingNamespaceIdExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiContainingNamespaceNameExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiContainingTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiContainingTypeNameExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiContainingTypeSubgroupExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiGetVisibilityExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiGroupExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiHandlerOfEventExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiImplementedInterfacesExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiImplementedMembersExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsAbstractProcedureExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsAbstractTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsDefaultMemberExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsExplicitImplementationExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsExtensionMethod")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsFamilyMemberExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsFinalExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsGenericExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsInitOnlyFieldExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsLiteralFieldExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsOverrideExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsReadPropertyExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsSealedTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsSerializableTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsSerializedFieldExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsSpecialExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsStaticExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsUnsafeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsVirtualExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsVolatileFieldExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiIsWritePropertyExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiNameExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiOverridesMemberExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiParametersExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiReturnTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiSetVisibilityExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiSubgroupExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiSubsubgroupExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiTemplatesExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiVisibilityExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiVisibilityOfMemberExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiVisibilityOfTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#assignmentNameExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#attachedEventAdderExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#attachedEventRemoverExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#attachedPropertyGetterExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#attachedPropertySetterExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#attributeArgumentsExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#attributeAssignmentsExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#attributeTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#maxPosition")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#memberDeclaringTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#nameExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#parameterIsInExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#parameterIsOutExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#parameterIsParamArrayExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#parameterIsRefExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#parameterNameExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#parameterTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#specializationArgumentsExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#templateConstraintsExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#templateIsConstrainedExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#templateIsConstructableExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#templateIsReferenceTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#templateIsValueTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#templateNameExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#typeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#typeIdExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#typeIsObjectExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#typeModifiersExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#typeOuterTypeExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#valueExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicDeclarationSyntaxGenerator.#WriteAttribute(System.String,System.Boolean,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicDeclarationSyntaxGenerator.#WriteNormalTypeReference(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicDeclarationSyntaxGenerator.#WriteMemberReference(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicDeclarationSyntaxGenerator.#WriteOperatorSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "isIn", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicDeclarationSyntaxGenerator.#WriteParameters(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicDeclarationSyntaxGenerator.#WriteVisibility(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicUsageSyntaxGenerator.#.cctor()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicUsageSyntaxGenerator.#WriteGenericTemplates(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicUsageSyntaxGenerator.#WriteNormalTypeReference(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicUsageSyntaxGenerator.#WriteMemberReference(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicUsageSyntaxGenerator.#WriteOperatorSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicUsageSyntaxGenerator.#WriteParameters(System.Xml.XPath.XPathNodeIterator,System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "reflection", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicUsageSyntaxGenerator.#WriteParameters(System.Xml.XPath.XPathNodeIterator,System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#contentPropertyNameExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#excludedAncestorList")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#IsPrimitiveType(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1820:TestForEmptyStringsUsingStringLength", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#ObjectElementUsageForClassStruct(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "isSerializable", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#WriteClassSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "name", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#WriteClassSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#WriteNormalTypeReference(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "name", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#WriteStructureSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "propertyName", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlUsageSyntaxGenerator.#WritePropertySyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.CPlusPlusDeclarationSyntaxGenerator.#WriteVisibility(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.CSharpDeclarationSyntaxGenerator.#WriteGenericTemplates(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter,System.Boolean)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.FSharpDeclarationSyntaxGenerator.#WriteAttribute(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "isStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.FSharpDeclarationSyntaxGenerator.#WriteConstructorSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "isLiteral", Scope = "member", Target = "Microsoft.Ddue.Tools.FSharpDeclarationSyntaxGenerator.#WriteFieldSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.FSharpDeclarationSyntaxGenerator.#WriteMemberKeyword(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "isOverride", Scope = "member", Target = "Microsoft.Ddue.Tools.FSharpDeclarationSyntaxGenerator.#WriteNormalMethodSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.FSharpDeclarationSyntaxGenerator.#WriteNormalTypeReference(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Ddue.Tools.FSharpDeclarationSyntaxGenerator.#WriteOperatorSyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "isExtension", Scope = "member", Target = "Microsoft.Ddue.Tools.FSharpDeclarationSyntaxGenerator.#WriteParameters(System.Xml.XPath.XPathNodeIterator,System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "isGettable", Scope = "member", Target = "Microsoft.Ddue.Tools.FSharpDeclarationSyntaxGenerator.#WritePropertySyntax(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.FSharpDeclarationSyntaxGenerator.#WriteTypeReference(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.FSharpDeclarationSyntaxGenerator.#WriteValue(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#apiEventArgsExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#templateIsContravariantExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Microsoft.Ddue.Tools.SyntaxGeneratorTemplate.#templateIsCovariantExpression")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicDeclarationSyntaxGenerator.#WriteVisibility(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicUsageSyntaxGenerator.#WriteGenericTemplates(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.VisualBasicUsageSyntaxGenerator.#WriteGenericTemplates(System.Xml.XPath.XPathNavigator,Microsoft.Ddue.Tools.SyntaxWriter,System.Boolean)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.JScriptDeclarationSyntaxGenerator.#WriteVisibility(System.String,Microsoft.Ddue.Tools.SyntaxWriter)")]
diff --git a/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/JScriptDeclarationSyntax.cs b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/JScriptDeclarationSyntax.cs
new file mode 100644
index 0000000..27ac11d
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/JScriptDeclarationSyntax.cs
@@ -0,0 +1,475 @@
+// 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.
+
+using System;
+using System.Xml.XPath;
+
+
+namespace Microsoft.Ddue.Tools {
+
+ public class JScriptDeclarationSyntaxGenerator : SyntaxGeneratorTemplate {
+
+ public JScriptDeclarationSyntaxGenerator (XPathNavigator configuration) : base(configuration) {
+ if (String.IsNullOrEmpty(Language)) Language = "JScript";
+ }
+
+ public override void WriteNamespaceSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ string name = (string)reflection.Evaluate(apiNameExpression);
+
+ writer.WriteKeyword("package");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ }
+
+ public override void WriteClassSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupportedGeneric(reflection, writer)) return;
+
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ bool isAbstract = (bool)reflection.Evaluate(apiIsAbstractTypeExpression);
+ bool isSealed = (bool)reflection.Evaluate(apiIsSealedTypeExpression);
+
+ WriteAttributeList(reflection, writer);
+ WriteAccessModifier(reflection, writer);
+ if (isSealed) {
+ writer.WriteKeyword("final");
+ writer.WriteString(" ");
+ } else if (isAbstract) {
+ writer.WriteKeyword("abstract");
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword("class");
+ writer.WriteString(" ");
+ writer.WriteString(name);
+ WriteBaseClass(reflection, writer);
+ WriteInterfaceList(reflection, writer);
+ }
+
+ public override void WriteStructureSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupportedGeneric(reflection, writer)) return;
+ writer.WriteMessage("UnsupportedStructure_" + Language);
+ }
+
+ public override void WriteInterfaceSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupportedGeneric(reflection, writer)) return;
+
+ string name = (string)reflection.Evaluate(apiNameExpression);
+
+ WriteAttributeList(reflection, writer);
+ WriteAccessModifier(reflection, writer);
+ writer.WriteKeyword("interface");
+ writer.WriteString(" ");
+ writer.WriteString(name);
+ WriteInterfaceList("extends", reflection, writer);
+ }
+
+ public override void WriteDelegateSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupportedGeneric(reflection, writer)) return;
+ writer.WriteMessage("UnsupportedDelegate_" + Language);
+ }
+
+ public override void WriteEnumerationSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ string name = (string)reflection.Evaluate(apiNameExpression);
+
+ WriteAttributeList(reflection, writer);
+ WriteAccessModifier(reflection, writer);
+ writer.WriteKeyword("enum");
+ writer.WriteString(" ");
+ writer.WriteString(name);
+ // no JScript support for underlying types
+ }
+
+ public override void WriteConstructorSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+ if (isStatic) {
+ writer.WriteMessage("UnsupportedStaticConstructor_" + Language);
+ } else {
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+ XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
+
+ WriteAttributeList(reflection, writer);
+ WriteAccessModifier(reflection, writer);
+ writer.WriteKeyword("function");
+ writer.WriteString(" ");
+ WriteTypeReference(declaringType, writer);
+ WriteParameterList(reflection, writer);
+ }
+ }
+
+ public override void WriteNormalMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+ if (IsUnsupportedGeneric(reflection, writer)) return;
+ if (IsUnsupportedExplicit(reflection, writer)) return;
+
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ XPathNavigator returnType = reflection.SelectSingleNode(apiReturnTypeExpression);
+
+ WriteAttributeList(reflection, writer);
+ WriteProcedureModifiers(reflection, writer);
+ writer.WriteKeyword("function");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteParameterList(reflection, writer);
+ if (returnType != null) {
+ writer.WriteString(" : ");
+ WriteTypeReference(returnType, writer);
+ }
+ }
+
+ public override void WritePropertySyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+ if (IsUnsupportedExplicit(reflection, writer)) return;
+
+ if (reflection.Select(apiParametersExpression).Count > 0) {
+ writer.WriteMessage("UnsupportedIndex_" + Language);
+ return;
+ }
+
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ bool isGettable = (bool)reflection.Evaluate(apiIsReadPropertyExpression);
+ bool isSettable = (bool)reflection.Evaluate(apiIsWritePropertyExpression);
+ XPathNavigator type = reflection.SelectSingleNode(apiReturnTypeExpression);
+
+ if (isGettable) {
+ WriteAttributeList(reflection, writer);
+
+ string getVisibility = (string)reflection.Evaluate(apiGetVisibilityExpression);
+ if (!String.IsNullOrEmpty(getVisibility))
+ {
+ WriteVisibility(getVisibility, writer);
+ writer.WriteString(" ");
+ }
+
+ WriteProcedureModifiers(reflection, writer);
+ writer.WriteKeyword("function get");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ writer.WriteString(" () : ");
+ WriteTypeReference(type, writer);
+ writer.WriteLine();
+ }
+
+ if (isSettable) {
+ WriteAttributeList(reflection, writer);
+
+ string setVisibility = (string)reflection.Evaluate(apiSetVisibilityExpression);
+ if (!String.IsNullOrEmpty(setVisibility))
+ {
+ WriteVisibility(setVisibility, writer);
+ writer.WriteString(" ");
+ }
+
+ WriteProcedureModifiers(reflection, writer);
+ writer.WriteKeyword("function set");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ writer.WriteString(" (");
+ writer.WriteParameter("value");
+ writer.WriteString(" : ");
+ WriteTypeReference(type, writer);
+ writer.WriteString(")");
+ }
+
+ }
+
+ public override void WriteFieldSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+ bool isLiteral = (bool)reflection.Evaluate(apiIsLiteralFieldExpression);
+ bool isInitOnly = (bool)reflection.Evaluate(apiIsInitOnlyFieldExpression);
+ bool isSerialized = (bool)reflection.Evaluate(apiIsSerializedFieldExpression);
+ XPathNavigator type = reflection.SelectSingleNode(apiReturnTypeExpression);
+
+ WriteAttributeList(reflection, writer);
+ WriteAccessModifier(reflection, writer);
+ if (isStatic) {
+ if (isLiteral) {
+ writer.WriteKeyword("const");
+ } else {
+ writer.WriteKeyword("static");
+ }
+ writer.WriteString(" ");
+ }
+ if (isInitOnly) {
+ writer.WriteKeyword("final");
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword("var");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ writer.WriteString(" : ");
+ WriteTypeReference(type, writer);
+ }
+
+ public override void WriteOperatorSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ writer.WriteMessage("UnsupportedOperator_" + Language);
+ }
+
+ public override void WriteCastSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ writer.WriteMessage("UnsupportedCast_" + Language);
+ }
+
+ public override void WriteEventSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ writer.WriteMessage("UnsupportedEvent_" + Language);
+ }
+
+ private void WriteBaseClass (XPathNavigator reflection, SyntaxWriter writer) {
+ XPathNavigator baseClass = reflection.SelectSingleNode(apiBaseClassExpression);
+
+ if ((baseClass != null) && !((bool)baseClass.Evaluate(typeIsObjectExpression))) {
+ writer.WriteString(" ");
+ writer.WriteKeyword("extends");
+ writer.WriteString(" ");
+ WriteTypeReference(baseClass, writer);
+ }
+ }
+
+ private void WriteInterfaceList (XPathNavigator reflection, SyntaxWriter writer) {
+ WriteInterfaceList("implements", reflection, writer);
+ }
+
+ private void WriteInterfaceList (string keyword, XPathNavigator reflection, SyntaxWriter writer) {
+ XPathNodeIterator implements = reflection.Select(apiImplementedInterfacesExpression);
+
+ if (implements.Count == 0) return;
+ writer.WriteString(" ");
+ writer.WriteKeyword(keyword);
+ writer.WriteString(" ");
+ while (implements.MoveNext()) {
+ XPathNavigator implement = implements.Current;
+ WriteTypeReference(implement, writer);
+ if (implements.CurrentPosition < implements.Count) writer.WriteString(", ");
+ }
+ }
+
+ private void WriteProcedureModifiers (XPathNavigator reflection, SyntaxWriter writer) {
+
+ // interface members don't get modified
+ string typeSubgroup = (string)reflection.Evaluate(apiContainingTypeSubgroupExpression);
+ if (typeSubgroup == "interface") return;
+
+ string subgroup = (string)reflection.Evaluate(apiSubgroupExpression);
+ if (subgroup != "property") {
+ WriteAccessModifier(reflection, writer);
+ }
+
+ // instance or virtual, static or abstract, etc.
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+ bool isVirtual = (bool)reflection.Evaluate(apiIsVirtualExpression);
+ bool isAbstract = (bool)reflection.Evaluate(apiIsAbstractProcedureExpression);
+ bool isFinal = (bool)reflection.Evaluate(apiIsFinalExpression);
+ bool isOverride = (bool)reflection.Evaluate(apiIsOverrideExpression);
+ if (isStatic) {
+ writer.WriteKeyword("static");
+ writer.WriteString(" ");
+ } else {
+ // all members are virtual in JScript, so no virtual keyword is required
+ if (isVirtual) {
+ if (isAbstract) {
+ writer.WriteKeyword("abstract");
+ writer.WriteString(" ");
+ } else {
+ if (isOverride) {
+ writer.WriteKeyword("override");
+ writer.WriteString(" ");
+ }
+ if (isFinal) {
+ writer.WriteKeyword("final");
+ writer.WriteString(" ");
+ }
+ }
+ }
+ }
+ }
+
+ private void WriteParameterList (XPathNavigator reflection, SyntaxWriter writer) {
+ WriteParameterList(reflection, writer, true);
+ }
+
+ private void WriteParameterList (XPathNavigator reflection, SyntaxWriter writer, bool newlines) {
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+
+ writer.WriteString("(");
+ if (newlines && (parameters.Count > 0)) writer.WriteLine();
+ while (parameters.MoveNext()) {
+ XPathNavigator parameter = parameters.Current;
+ if (newlines) writer.WriteString("\t");
+ WriteParameter(parameter, writer);
+ if (parameters.CurrentPosition < parameters.Count) writer.WriteString(", ");
+ if (newlines) writer.WriteLine();
+ }
+ writer.WriteString(")");
+ }
+
+ // JScript has no in, out, optional, or reference parameters
+ private void WriteParameter (XPathNavigator parameter, SyntaxWriter writer) {
+ string name = (string)parameter.Evaluate(parameterNameExpression);
+ XPathNavigator type = parameter.SelectSingleNode(parameterTypeExpression);
+ bool isParamArray = (bool)parameter.Evaluate(parameterIsParamArrayExpression);
+
+ if (isParamArray) {
+ writer.WriteString("... ");
+ }
+
+ writer.WriteParameter(name);
+ writer.WriteString(" : ");
+ WriteTypeReference(type, writer);
+ }
+
+ private void WriteAccessModifier (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string visibility = reflection.Evaluate(apiVisibilityExpression).ToString();
+
+ switch (visibility) {
+ case "public":
+ writer.WriteKeyword("public");
+ break;
+ case "family":
+ writer.WriteKeyword("protected");
+ break;
+ case "family or assembly":
+ // this isn't handled in JScript
+ break;
+ case "assembly":
+ writer.WriteKeyword("internal");
+ break;
+ case "private":
+ writer.WriteKeyword("private");
+ break;
+ case "family and assembly":
+ // this isn't handled in JScript
+ break;
+ }
+
+ writer.WriteString(" ");
+
+ }
+
+ private void WriteTypeReference (XPathNavigator reference, SyntaxWriter writer) {
+ switch (reference.LocalName) {
+ case "arrayOf":
+ int rank = Convert.ToInt32(reference.GetAttribute("rank", String.Empty));
+ XPathNavigator element = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(element, writer);
+ writer.WriteString("[");
+ for (int i = 1; i < rank; i++) { writer.WriteString(","); }
+ writer.WriteString("]");
+ break;
+ case "pointerTo":
+ XPathNavigator pointee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(pointee, writer);
+ writer.WriteString("*");
+ break;
+ case "referenceTo":
+ XPathNavigator referee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(referee, writer);
+ break;
+ case "type":
+ string id = reference.GetAttribute("api", String.Empty);
+ WriteNormalTypeReference(id, writer);
+ XPathNodeIterator typeModifiers = reference.Select(typeModifiersExpression);
+ while (typeModifiers.MoveNext()) {
+ WriteTypeReference(typeModifiers.Current, writer);
+ }
+ break;
+ case "template":
+ string name = reference.GetAttribute("name", String.Empty);
+ writer.WriteString(name);
+ XPathNodeIterator modifiers = reference.Select(typeModifiersExpression);
+ while (modifiers.MoveNext()) {
+ WriteTypeReference(modifiers.Current, writer);
+ }
+ break;
+ case "specialization":
+ writer.WriteString("<");
+ XPathNodeIterator arguments = reference.Select(specializationArgumentsExpression);
+ while (arguments.MoveNext()) {
+ if (arguments.CurrentPosition > 1) writer.WriteString(", ");
+ WriteTypeReference(arguments.Current, writer);
+ }
+ writer.WriteString(">");
+ break;
+ }
+ }
+
+ private void WriteNormalTypeReference (string api, SyntaxWriter writer) {
+ switch (api) {
+ case "T:System.Boolean":
+ writer.WriteReferenceLink(api, "boolean");
+ break;
+ case "T:System.Byte":
+ writer.WriteReferenceLink(api, "byte");
+ break;
+ case "T:System.SByte":
+ writer.WriteReferenceLink(api, "sbyte");
+ break;
+ case "T:System.Char":
+ writer.WriteReferenceLink(api, "char");
+ break;
+ case "T:System.Int16":
+ writer.WriteReferenceLink(api, "short");
+ break;
+ case "T:System.Int32":
+ writer.WriteReferenceLink(api, "int");
+ break;
+ case "T:System.Int64":
+ writer.WriteReferenceLink(api, "long");
+ break;
+ case "T:System.UInt16":
+ writer.WriteReferenceLink(api, "ushort");
+ break;
+ case "T:System.UInt32":
+ writer.WriteReferenceLink(api, "uint");
+ break;
+ case "T:System.UInt64":
+ writer.WriteReferenceLink(api, "ulong");
+ break;
+ case "T:System.Single":
+ writer.WriteReferenceLink(api, "float");
+ break;
+ case "T:System.Double":
+ writer.WriteReferenceLink(api, "double");
+ break;
+ case "T:System.Decimal":
+ writer.WriteReferenceLink(api, "decimal");
+ break;
+ default:
+ writer.WriteReferenceLink(api);
+ break;
+ }
+ }
+
+ private void WriteAttributeList (XPathNavigator reflection, SyntaxWriter writer) {
+ // fill in this logic
+ }
+
+ private void WriteVisibility(string visibility, SyntaxWriter writer) {
+
+ switch (visibility) {
+ case "public":
+ writer.WriteKeyword("public");
+ break;
+ case "family":
+ writer.WriteKeyword("protected");
+ break;
+ case "family or assembly":
+ // this isn't handled in JScript
+ break;
+ case "assembly":
+ writer.WriteKeyword("internal");
+ break;
+ case "private":
+ writer.WriteKeyword("private");
+ break;
+ case "family and assembly":
+ // this isn't handled in JScript
+ break;
+ }
+
+ }
+
+ }
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/JSharpDeclarationSyntax.cs b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/JSharpDeclarationSyntax.cs
new file mode 100644
index 0000000..c6e3b0d
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/JSharpDeclarationSyntax.cs
@@ -0,0 +1,648 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+
+ public class JSharpDeclarationSyntaxGenerator : DeclarationSyntaxGeneratorTemplate {
+
+ public JSharpDeclarationSyntaxGenerator (XPathNavigator configuration) : base(configuration) {
+ if (String.IsNullOrEmpty(Language)) Language = "JSharp";
+ }
+
+ // private static string unsupportedGeneric = "UnsupportedGeneric_JSharp";
+
+ public override void WriteNamespaceSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = reflection.Evaluate(apiNameExpression).ToString();
+
+ writer.WriteKeyword("package");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ }
+
+
+ public override void WriteClassSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ if (IsUnsupportedGeneric(reflection, writer)) return;
+
+ string name = reflection.Evaluate(apiNameExpression).ToString();
+ bool isAbstract = (bool) reflection.Evaluate(apiIsAbstractTypeExpression);
+ bool isSealed = (bool) reflection.Evaluate(apiIsSealedTypeExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ if (isSealed) {
+ writer.WriteKeyword("final");
+ writer.WriteString(" ");
+ } else if (isAbstract) {
+ writer.WriteKeyword("abstract");
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword("class");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+
+ XPathNavigator baseClass = reflection.SelectSingleNode(apiBaseClassExpression);
+ if ((baseClass != null) && !((bool) baseClass.Evaluate(typeIsObjectExpression))) {
+ writer.WriteString(" ");
+ writer.WriteKeyword("extends");
+ writer.WriteString(" ");
+ WriteTypeReference(baseClass, writer);
+ }
+
+ WriteImplementedInterfaces(reflection, writer);
+
+ }
+
+
+ public override void WriteStructureSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ if (IsUnsupportedGeneric(reflection, writer)) return;
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("final");
+ writer.WriteString(" ");
+ writer.WriteKeyword("class");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+
+ writer.WriteString(" ");
+ writer.WriteKeyword("extends");
+ writer.WriteString(" ");
+ writer.WriteReferenceLink("T:System.ValueType");
+
+ WriteImplementedInterfaces(reflection, writer);
+ }
+
+ public override void WriteInterfaceSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ if (IsUnsupportedGeneric(reflection, writer)) return;
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("interface");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteImplementedInterfaces("extends", reflection, writer);
+ }
+
+ public override void WriteDelegateSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+ if (IsUnsupportedGeneric(reflection, writer)) return;
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ writer.WriteString("/** @delegate */");
+ writer.WriteLine();
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("delegate");
+ writer.WriteString(" ");
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteMethodParameters(reflection, writer);
+
+ }
+
+ public override void WriteEnumerationSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("enum");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ }
+
+ public override void WriteConstructorSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+
+ string name = (string) reflection.Evaluate(apiContainingTypeNameExpression);
+ bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression);
+
+ if (isStatic) {
+ // no static constructors in Java
+ writer.WriteMessage("UnsupportedStaticConstructor_" + Language);
+ return;
+ }
+
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteMethodParameters(reflection, writer);
+
+ }
+
+ public override void WriteMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ bool isSpecialName = (bool) reflection.Evaluate(apiIsSpecialExpression);
+
+ if (isSpecialName) {
+ writer.WriteMessage("UnsupportedOperator_" + Language);
+ } else {
+ WriteNormalMethodSyntax(reflection, writer);
+ }
+ }
+
+ public override void WriteNormalMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+ if (IsUnsupportedGeneric(reflection, writer)) return;
+ if (IsUnsupportedExplicit(reflection, writer)) return;
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+
+ WriteAttributes(reflection, writer);
+ WriteProcedureModifiers(reflection, writer);
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteMethodParameters(reflection, writer);
+ }
+
+ private void WriteNamedNormalMethodSyntax (string name, XPathNavigator reflection, SyntaxWriter writer) {
+
+
+ }
+
+ public override void WritePropertySyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+ if (IsUnsupportedExplicit(reflection, writer)) return;
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isGettable = (bool) reflection.Evaluate(apiIsReadPropertyExpression);
+ bool isSettable = (bool) reflection.Evaluate(apiIsWritePropertyExpression);
+
+ if (isGettable) {
+ writer.WriteString("/** @property */");
+ writer.WriteLine();
+ // write getter method
+ WriteAttributes(reflection, writer);
+ WriteProcedureModifiers(reflection, writer);
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteIdentifier("get_" + name);
+ WriteMethodParameters(reflection, writer);
+ writer.WriteLine();
+ }
+
+ if (isSettable) {
+ writer.WriteString("/** @property */");
+ writer.WriteLine();
+ // write setter method
+ WriteAttributes(reflection, writer);
+ WriteProcedureModifiers(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("void");
+ writer.WriteString(" ");
+ writer.WriteIdentifier("set_" + name);
+ // parameters
+ writer.WriteString("(");
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteParameter("value");
+ writer.WriteString(")");
+ // end parameters
+ writer.WriteLine();
+ }
+
+ }
+
+ public override void WriteEventSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ XPathNavigator handler = reflection.SelectSingleNode(apiHandlerOfEventExpression);
+
+ writer.WriteString("/** @event */");
+ writer.WriteLine();
+ // add_ method declaration
+ WriteAttributes(reflection, writer);
+ WriteProcedureModifiers(reflection, writer);
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteIdentifier("add_" + name);
+ writer.WriteString(" (");
+ WriteTypeReference(handler, writer);
+ writer.WriteString(" ");
+ writer.WriteParameter("value");
+ writer.WriteString(")");
+ writer.WriteLine();
+
+ writer.WriteString("/** @event */");
+ writer.WriteLine();
+ // remove_ method declaration
+ WriteAttributes(reflection, writer);
+ WriteProcedureModifiers(reflection, writer);
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteIdentifier("remove_" + name);
+ writer.WriteString(" (");
+ WriteTypeReference(handler, writer);
+ writer.WriteString(" ");
+ writer.WriteParameter("value");
+ writer.WriteString(")");
+ writer.WriteLine();
+
+ }
+
+ private void WriteProcedureModifiers (XPathNavigator reflection, SyntaxWriter writer) {
+
+ // interface members don't get modified
+ string typeSubgroup = (string) reflection.Evaluate(apiContainingTypeSubgroupExpression);
+ if (typeSubgroup == "interface") return;
+
+ bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression);
+ bool isVirtual = (bool) reflection.Evaluate(apiIsVirtualExpression);
+ bool isAbstract = (bool) reflection.Evaluate(apiIsAbstractProcedureExpression);
+ bool isFinal = (bool) reflection.Evaluate(apiIsFinalExpression);
+ // bool isOverride = (bool) reflection.Evaluate(apiIsOverrideExpression);
+
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ if (isStatic) {
+ writer.WriteKeyword("static");
+ writer.WriteString(" ");
+ } else {
+ if (isVirtual) {
+ if (isAbstract) {
+ writer.WriteKeyword("abstract");
+ writer.WriteString(" ");
+ } else if (isFinal) {
+ writer.WriteKeyword("final");
+ writer.WriteString(" ");
+ }
+ }
+ }
+
+ }
+
+ public override void WriteFieldSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression);
+ bool isLiteral = (bool) reflection.Evaluate(apiIsLiteralFieldExpression);
+ bool isInitOnly = (bool) reflection.Evaluate(apiIsInitOnlyFieldExpression);
+ bool isSerialized = (bool) reflection.Evaluate(apiIsSerializedFieldExpression);
+
+ if (!isSerialized) WriteAttribute("T:System.NonSerializedAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ // Java doesn't support literals as distinct from static initonly
+ if (isStatic) {
+ writer.WriteKeyword("static");
+ writer.WriteString(" ");
+ }
+ if (isLiteral || isInitOnly) {
+ writer.WriteKeyword("final");
+ writer.WriteString(" ");
+ }
+ WriteReturnValue(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+
+ }
+
+ // Visibility
+
+ protected override void WriteVisibility (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string visibility = reflection.Evaluate(apiVisibilityExpression).ToString();
+
+ switch (visibility) {
+ case "public":
+ writer.WriteKeyword("public");
+ break;
+ case "family":
+ // in Java, protected = family or assembly
+ writer.WriteKeyword("protected");
+ break;
+ case "family or assembly":
+ writer.WriteKeyword("protected");
+ break;
+ case "assembly":
+ // no assembly-only access in Java
+ break;
+ case "private":
+ writer.WriteKeyword("private");
+ break;
+ }
+
+ }
+
+ // Attributes
+
+ private void WriteAttribute (string reference, SyntaxWriter writer) {
+ WriteAttribute(reference, writer, true);
+ }
+
+ private void WriteAttribute (string reference, SyntaxWriter writer, bool newline) {
+ writer.WriteString("/** @attribute ");
+ writer.WriteReferenceLink(reference);
+ writer.WriteString(" */ ");
+ if (newline) writer.WriteLine();
+ }
+
+
+ private void WriteAttributes (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator attributes = (XPathNodeIterator) reflection.Evaluate(apiAttributesExpression);
+
+ foreach (XPathNavigator attribute in attributes) {
+
+ XPathNavigator type = attribute.SelectSingleNode(attributeTypeExpression);
+
+ writer.WriteString("/** @attribute ");
+ WriteTypeReference(type, writer);
+
+ XPathNodeIterator arguments = (XPathNodeIterator) attribute.Select(attributeArgumentsExpression);
+ XPathNodeIterator assignments = (XPathNodeIterator) attribute.Select(attributeAssignmentsExpression);
+
+ if ((arguments.Count > 0) || (assignments.Count > 0)) {
+ writer.WriteString("(");
+ while (arguments.MoveNext()) {
+ XPathNavigator argument = arguments.Current;
+ if (arguments.CurrentPosition > 1) writer.WriteString(", ");
+ WriteValue(argument, writer);
+ }
+ if ((arguments.Count > 0) && (assignments.Count > 0)) writer.WriteString(", ");
+ while (assignments.MoveNext()) {
+ XPathNavigator assignment = assignments.Current;
+ if (assignments.CurrentPosition > 1) writer.WriteString(", ");
+ writer.WriteString((string) assignment.Evaluate(assignmentNameExpression));
+ writer.WriteString(" = ");
+ WriteValue(assignment, writer);
+ }
+ writer.WriteString(")");
+ }
+
+ writer.WriteString(" */");
+ writer.WriteLine();
+ }
+
+ }
+
+ private void WriteValue (XPathNavigator parent, SyntaxWriter writer) {
+
+ XPathNavigator type = parent.SelectSingleNode(attributeTypeExpression);
+ XPathNavigator value = parent.SelectSingleNode(valueExpression);
+ // if (value == null) Console.WriteLine("null value");
+
+ switch (value.LocalName) {
+ case "nullValue":
+ writer.WriteKeyword("null");
+ break;
+ case "typeValue":
+ // this isn't really supported in J#; there is no compile-time way to get a type representation
+ // writer.WriteKeyword("typeof");
+ // writer.WriteString("(");
+ WriteTypeReference(value.SelectSingleNode(typeExpression), writer);
+ // writer.WriteString(")");
+ break;
+ case "enumValue":
+ XPathNodeIterator fields = value.SelectChildren(XPathNodeType.Element);
+ while (fields.MoveNext()) {
+ string name = fields.Current.GetAttribute("name", String.Empty);
+ if (fields.CurrentPosition > 1) writer.WriteString("|");
+ WriteTypeReference(type, writer);
+ writer.WriteString(".");
+ writer.WriteString(name);
+ }
+ break;
+ case "value":
+ string text = value.Value;
+ string typeId = type.GetAttribute("api", String.Empty);
+ switch (typeId) {
+ case "T:System.String":
+ writer.WriteString("\"");
+ writer.WriteString(text);
+ writer.WriteString("\"");
+ break;
+ case "T:System.Boolean":
+ bool bool_value = Convert.ToBoolean(text);
+ if (bool_value) {
+ writer.WriteKeyword("true");
+ } else {
+ writer.WriteKeyword("false");
+ }
+ break;
+ case "T:System.Char":
+ writer.WriteString("'");
+ writer.WriteString(text);
+ writer.WriteString("'");
+ break;
+ }
+ break;
+ }
+
+ }
+
+ // Interfaces
+
+ private void WriteImplementedInterfaces (XPathNavigator reflection, SyntaxWriter writer) {
+ WriteImplementedInterfaces("implements", reflection, writer);
+ }
+
+ private void WriteImplementedInterfaces (string keyword, XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator implements = reflection.Select(apiImplementedInterfacesExpression);
+
+ if (implements.Count == 0) return;
+
+ writer.WriteString(" ");
+ writer.WriteKeyword(keyword);
+ writer.WriteString(" ");
+
+ while (implements.MoveNext()) {
+ XPathNavigator implement = implements.Current;
+ WriteTypeReference(implement, writer);
+ if (implements.CurrentPosition < implements.Count) {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition) {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ }
+
+ }
+ // Parameters
+
+ private void WriteMethodParameters (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+
+ writer.WriteString("(");
+ if (parameters.Count > 0) {
+ writer.WriteLine();
+ WriteParameters(parameters, reflection, writer);
+ }
+ writer.WriteString(")");
+
+ }
+
+
+ private void WriteParameters (XPathNodeIterator parameters, XPathNavigator reflection, SyntaxWriter writer) {
+
+ while (parameters.MoveNext()) {
+ XPathNavigator parameter = parameters.Current;
+
+ string name = (string) parameter.Evaluate(parameterNameExpression);
+ XPathNavigator type = parameter.SelectSingleNode(parameterTypeExpression);
+ bool isIn = (bool) parameter.Evaluate(parameterIsInExpression);
+ bool isOut = (bool) parameter.Evaluate(parameterIsOutExpression);
+ bool isRef = (bool) parameter.Evaluate(parameterIsRefExpression);
+ // bool isParamArray = (bool) parameter.Evaluate(parameterIsParamArrayExpression);
+
+ writer.WriteString("\t");
+
+ if (isIn) WriteAttribute("T:System.Runtime.InteropServices.InAttribute", writer, false);
+ if (isOut) WriteAttribute("T:System.Runtime.InteropServices.OutAttribute", writer, false);
+ if (isRef) {
+ writer.WriteString("/** @ref */");
+ }
+
+ WriteTypeReference(type, writer);
+ writer.WriteString(" ");
+ writer.WriteParameter(name);
+
+ if (parameters.CurrentPosition < parameters.Count) writer.WriteString(",");
+ writer.WriteLine();
+ }
+
+ }
+
+ // Return Value
+
+ private void WriteReturnValue (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNavigator type = reflection.SelectSingleNode(apiReturnTypeExpression);
+
+ if (type == null) {
+ writer.WriteKeyword("void");
+ } else {
+ WriteTypeReference(type, writer);
+ }
+ }
+
+ // References
+
+ private void WriteTypeReference (XPathNavigator reference, SyntaxWriter writer) {
+ switch (reference.LocalName) {
+ case "arrayOf":
+ int rank = Convert.ToInt32( reference.GetAttribute("rank",String.Empty) );
+ XPathNavigator element = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(element, writer);
+ writer.WriteString("[");
+ for (int i=1; i<rank; i++) { writer.WriteString(","); }
+ writer.WriteString("]");
+ break;
+ case "pointerTo":
+ XPathNavigator pointee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(pointee, writer);
+ writer.WriteString("*");
+ break;
+ case "referenceTo":
+ XPathNavigator referee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(referee, writer);
+ break;
+ case "type":
+ string id = reference.GetAttribute("api", String.Empty);
+ WriteNormalTypeReference(id, writer);
+ XPathNodeIterator typeModifiers = reference.Select(typeModifiersExpression);
+ while (typeModifiers.MoveNext()) {
+ WriteTypeReference(typeModifiers.Current, writer);
+ }
+ break;
+ case "template":
+ string name = reference.GetAttribute("name", String.Empty);
+ writer.WriteString(name);
+ XPathNodeIterator modifiers = reference.Select(typeModifiersExpression);
+ while (modifiers.MoveNext()) {
+ WriteTypeReference(modifiers.Current, writer);
+ }
+ break;
+ case "specialization":
+ writer.WriteString("<");
+ XPathNodeIterator arguments = reference.Select(specializationArgumentsExpression);
+ while (arguments.MoveNext()) {
+ if (arguments.CurrentPosition > 1) writer.WriteString(", ");
+ WriteTypeReference(arguments.Current, writer);
+ }
+ writer.WriteString(">");
+ break;
+ }
+ }
+
+ private void WriteNormalTypeReference (string reference, SyntaxWriter writer) {
+ switch (reference) {
+ case "T:System.Void":
+ writer.WriteReferenceLink(reference, "void");
+ break;
+ case "T:System.Boolean":
+ writer.WriteReferenceLink(reference, "boolean");
+ break;
+ case "T:System.Byte":
+ writer.WriteReferenceLink(reference, "byte");
+ break;
+ case "T:System.Char":
+ writer.WriteReferenceLink(reference, "char");
+ break;
+ case "T:System.Int16":
+ writer.WriteReferenceLink(reference, "short");
+ break;
+ case "T:System.Int32":
+ writer.WriteReferenceLink(reference, "int");
+ break;
+ case "T:System.Int64":
+ writer.WriteReferenceLink(reference, "long");
+ break;
+ case "T:System.Single":
+ writer.WriteReferenceLink(reference, "float");
+ break;
+ case "T:System.Double":
+ writer.WriteReferenceLink(reference, "double");
+ break;
+ default:
+ writer.WriteReferenceLink(reference);
+ break;
+ }
+ }
+
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/Properties/AssemblyInfo.cs b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b425318
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/Properties/AssemblyInfo.cs
@@ -0,0 +1,42 @@
+// 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.
+
+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("SyntaxComponents")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("SyntaxComponents")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2006")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: System.CLSCompliant(true)]
+
+// 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("52404499-7bf9-4908-88db-44f8de788cf0")]
+
+// 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.5.10626.00")]
+[assembly: AssemblyFileVersion("2.5.10626.00")]
diff --git a/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/ScriptSharpDeclarationSyntax.cs b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/ScriptSharpDeclarationSyntax.cs
new file mode 100644
index 0000000..6958df6
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/ScriptSharpDeclarationSyntax.cs
@@ -0,0 +1,614 @@
+// 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.
+
+using System;
+using System.Xml.XPath;
+using System.Globalization;
+
+namespace Microsoft.Ddue.Tools {
+ /// <summary>
+ /// Generates syntax that corresponds to JavaScript that Script# generates.
+ /// </summary>
+ public class ScriptSharpDeclarationSyntaxGenerator : SyntaxGeneratorTemplate {
+ private static readonly XPathExpression typeIsRecordExpression = XPathExpression.Compile("boolean(apidata/@record)");
+
+ private static readonly XPathExpression memberIsGlobalExpression = XPathExpression.Compile("boolean(apidata/@global)");
+
+ /// <summary>
+ /// Initializes a new instance of the <c>ScriptSharpDeclarationSyntaxGenerator</c> class.
+ /// </summary>
+ /// <param name="configuration"></param>
+ public ScriptSharpDeclarationSyntaxGenerator(XPathNavigator configuration) : base(configuration) {
+ if (String.IsNullOrEmpty(Language)) Language = "JavaScript";
+ }
+
+ /// <summary>
+ /// Determines whether the feature is unsupported by this language.
+ /// </summary>
+ /// <param name="reflection"></param>
+ /// <param name="writer"></param>
+ /// <returns></returns>
+ private bool IsUnsupported(XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupportedGeneric(reflection, writer)) {
+ return true;
+ }
+
+ if (IsUnsupportedExplicit(reflection, writer)) {
+ return true;
+ }
+
+ if (IsUnsupportedUnsafe(reflection, writer)) {
+ return true;
+ }
+
+ if (HasAttribute(reflection, "System.NonScriptableAttribute")) {
+ writer.WriteMessage("UnsupportedType_ScriptSharp");
+ return true;
+ }
+
+ return false;
+ }
+
+ private string ReadNamespaceName(XPathNavigator reflection) {
+ return (string)reflection.Evaluate(apiContainingNamespaceNameExpression);
+ }
+
+ private string ReadTypeName(XPathNavigator reflection) {
+ return (string)reflection.Evaluate(apiNameExpression);
+ }
+
+ private string ReadContainingTypeName(XPathNavigator reflection) {
+ return (string)reflection.Evaluate(apiContainingTypeNameExpression);
+ }
+
+ private string ReadFullTypeName(XPathNavigator reflection) {
+ string namespaceName = ReadNamespaceName(reflection);
+
+ string typeName = ReadTypeName(reflection);
+
+ if (String.IsNullOrEmpty(namespaceName) || HasAttribute(reflection, "System.IgnoreNamespaceAttribute")) {
+ return typeName;
+ }
+ else {
+ return String.Format("{0}.{1}", namespaceName, typeName);
+ }
+ }
+
+ private string ReadFullContainingTypeName(XPathNavigator reflection) {
+ string namespaceName = ReadNamespaceName(reflection);
+
+ string typeName = ReadContainingTypeName(reflection);
+
+ if (String.IsNullOrEmpty(namespaceName) || HasAttribute(reflection, "System.IgnoreNamespaceAttribute")) {
+ return typeName;
+ }
+ else {
+ return String.Format("{0}.{1}", namespaceName, typeName);
+ }
+ }
+
+ private string ReadMemberName(XPathNavigator reflection) {
+ string identifier = (string)reflection.Evaluate(apiNameExpression);
+
+ if (!HasAttribute(reflection, "System.PreserveCaseAttribute")) {
+ identifier = CreateCamelCaseName(identifier);
+ }
+
+ return identifier;
+ }
+
+ private bool HasAttribute(XPathNavigator reflection, string attributeName) {
+ attributeName = "T:" + attributeName;
+
+ XPathNodeIterator iterator = (XPathNodeIterator)reflection.Evaluate(apiAttributesExpression);
+ foreach (XPathNavigator navigator in iterator) {
+ XPathNavigator reference = navigator.SelectSingleNode(attributeTypeExpression);
+ if (reference.GetAttribute("api", string.Empty) == attributeName) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static string CreateCamelCaseName(string name) {
+
+ if (String.IsNullOrEmpty(name)) {
+ return name;
+ }
+
+ // Some exceptions that simply need to be special cased
+ if (name.Equals("ID", StringComparison.Ordinal)) {
+ return "id";
+ }
+
+ bool hasLowerCase = false;
+ int conversionLength = 0;
+
+ for (int i = 0; i < name.Length; i++) {
+ if (Char.IsUpper(name, i)) {
+ conversionLength++;
+ } else {
+ hasLowerCase = true;
+ break;
+ }
+ }
+
+ if (((hasLowerCase == false) && (name.Length != 1)) || (conversionLength == 0)) {
+ // Name is all upper case, or all lower case; leave it as-is.
+ return name;
+ }
+
+ if (conversionLength > 1) {
+ // Convert the leading uppercase segment, except the last character
+ // which is assumed to be the first letter of the next word
+ return name.Substring(0, conversionLength - 1).ToLower(CultureInfo.InvariantCulture) + name.Substring(conversionLength - 1);
+ }
+
+ else if (name.Length == 1) {
+ return name.ToLower(CultureInfo.InvariantCulture);
+ }
+
+ else {
+ // Convert the leading upper case character to lower case
+ return Char.ToLower(name[0], CultureInfo.InvariantCulture) + name.Substring(1);
+ }
+ }
+
+ private void WriteIndentedNewLine(SyntaxWriter writer) {
+ writer.WriteString(",");
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+
+ private void WriteParameterList(XPathNavigator reflection, SyntaxWriter writer) {
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+ writer.WriteString("(");
+
+ while (parameters.MoveNext()) {
+ XPathNavigator parameter = parameters.Current;
+
+ WriteParameter(parameter, writer);
+ if (parameters.CurrentPosition < parameters.Count) {
+ writer.WriteString(", ");
+ }
+ }
+ writer.WriteString(")");
+ }
+
+ private void WriteParameter(XPathNavigator parameter, SyntaxWriter writer) {
+ string text = (string)parameter.Evaluate(parameterNameExpression);
+ XPathNavigator reference = parameter.SelectSingleNode(parameterTypeExpression);
+ if ((bool)parameter.Evaluate(parameterIsParamArrayExpression)) {
+ writer.WriteString("... ");
+ }
+ writer.WriteParameter(text);
+ }
+
+ private void WriteTypeReference(XPathNavigator reference, SyntaxWriter writer)
+ {
+ switch (reference.LocalName)
+ {
+ case "arrayOf":
+ int rank = Convert.ToInt32(reference.GetAttribute("rank", string.Empty));
+ XPathNavigator navigator = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(navigator, writer);
+ writer.WriteString("[");
+ for (int i = 1; i < rank; i++) { writer.WriteString(","); }
+ writer.WriteString("]");
+ break;
+ case "type":
+ string id = reference.GetAttribute("api", string.Empty);
+ WriteNormalTypeReference(id, writer);
+ break;
+ case "pointerTo":
+ case "referenceTo":
+ case "template":
+ case "specialization":
+ // Not supported
+ break;
+ }
+ }
+
+ private void WriteNormalTypeReference(string api, SyntaxWriter writer) {
+ switch (api) {
+ case "T:System.Byte":
+ writer.WriteReferenceLink(api, "Byte");
+ return;
+
+ case "T:System.SByte":
+ writer.WriteReferenceLink(api, "SByte");
+ return;
+
+ case "T:System.Char":
+ writer.WriteReferenceLink(api, "Char");
+ return;
+
+ case "T:System.Int16":
+ writer.WriteReferenceLink(api, "Int16");
+ return;
+
+ case "T:System.Int32":
+ writer.WriteReferenceLink(api, "Int32");
+ return;
+
+ case "T:System.Int64":
+ writer.WriteReferenceLink(api, "Int64");
+ return;
+
+ case "T:System.UInt16":
+ writer.WriteReferenceLink(api, "UInt16");
+ return;
+
+ case "T:System.UInt32":
+ writer.WriteReferenceLink(api, "UInt32");
+ return;
+
+ case "T:System.UInt64":
+ writer.WriteReferenceLink(api, "UInt64");
+ return;
+
+ case "T:System.Single":
+ writer.WriteReferenceLink(api, "Single");
+ return;
+
+ case "T:System.Double":
+ writer.WriteReferenceLink(api, "Double");
+ return;
+
+ case "T:System.Decimal":
+ writer.WriteReferenceLink(api, "Decimal");
+ return;
+
+ case "T:System.Boolean":
+ writer.WriteReferenceLink(api, "Boolean");
+ return;
+ }
+
+ // Remove 'T:'
+ string name = api.Substring(2);
+
+ // Strip System namespaces
+ if (name.StartsWith("System.")) {
+ int idx = name.LastIndexOf('.');
+ name = name.Substring(idx + 1);
+ }
+
+ writer.WriteReferenceLink(api, name);
+ }
+
+ private void WriteRecordSyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ string namespaceName = ReadNamespaceName(reflection);
+
+ string typeName = ReadTypeName(reflection);
+
+ writer.WriteString(namespaceName);
+ writer.WriteString(".$create_");
+ writer.WriteString(typeName);
+ writer.WriteString(" = ");
+ writer.WriteKeyword("function");
+ writer.WriteString("();");
+ }
+
+ private void WriteRecordConstructorSyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ string namespaceName = ReadNamespaceName(reflection);
+
+ string typeName = ReadContainingTypeName(reflection);
+
+ writer.WriteString(namespaceName);
+ writer.WriteString(".$create_");
+ writer.WriteString(typeName);
+ writer.WriteString(" = ");
+ writer.WriteKeyword("function");
+ WriteParameterList(reflection, writer);
+ writer.WriteString(";");
+ }
+
+ public override void WriteClassSyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupported(reflection, writer)) return;
+
+ if (HasAttribute(reflection, "System.RecordAttribute")) {
+ WriteRecordSyntax(reflection, writer);
+ return;
+ }
+
+ string typeName = ReadFullTypeName(reflection);
+
+ writer.WriteIdentifier(typeName);
+ writer.WriteString(" = ");
+ writer.WriteKeyword("function");
+ writer.WriteString("();");
+
+ writer.WriteLine();
+ writer.WriteLine();
+
+ writer.WriteIdentifier("Type");
+ writer.WriteString(".createClass(");
+ writer.WriteLine();
+ writer.WriteString("\t'");
+ writer.WriteString(typeName);
+ writer.WriteString("'");
+
+ bool hasBaseClass = false;
+
+ // Write the base class.
+ XPathNavigator reference = reflection.SelectSingleNode(apiBaseClassExpression);
+ if (!((reference == null) || ((bool)reference.Evaluate(typeIsObjectExpression)))) {
+ WriteIndentedNewLine(writer);
+ WriteTypeReference(reference, writer);
+ hasBaseClass = true;
+ }
+
+ // Write the interfaces.
+ XPathNodeIterator iterator = reflection.Select(apiImplementedInterfacesExpression);
+ if (iterator.Count != 0) {
+ if (!hasBaseClass) {
+ WriteIndentedNewLine(writer);
+ writer.WriteString("null");
+ }
+
+ WriteIndentedNewLine(writer);
+
+ while (iterator.MoveNext()) {
+ XPathNavigator interfaceRef = iterator.Current;
+ WriteTypeReference(interfaceRef, writer);
+ if (iterator.CurrentPosition < iterator.Count) {
+ WriteIndentedNewLine(writer);
+ }
+ }
+ }
+
+ writer.WriteString(");");
+ }
+
+ public override void WriteConstructorSyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupported(reflection, writer)) {
+ return;
+ }
+
+ bool isRecord = (bool)reflection.Evaluate(typeIsRecordExpression);
+
+ if (isRecord) {
+ WriteRecordConstructorSyntax(reflection, writer);
+ return;
+ }
+
+ string typeName = ReadFullContainingTypeName(reflection);
+
+ writer.WriteIdentifier(typeName);
+ writer.WriteString(" = ");
+ writer.WriteKeyword("function");
+ WriteParameterList(reflection, writer);
+ writer.WriteString(";");
+ }
+
+ public override void WriteNormalMethodSyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupported(reflection, writer)) return;
+
+ if (HasAttribute(reflection, "System.AttachedPropertyAttribute")) {
+ WriteAttachedPropertySyntax(reflection, writer);
+ return;
+ }
+
+ string memberName = ReadMemberName(reflection);
+
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+ bool isGlobal = (bool)reflection.Evaluate(memberIsGlobalExpression);
+
+ if (isStatic && !isGlobal) {
+ writer.WriteIdentifier(ReadFullContainingTypeName(reflection));
+ writer.WriteString(".");
+ writer.WriteIdentifier(memberName);
+ writer.WriteString(" = ");
+ writer.WriteKeyword("function");
+ }
+ else {
+ writer.WriteKeyword("function");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(memberName);
+ }
+
+ WriteParameterList(reflection, writer);
+ writer.WriteString(";");
+ }
+
+ public override void WriteDelegateSyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ writer.WriteKeyword("function");
+ WriteParameterList(reflection, writer);
+ writer.WriteString(";");
+ }
+
+ public override void WriteEnumerationSyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ string typeName = ReadFullTypeName(reflection);
+
+ writer.WriteIdentifier(typeName);
+ writer.WriteString(" = ");
+ writer.WriteKeyword("function");
+ writer.WriteString("();");
+
+ writer.WriteLine();
+
+ writer.WriteIdentifier(typeName);
+ writer.WriteString(".createEnum('");
+ writer.WriteIdentifier(typeName);
+ writer.WriteString("', ");
+ writer.WriteString(HasAttribute(reflection, "System.FlagsAttribute") ? "true" : "false");
+ writer.WriteString(");");
+ }
+
+ public override void WriteEventSyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupported(reflection, writer)) return;
+
+ if (reflection.Select(apiParametersExpression).Count > 0) {
+ writer.WriteMessage("UnsupportedIndex_" + Language);
+ return;
+ }
+
+ string memberName = ReadMemberName(reflection);
+
+ writer.WriteKeyword("function");
+ writer.WriteString(" add_");
+ writer.WriteIdentifier(memberName);
+ writer.WriteString("(");
+ writer.WriteParameter("value");
+ writer.WriteString(");");
+
+ writer.WriteLine();
+
+ writer.WriteKeyword("function");
+ writer.WriteString(" remove_");
+ writer.WriteIdentifier(memberName);
+ writer.WriteString("(");
+ writer.WriteParameter("value");
+ writer.WriteString(");");
+ }
+
+ public override void WriteFieldSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ if (IsUnsupported(reflection, writer)) {
+ return;
+ }
+
+ string memberName = ReadMemberName(reflection);
+
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+ if (isStatic) {
+ string typeName = ReadFullContainingTypeName(reflection);
+
+ writer.WriteIdentifier(typeName);
+ writer.WriteString(".");
+ }
+
+ writer.WriteIdentifier(memberName);
+ }
+
+ public override void WriteInterfaceSyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupported(reflection, writer)) return;
+
+ string typeName = ReadFullTypeName(reflection);
+
+ writer.WriteIdentifier(typeName);
+ writer.WriteString(" = ");
+ writer.WriteKeyword("function");
+ writer.WriteString("();");
+
+ writer.WriteLine();
+
+ writer.WriteIdentifier(typeName);
+ writer.WriteString(".createInterface('");
+ writer.WriteIdentifier(typeName);
+ writer.WriteString("');");
+ }
+
+ public override void WriteAttachedEventSyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ // Not supported
+ }
+
+ public override void WriteAttachedPropertySyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ string typeName = ReadContainingTypeName(reflection);
+
+ string methodName = ReadMemberName(reflection);
+
+ string propertyName = String.Format("{0}.{1}", typeName, methodName.Substring(3));
+
+ if (methodName.StartsWith("Get", StringComparison.OrdinalIgnoreCase)) {
+ writer.WriteKeyword("var");
+ writer.WriteString(" value = obj['");
+ writer.WriteString(propertyName);
+ writer.WriteString("'];");
+ }
+ else if (methodName.StartsWith("Set", StringComparison.OrdinalIgnoreCase)) {
+ writer.WriteString("obj['");
+ writer.WriteString(propertyName);
+ writer.WriteString("'] = value;");
+ }
+ }
+
+ public override void WriteOperatorSyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ writer.WriteMessage("UnsupportedOperator_" + Language);
+ }
+
+ public override void WriteCastSyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ writer.WriteMessage("UnsupportedCast_" + Language);
+ }
+
+ public override void WriteNamespaceSyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ string name = reflection.Evaluate(apiNameExpression).ToString();
+
+ writer.WriteString("Type.createNamespace('");
+ writer.WriteIdentifier(name);
+ writer.WriteString("');");
+ }
+
+ public override void WritePropertySyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupported(reflection, writer)) return;
+
+ if (HasAttribute(reflection, "System.IntrinsicPropertyAttribute")) {
+ WriteFieldSyntax(reflection, writer);
+ return;
+ }
+
+ string memberName = ReadMemberName(reflection);
+
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+
+ bool isGetter = (bool)reflection.Evaluate(apiIsReadPropertyExpression);
+ bool isSetter = (bool)reflection.Evaluate(apiIsWritePropertyExpression);
+
+ XPathNavigator reference = reflection.SelectSingleNode(apiReturnTypeExpression);
+
+ if (isGetter) {
+ if (isStatic) {
+ writer.WriteIdentifier(ReadFullContainingTypeName(reflection));
+ writer.WriteString(".");
+
+ writer.WriteString("get_");
+ writer.WriteIdentifier(memberName);
+ writer.WriteString(" = ");
+ writer.WriteKeyword("function");
+ }
+ else {
+ writer.WriteKeyword("function");
+ writer.WriteString(" ");
+
+ writer.WriteString("get_");
+ writer.WriteIdentifier(memberName);
+ }
+
+ WriteParameterList(reflection, writer);
+ writer.WriteString(";");
+ writer.WriteLine();
+ }
+
+ if (isSetter) {
+ if (isStatic) {
+ writer.WriteIdentifier(ReadFullContainingTypeName(reflection));
+ writer.WriteString(".");
+
+ writer.WriteString("set_");
+ writer.WriteIdentifier(memberName);
+ writer.WriteString(" = ");
+ writer.WriteKeyword("function");
+ }
+ else {
+ writer.WriteKeyword("function");
+ writer.WriteString(" ");
+
+ writer.WriteString("set_");
+ writer.WriteIdentifier(memberName);
+ }
+
+ writer.WriteString("(");
+ writer.WriteParameter("value");
+ writer.WriteString(");");
+ }
+ }
+
+ public override void WriteStructureSyntax(XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupported(reflection, writer)) return;
+ writer.WriteMessage("UnsupportedStructure_" + Language);
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/SyntaxComponents.csproj b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/SyntaxComponents.csproj
new file mode 100644
index 0000000..e6d8ad0
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/SyntaxComponents.csproj
@@ -0,0 +1,105 @@
+<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>{CEAEC85B-973A-4414-8668-723EB65E5088}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>SyntaxComponents</RootNamespace>
+ <AssemblyName>SyntaxComponents</AssemblyName>
+ <SccProjectName>
+ </SccProjectName>
+ <SccLocalPath>
+ </SccLocalPath>
+ <SccAuxPath>
+ </SccAuxPath>
+ <SccProvider>
+ </SccProvider>
+ <SignAssembly>false</SignAssembly>
+ <AssemblyOriginatorKeyFile>../../../key.snk</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>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'WebDocsDebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\WebDocsDebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Sandcastle|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Sandcastle\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Web.Services" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AspNetSyntax.cs" />
+ <Compile Include="CPlusPlusDeclarationSyntax.cs" />
+ <Compile Include="CSharpDeclarationSyntax.cs" />
+ <Compile Include="FSharpDeclarationSyntax.cs" />
+ <Compile Include="GlobalSuppressions.cs" />
+ <Compile Include="JScriptDeclarationSyntax.cs" />
+ <Compile Include="JSharpDeclarationSyntax.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ScriptSharpDeclarationSyntax.cs" />
+ <Compile Include="SyntaxGenerators.cs" />
+ <Compile Include="VisualBasicDeclarationSyntax.cs" />
+ <Compile Include="VisualBasicUsageSyntax.cs" />
+ <Compile Include="XamlUsageSyntax.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\BuildAssemblerLibrary\BuildAssemblerLibrary.csproj">
+ <Project>{399E78F8-4954-409E-991A-37DA9D0579CC}</Project>
+ <Name>BuildAssemblerLibrary</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\BuildComponents\BuildComponents.csproj">
+ <Project>{30773718-BC7C-4FCC-A9C2-7EE61DF4EC41}</Project>
+ <Name>BuildComponents</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/SyntaxComponents/SyntaxGenerators.cs b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/SyntaxGenerators.cs
new file mode 100644
index 0000000..8f9f2c9
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/SyntaxGenerators.cs
@@ -0,0 +1,435 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ public abstract class SyntaxGeneratorTemplate : SyntaxGenerator {
+
+ protected SyntaxGeneratorTemplate (XPathNavigator configuration) : base(configuration) {
+
+ string nameValue = configuration.GetAttribute("name", String.Empty);
+ language = nameValue;
+
+ }
+
+ // A maximum width setting
+
+ protected static int maxPosition = 60;
+
+ // The language itentifier
+
+
+ private string language;
+
+ public string Language {
+ get {
+ return (language);
+ }
+ protected set {
+ language = value;
+ }
+ }
+
+ // Where data is stored
+
+ // api data
+ protected static XPathExpression apiNameExpression = XPathExpression.Compile("string(apidata/@name)");
+ protected static XPathExpression apiGroupExpression = XPathExpression.Compile("string(apidata/@group)");
+ protected static XPathExpression apiSubgroupExpression = XPathExpression.Compile("string(apidata/@subgroup)");
+ protected static XPathExpression apiSubsubgroupExpression = XPathExpression.Compile("string(apidata/@subsubgroup)");
+
+ // support testing
+ protected static XPathExpression apiIsUnsafeExpression = XPathExpression.Compile("boolean(parameters/parameter//pointerTo or returns//pointerTo)");
+ protected static XPathExpression apiIsGenericExpression = XPathExpression.Compile("boolean(templates/template)");
+ protected static XPathExpression apiIsExtensionMethod = XPathExpression.Compile("boolean(attributes/attribute/type[@api='T:System.Runtime.CompilerServices.ExtensionAttribute'])");
+
+ // visibility attribute
+ protected static XPathExpression apiVisibilityExpression = XPathExpression.Compile("string((typedata|memberdata)/@visibility)");
+ protected static XPathExpression apiIsFamilyMemberExpression = XPathExpression.Compile("boolean(contains(memberdata/@visibility,'family'))");
+
+ // type data
+ protected static XPathExpression apiVisibilityOfTypeExpression = XPathExpression.Compile("string(typedata/@visibility)");
+ protected static XPathExpression apiIsAbstractTypeExpression = XPathExpression.Compile("boolean(typedata[@abstract='true'])");
+ protected static XPathExpression apiIsSealedTypeExpression = XPathExpression.Compile("boolean(typedata[@sealed='true'])");
+ protected static XPathExpression apiIsSerializableTypeExpression = XPathExpression.Compile("boolean(typedata[@serializable='true'])");
+
+ // class data
+ protected static XPathExpression apiBaseClassExpression = XPathExpression.Compile("family/ancestors/*[1]");
+ protected static XPathExpression apiAncestorsExpression = XPathExpression.Compile("family/ancestors/*");
+
+ // enumeration data
+
+ // various subheadings
+ protected static XPathExpression apiAttributesExpression = XPathExpression.Compile("attributes/attribute");
+ protected static XPathExpression apiTemplatesExpression = XPathExpression.Compile("templates/template");
+ protected static XPathExpression apiImplementedInterfacesExpression = XPathExpression.Compile("implements/type");
+ protected static XPathExpression apiParametersExpression = XPathExpression.Compile("parameters/parameter");
+ protected static XPathExpression apiReturnTypeExpression = XPathExpression.Compile("returns/*[1]");
+
+ // member data
+ protected static XPathExpression apiVisibilityOfMemberExpression = XPathExpression.Compile("string(memberdata/@visibility)");
+ protected static XPathExpression apiIsStaticExpression = XPathExpression.Compile("boolean(memberdata[@static='true'])");
+ protected static XPathExpression apiIsSpecialExpression = XPathExpression.Compile("boolean(memberdata[@special='true'])");
+ protected static XPathExpression apiIsDefaultMemberExpression = XPathExpression.Compile("boolean(memberdata[@default='true'])");
+
+ // field data
+ protected static XPathExpression apiIsLiteralFieldExpression = XPathExpression.Compile("boolean(fielddata[@literal='true'])");
+ protected static XPathExpression apiIsInitOnlyFieldExpression = XPathExpression.Compile("boolean(fielddata[@initonly='true'])");
+ protected static XPathExpression apiIsVolatileFieldExpression = XPathExpression.Compile("boolean(fielddata[@volatile='true'])");
+ protected static XPathExpression apiIsSerializedFieldExpression = XPathExpression.Compile("boolean(fielddata[@serialized='true'])");
+
+ // procedure data
+ protected static XPathExpression apiIsAbstractProcedureExpression = XPathExpression.Compile("boolean(proceduredata[@abstract='true'])");
+ protected static XPathExpression apiIsVirtualExpression = XPathExpression.Compile("boolean(proceduredata[@virtual='true'])");
+ protected static XPathExpression apiIsFinalExpression = XPathExpression.Compile("boolean(proceduredata[@final='true'])");
+ protected static XPathExpression apiOverridesMemberExpression = XPathExpression.Compile("string(proceduredata/@overrides/member)");
+ protected static XPathExpression apiIsExplicitImplementationExpression = XPathExpression.Compile("boolean(memberdata/@visibility='private' and proceduredata/@virtual='true' and boolean(implements/member))");
+ protected static XPathExpression apiImplementedMembersExpression = XPathExpression.Compile("implements/member");
+ protected static XPathExpression apiIsOverrideExpression = XPathExpression.Compile("boolean(overrides/member)");
+
+ // property data
+ protected static XPathExpression apiIsReadPropertyExpression = XPathExpression.Compile("boolean(propertydata/@get='true')");
+ protected static XPathExpression apiIsWritePropertyExpression = XPathExpression.Compile("boolean(propertydata/@set='true')");
+ protected static XPathExpression apiGetVisibilityExpression = XPathExpression.Compile("string(propertydata/@get-visibility)");
+ protected static XPathExpression apiSetVisibilityExpression = XPathExpression.Compile("string(propertydata/@set-visibility)");
+
+ // event data
+ protected static XPathExpression apiHandlerOfEventExpression = XPathExpression.Compile("eventhandler/*[1]");
+ protected static XPathExpression apiEventArgsExpression = XPathExpression.Compile("eventargs/*[1]");
+
+ // parameter data
+ //protected static XPathExpression params_expression = XPathExpression.Compile("boolean(@params='true')");
+ protected static XPathExpression parameterNameExpression = XPathExpression.Compile("string(@name)");
+ protected static XPathExpression parameterTypeExpression = XPathExpression.Compile("*[1]");
+ protected static XPathExpression parameterIsInExpression = XPathExpression.Compile("boolean(@in='true')");
+ protected static XPathExpression parameterIsOutExpression = XPathExpression.Compile("boolean(@out='true')");
+ protected static XPathExpression parameterIsRefExpression = XPathExpression.Compile("boolean(referenceTo)");
+ protected static XPathExpression parameterIsParamArrayExpression = XPathExpression.Compile("boolean(@params='true')");
+
+ // container data
+ protected static XPathExpression apiContainingTypeExpression = XPathExpression.Compile("containers/type");
+ protected static XPathExpression apiContainingTypeNameExpression = XPathExpression.Compile("string(containers/type/apidata/@name)");
+ protected static XPathExpression apiContainingTypeSubgroupExpression = XPathExpression.Compile("string(containers/type/apidata/@subgroup)");
+ protected static XPathExpression apiContainingAssemblyExpression = XPathExpression.Compile("string(containers/library/@assembly)");
+ protected static XPathExpression apiContainingNamespaceIdExpression = XPathExpression.Compile("string(containers/namespace/@api)");
+ protected static XPathExpression apiContainingNamespaceNameExpression = XPathExpression.Compile("string(containers/namespace/apidata/@name)");
+ // protected static XPathExpression containing_type_templates_expression = XPathExpression.Compile("containers/container[@type]/templates");
+
+ // referenced type data
+ protected static XPathExpression typeExpression = XPathExpression.Compile("*[1]");
+ protected static XPathExpression typeIdExpression = XPathExpression.Compile("@api");
+ protected static XPathExpression typeModifiersExpression = XPathExpression.Compile("optionalModifier|requiredModifier|specialization");
+ protected static XPathExpression typeOuterTypeExpression = XPathExpression.Compile("type");
+ protected static XPathExpression typeIsObjectExpression = XPathExpression.Compile("boolean(local-name()='type' and @api='T:System.Object')");
+ protected static XPathExpression valueExpression = XPathExpression.Compile("*[2]");
+ protected static XPathExpression nameExpression = XPathExpression.Compile("string(@name)");
+ protected static XPathExpression specializationArgumentsExpression = XPathExpression.Compile("*");
+
+ // referenced member data
+ protected static XPathExpression memberDeclaringTypeExpression = XPathExpression.Compile("*[1]");
+
+ // attribute data
+ protected static XPathExpression attributeTypeExpression = XPathExpression.Compile("*[1]");
+ protected static XPathExpression attributeArgumentsExpression = XPathExpression.Compile("argument");
+ protected static XPathExpression attributeAssignmentsExpression = XPathExpression.Compile("assignment");
+ protected static XPathExpression assignmentNameExpression = XPathExpression.Compile("string(@name)");
+
+ // template data
+ protected static XPathExpression templateNameExpression = XPathExpression.Compile("string(@name)");
+ protected static XPathExpression templateIsConstrainedExpression = XPathExpression.Compile("boolean(constrained)");
+ protected static XPathExpression templateIsValueTypeExpression = XPathExpression.Compile("boolean(constrained/@value='true')");
+ protected static XPathExpression templateIsReferenceTypeExpression = XPathExpression.Compile("boolean(constrained/@ref='true')");
+ protected static XPathExpression templateIsConstructableExpression = XPathExpression.Compile("boolean(constrained/@ctor='true')");
+ protected static XPathExpression templateConstraintsExpression = XPathExpression.Compile("constrained/type | constrained/implements/type | constrained/implements/template");
+ protected static XPathExpression templateIsCovariantExpression = XPathExpression.Compile("boolean(variance/@covariant='true')");
+ protected static XPathExpression templateIsContravariantExpression = XPathExpression.Compile("boolean(variance/@contravariant='true')");
+
+ protected static XPathExpression attachedEventAdderExpression = XPathExpression.Compile("string(attachedeventdata/adder/member/@api)");
+ protected static XPathExpression attachedEventRemoverExpression = XPathExpression.Compile("string(attachedeventdata/remover/member/@api)");
+
+ protected static XPathExpression attachedPropertyGetterExpression = XPathExpression.Compile("string(attachedpropertydata/getter/member/@api)");
+ protected static XPathExpression attachedPropertySetterExpression = XPathExpression.Compile("string(attachedpropertydata/setter/member/@api)");
+
+ // Methods to write syntax for different kinds of APIs
+
+ public override void WriteSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ writer.WriteStartBlock(Language);
+
+ string group = (string) reflection.Evaluate(apiGroupExpression);
+
+ switch (group) {
+ case "namespace":
+ WriteNamespaceSyntax(reflection, writer);
+ break;
+ case "type":
+ WriteTypeSyntax(reflection, writer);
+ break;
+ case "member":
+ WriteMemberSyntax(reflection, writer);
+ break;
+ }
+
+ writer.WriteEndBlock();
+
+ }
+
+ public virtual void WriteTypeSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string subgroup = (string) reflection.Evaluate(apiSubgroupExpression);
+
+ switch (subgroup) {
+ case "class":
+ WriteClassSyntax(reflection, writer);
+ break;
+ case "structure":
+ WriteStructureSyntax(reflection, writer);
+ break;
+ case "interface":
+ WriteInterfaceSyntax(reflection, writer);
+ break;
+ case "delegate":
+ WriteDelegateSyntax(reflection, writer);
+ break;
+ case "enumeration":
+ WriteEnumerationSyntax(reflection, writer);
+ break;
+ }
+
+ }
+
+ public virtual void WriteMemberSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string subgroup = (string) reflection.Evaluate(apiSubgroupExpression);
+ string subsubgroup = (string)reflection.Evaluate(apiSubsubgroupExpression);
+
+ switch (subgroup) {
+ case "constructor":
+ WriteConstructorSyntax(reflection, writer);
+ break;
+ case "method":
+ WriteMethodSyntax(reflection, writer);
+ break;
+ case "property":
+ if (subsubgroup == "attachedProperty")
+ WriteAttachedPropertySyntax(reflection, writer);
+ else
+ WritePropertySyntax(reflection, writer);
+ break;
+ case "event":
+ if (subsubgroup == "attachedEvent")
+ WriteAttachedEventSyntax(reflection, writer);
+ else
+ WriteEventSyntax(reflection, writer);
+ break;
+ case "field":
+ WriteFieldSyntax(reflection, writer);
+ break;
+ }
+
+ }
+
+ public abstract void WriteNamespaceSyntax (XPathNavigator reflection, SyntaxWriter writer);
+
+ public abstract void WriteClassSyntax (XPathNavigator reflection, SyntaxWriter writer);
+
+ public abstract void WriteStructureSyntax (XPathNavigator reflection, SyntaxWriter writer);
+
+ public abstract void WriteInterfaceSyntax (XPathNavigator reflection, SyntaxWriter writer);
+
+ public abstract void WriteDelegateSyntax (XPathNavigator reflection, SyntaxWriter writer);
+
+ public abstract void WriteEnumerationSyntax (XPathNavigator reflection, SyntaxWriter writer);
+
+ public abstract void WriteConstructorSyntax (XPathNavigator reflection, SyntaxWriter writer);
+
+ public virtual void WriteMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ bool isSpecialName = (bool)reflection.Evaluate(apiIsSpecialExpression);
+ string name = (string)reflection.Evaluate(apiNameExpression);
+
+ if (isSpecialName) {
+ string subsubgroup = (string)reflection.Evaluate(apiSubsubgroupExpression);
+ if (subsubgroup == "operator") {
+ if ((name == "Implicit") || (name == "Explicit")) {
+ WriteCastSyntax(reflection, writer);
+ } else {
+ WriteOperatorSyntax(reflection, writer);
+ }
+ }
+ } else {
+ WriteNormalMethodSyntax(reflection, writer);
+ }
+ }
+
+ public abstract void WritePropertySyntax (XPathNavigator reflection, SyntaxWriter writer);
+
+ public abstract void WriteFieldSyntax (XPathNavigator reflection, SyntaxWriter writer);
+
+ public abstract void WriteEventSyntax (XPathNavigator reflection, SyntaxWriter writer);
+
+ public virtual void WriteNormalMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) { }
+
+ public virtual void WriteOperatorSyntax (XPathNavigator reflection, SyntaxWriter writer) { }
+
+ public virtual void WriteCastSyntax (XPathNavigator reflection, SyntaxWriter writer) { }
+
+ public virtual void WriteAttachedPropertySyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ string getterId = (string)reflection.Evaluate(attachedPropertyGetterExpression);
+ string setterId = (string)reflection.Evaluate(attachedPropertySetterExpression);
+ if (!string.IsNullOrEmpty(getterId))
+ {
+ writer.WriteString("See ");
+ writer.WriteReferenceLink(getterId);
+ }
+ if (!string.IsNullOrEmpty(setterId))
+ {
+ if (!string.IsNullOrEmpty(getterId))
+ writer.WriteString(", ");
+ writer.WriteReferenceLink(setterId);
+ }
+ }
+
+ public virtual void WriteAttachedEventSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ string adderId = (string)reflection.Evaluate(attachedEventAdderExpression);
+ string removerId = (string)reflection.Evaluate(attachedEventRemoverExpression);
+ if (!(string.IsNullOrEmpty(adderId) && string.IsNullOrEmpty(removerId)))
+ {
+ writer.WriteString("See ");
+ writer.WriteReferenceLink(adderId);
+ writer.WriteString(", ");
+ writer.WriteReferenceLink(removerId);
+ }
+ }
+
+ protected virtual bool IsUnsupportedUnsafe(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ bool isUnsafe = (bool) reflection.Evaluate(apiIsUnsafeExpression);
+
+ if (isUnsafe) {
+ writer.WriteMessage("UnsupportedUnsafe_" + Language);
+ }
+
+ return(isUnsafe);
+ }
+
+ protected virtual bool IsUnsupportedGeneric (XPathNavigator reflection, SyntaxWriter writer) {
+
+ bool isGeneric = (bool) reflection.Evaluate(apiIsGenericExpression);
+
+ if (isGeneric) {
+ writer.WriteMessage("UnsupportedGeneric_" + Language);
+ }
+
+ return(isGeneric);
+
+ }
+
+ protected virtual bool IsUnsupportedExplicit (XPathNavigator reflection, SyntaxWriter writer) {
+
+ bool isExplicit = (bool) reflection.Evaluate(apiIsExplicitImplementationExpression);
+
+ if (isExplicit) {
+ writer.WriteMessage("UnsupportedExplicit_" + Language);
+ }
+
+ return(isExplicit);
+
+ }
+
+ }
+
+ public abstract class DeclarationSyntaxGeneratorTemplate : SyntaxGeneratorTemplate {
+
+ protected DeclarationSyntaxGeneratorTemplate (XPathNavigator configuration) : base(configuration) { }
+
+ // Methods to implement
+
+ protected abstract void WriteVisibility (XPathNavigator reflection, SyntaxWriter writer);
+
+ // Utility methods
+
+ protected static string[] SeperateTypes (string typelist) {
+ List<string> types = new List<string>();
+
+ int start = 0;
+ int specializationCount = 0;
+ for (int index=0; index<typelist.Length; index++) {
+ switch (typelist[index]) {
+ case '{':
+ specializationCount++;
+ break;
+ case '}':
+ specializationCount--;
+ break;
+ case ',':
+ if (specializationCount == 0) {
+ types.Add( "T:" + typelist.Substring(start, index-start) );
+ start = index + 1;
+ }
+ break;
+ }
+ }
+ types.Add( "T:" + typelist.Substring(start) );
+ return(types.ToArray());
+ }
+
+ protected static string GetTemplateParameterName (string reference, XPathNavigator reflection) {
+
+ string group = (string) reflection.Evaluate(apiGroupExpression);
+
+ XPathNavigator template = null;
+ if (reference.StartsWith("T:`")) {
+ if (reference[3]=='`') {
+
+ // a method template parameter
+
+ int position = Convert.ToInt32( reference.Substring(4) ) + 1;
+
+ if (group == "member") {
+ // we are in a method, so presumably it is one of that method's template parameters
+ template = reflection.SelectSingleNode( String.Format("templates/template[{0}]", position) );
+ }
+
+ } else {
+
+ // a type template parameter
+
+ int position = Convert.ToInt32( reference.Substring(3) ) + 1;
+
+ if (group == "type") {
+ // we are in a type, so look there for the parameter
+ template = reflection.SelectSingleNode( String.Format("templates/template[{0}]", position) );
+ }
+
+ if (template == null) {
+ // either we weren't in a type, or it didn't have the template
+ // so now look at the templates of the containing type
+ template = reflection.SelectSingleNode( String.Format("containers/container[@type]/templates/template[{0}]", position) );
+ }
+
+
+
+ }
+ }
+
+ if (template != null) {
+ return(template.GetAttribute("name", String.Empty));
+ } else {
+ Console.WriteLine("UNRESOLVED TEMPLATE PARAMETER NAME");
+ return("T");
+ }
+
+ }
+
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/VisualBasicDeclarationSyntax.cs b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/VisualBasicDeclarationSyntax.cs
new file mode 100644
index 0000000..e90ab1a
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/VisualBasicDeclarationSyntax.cs
@@ -0,0 +1,961 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class VisualBasicDeclarationSyntaxGenerator : SyntaxGeneratorTemplate {
+
+ public VisualBasicDeclarationSyntaxGenerator (XPathNavigator configuration) : base(configuration) {
+ if (String.IsNullOrEmpty(Language)) Language = "VisualBasic";
+ }
+
+ // namespace: done
+ public override void WriteNamespaceSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+
+ writer.WriteKeyword("Namespace");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ }
+
+ // class: done
+ public override void WriteClassSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isAbstract = (bool) reflection.Evaluate(apiIsAbstractTypeExpression);
+ bool isSealed = (bool) reflection.Evaluate(apiIsSealedTypeExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ if (isAbstract) {
+ if (isSealed) {
+ // static -- VB doesn't really handle this case
+ writer.WriteKeyword("NotInheritable");
+ writer.WriteString(" ");
+ } else {
+ writer.WriteKeyword("MustInherit");
+ writer.WriteString(" ");
+ }
+ } else if (isSealed) {
+ writer.WriteKeyword("NotInheritable");
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword("Class");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteGenericTemplates(reflection, writer);
+ WriteBaseClass(reflection, writer);
+ WriteImplementedInterfaces(reflection, writer);
+ }
+
+ // structure: add base type
+ public override void WriteStructureSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("Structure");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteGenericTemplates(reflection, writer);
+ WriteImplementedInterfaces(reflection, writer);
+ }
+
+ // interface: done
+ public override void WriteInterfaceSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("Interface");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteGenericTemplates(reflection, writer, true); // Need to write variance info for interfaces and delegates
+ WriteImplementedInterfaces(reflection, writer);
+ }
+
+ // delegate: done
+ public override void WriteDelegateSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+ XPathNavigator type = reflection.SelectSingleNode(apiReturnTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("Delegate");
+ writer.WriteString(" ");
+ if (type == null) {
+ writer.WriteKeyword("Sub");
+ } else {
+ writer.WriteKeyword("Function");
+ }
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteGenericTemplates(reflection, writer, true); // Need to write variance info for interfaces and delegates
+ WriteParameters(reflection, writer);
+ if (type != null) {
+ writer.WriteString(" ");
+ writer.WriteKeyword("As");
+ writer.WriteString(" ");
+ WriteTypeReference(type, writer);
+ }
+
+ }
+
+ // enumeration: done
+ public override void WriteEnumerationSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression);
+
+ if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("Enumeration");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ }
+
+ // constructor: done
+ public override void WriteConstructorSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+
+ bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression);
+
+ WriteAttributes(reflection, writer);
+ if (isStatic) {
+ writer.WriteKeyword("Shared");
+ } else {
+ WriteVisibility(reflection, writer);
+ }
+ writer.WriteString(" ");
+ writer.WriteKeyword("Sub");
+ writer.WriteString(" ");
+ writer.WriteIdentifier("New");
+ WriteParameters(reflection, writer);
+
+ }
+
+
+ public override void WriteNormalMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ XPathNavigator type = reflection.SelectSingleNode(apiReturnTypeExpression);
+ bool isExplicit = (bool) reflection.Evaluate(apiIsExplicitImplementationExpression);
+
+ WriteAttributes(reflection, writer);
+ WriteProcedureModifiers(reflection, writer);
+ if (type == null) {
+ writer.WriteKeyword("Sub");
+ } else {
+ writer.WriteKeyword("Function");
+ }
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteGenericTemplates(reflection, writer);
+ WriteParameters(reflection, writer);
+ if (type != null) {
+ writer.WriteString(" ");
+ writer.WriteKeyword("As");
+ writer.WriteString(" ");
+ WriteTypeReference(type, writer);
+ }
+ if (isExplicit) {
+ if (writer.Position > maxPosition) {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ } else {
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword("Implements");
+ writer.WriteString(" ");
+ XPathNodeIterator implementations = reflection.Select(apiImplementedMembersExpression);
+ while (implementations.MoveNext()) {
+ XPathNavigator implementation = implementations.Current;
+ XPathNavigator contract = implementation.SelectSingleNode(attributeTypeExpression);
+ // string id = implementation.GetAttribute("api", String.Empty);
+ if (implementations.CurrentPosition > 1) writer.WriteString(", ");
+ WriteTypeReference(contract, writer);
+ writer.WriteString(".");
+ WriteMemberReference(implementation, writer);
+ }
+ }
+
+ }
+
+ public override void WriteOperatorSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ XPathNavigator type = reflection.SelectSingleNode(apiReturnTypeExpression);
+
+ string identifier;
+ switch (name) {
+ // unary math operators
+ case "UnaryPlus":
+ identifier = "+";
+ break;
+ case "UnaryNegation":
+ identifier = "-";
+ break;
+ case "Increment":
+ identifier = "++";
+ break;
+ case "Decrement":
+ identifier = "--";
+ break;
+ // unary logical operators
+ case "LogicalNot":
+ identifier = "Not";
+ break;
+ case "True":
+ identifier = "IsTrue";
+ break;
+ case "False":
+ identifier = "IsFalse";
+ break;
+ // binary comparison operators
+ case "Equality":
+ identifier = "=";
+ break;
+ case "Inequality":
+ identifier = "<>";
+ break;
+ case "LessThan":
+ identifier = "<";
+ break;
+ case "GreaterThan":
+ identifier = ">";
+ break;
+ case "LessThanOrEqual":
+ identifier = "<=";
+ break;
+ case "GreaterThanOrEqual":
+ identifier = ">=";
+ break;
+ // binary math operators
+ case "Addition":
+ identifier = "+";
+ break;
+ case "Subtraction":
+ identifier = "-";
+ break;
+ case "Multiply":
+ identifier = "*";
+ break;
+ case "Division":
+ identifier = "/";
+ break;
+ case "Exponent":
+ identifier = "^";
+ break;
+ case "Modulus":
+ identifier = "Mod";
+ break;
+ case "IntegerDivision":
+ identifier = @"\";
+ break;
+ // binary logical operators
+ case "BitwiseAnd":
+ identifier = "And";
+ break;
+ case "BitwiseOr":
+ identifier = "Or";
+ break;
+ case "ExclusiveOr":
+ identifier = "Xor";
+ break;
+ // bit-array operators
+ case "OnesComplement":
+ identifier = "~";
+ break;
+ case "LeftShift":
+ identifier = "<<";
+ break;
+ case "RightShift":
+ identifier = ">>";
+ break;
+ // concatenation
+ case "Concatenate":
+ identifier = "&";
+ break;
+ // casting operators
+ case "Implicit":
+ case "Explicit":
+ identifier = "CType";
+ break;
+ // didn't recognize an operator
+ default:
+ identifier = null;
+ break;
+ }
+ if (identifier == null) {
+ writer.WriteMessage("UnsupportedOperator_" + Language);
+ return;
+ }
+ WriteProcedureModifiers(reflection, writer);
+ if (name == "Implicit") {
+ writer.WriteKeyword("Widening");
+ writer.WriteString(" ");
+ } else if (name == "Explicit") {
+ writer.WriteKeyword("Narrowing");
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword("Operator");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(identifier);
+ WriteParameters(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("As");
+ writer.WriteString(" ");
+ WriteTypeReference(type, writer);
+ }
+
+ public override void WriteCastSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ WriteOperatorSyntax(reflection, writer);
+ }
+
+ public override void WritePropertySyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool getter = (bool) reflection.Evaluate(apiIsReadPropertyExpression);
+ bool setter = (bool) reflection.Evaluate(apiIsWritePropertyExpression);
+ bool isDefault = (bool)reflection.Evaluate(apiIsDefaultMemberExpression);
+ bool isExplicit = (bool)reflection.Evaluate(apiIsExplicitImplementationExpression);
+ XPathNavigator type = reflection.SelectSingleNode(apiReturnTypeExpression);
+
+ WriteAttributes(reflection, writer);
+ WriteProcedureModifiers(reflection, writer);
+ if (getter && !setter) {
+ writer.WriteKeyword("ReadOnly");
+ writer.WriteString(" ");
+ } else if (setter && !getter) {
+ writer.WriteKeyword("WriteOnly");
+ writer.WriteString(" ");
+ }
+ if (isDefault) {
+ writer.WriteKeyword("Default");
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword("Property");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ WriteParameters(reflection, writer);
+ writer.WriteString(" ");
+ writer.WriteKeyword("As");
+ writer.WriteString(" ");
+ WriteTypeReference(type, writer);
+
+ if (isExplicit) {
+ if (writer.Position > maxPosition) {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ } else {
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword("Implements");
+ writer.WriteString(" ");
+ XPathNodeIterator implementations = reflection.Select(apiImplementedMembersExpression);
+ while (implementations.MoveNext()) {
+ XPathNavigator implementation = implementations.Current;
+ XPathNavigator contract = implementation.SelectSingleNode(memberDeclaringTypeExpression);
+ //string id = implementation.GetAttribute("api", String.Empty);
+ if (implementations.CurrentPosition > 1) writer.WriteString(", ");
+ WriteTypeReference(contract, writer);
+ writer.WriteString(".");
+ WriteMemberReference(implementation, writer);
+ //writer.WriteReferenceLink(id);
+ }
+ }
+
+ if (getter)
+ {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ string getVisibility = (string)reflection.Evaluate(apiGetVisibilityExpression);
+ if (!String.IsNullOrEmpty(getVisibility))
+ {
+ WriteVisibility(getVisibility, writer);
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword("Get");
+ }
+ if (setter)
+ {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ string setVisibility = (string)reflection.Evaluate(apiSetVisibilityExpression);
+ if (!String.IsNullOrEmpty(setVisibility))
+ {
+ WriteVisibility(setVisibility, writer);
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword("Set");
+ }
+ }
+
+
+ public override void WriteEventSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ XPathNavigator handler = reflection.SelectSingleNode(apiHandlerOfEventExpression);
+
+ WriteAttributes(reflection, writer);
+ WriteProcedureModifiers(reflection, writer);
+ writer.WriteString("Event");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ writer.WriteString(" ");
+ writer.WriteKeyword("As");
+ writer.WriteString(" ");
+ WriteTypeReference(handler, writer);
+ WriteExplicitImplementations(reflection, writer);
+ }
+
+ private void WriteExplicitImplementations (XPathNavigator reflection, SyntaxWriter writer) {
+ bool isExplicit = (bool)reflection.Evaluate(apiIsExplicitImplementationExpression);
+ if (isExplicit) {
+ if (writer.Position > maxPosition) {
+ writer.WriteLine();
+ writer.WriteString("\t");
+ } else {
+ writer.WriteString(" ");
+ }
+ writer.WriteKeyword("Implements");
+ writer.WriteString(" ");
+ XPathNodeIterator implementations = reflection.Select(apiImplementedMembersExpression);
+ while (implementations.MoveNext()) {
+ XPathNavigator implementation = implementations.Current;
+ XPathNavigator contract = implementation.SelectSingleNode(memberDeclaringTypeExpression);
+ //string id = implementation.GetAttribute("api", String.Empty);
+ if (implementations.CurrentPosition > 1) writer.WriteString(", ");
+ WriteTypeReference(contract, writer);
+ writer.WriteString(".");
+ WriteMemberReference(implementation, writer);
+ //writer.WriteReferenceLink(id);
+ }
+ }
+ }
+
+ private void WriteProcedureModifiers (XPathNavigator reflection, SyntaxWriter writer) {
+
+ // interface members don't get modified
+ string typeSubgroup = (string) reflection.Evaluate(apiContainingTypeSubgroupExpression);
+ if (typeSubgroup == "interface") return;
+
+ bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression);
+ bool isVirtual = (bool) reflection.Evaluate(apiIsVirtualExpression);
+ bool isAbstract = (bool) reflection.Evaluate(apiIsAbstractProcedureExpression);
+ bool isFinal = (bool) reflection.Evaluate(apiIsFinalExpression);
+ bool isOverride = (bool) reflection.Evaluate(apiIsOverrideExpression);
+
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ if (isStatic) {
+ writer.WriteKeyword("Shared");
+ writer.WriteString(" ");
+ } else {
+ if (isVirtual) {
+ if (isAbstract) {
+ writer.WriteKeyword("MustOverride");
+ writer.WriteString(" ");
+ } else if (isOverride) {
+ writer.WriteKeyword("Overrides");
+ writer.WriteString(" ");
+ if (isFinal) {
+ writer.WriteKeyword("NotOverridable");
+ writer.WriteString(" ");
+ }
+ } else {
+ if (!isFinal) {
+ writer.WriteKeyword("Overridable");
+ writer.WriteString(" ");
+ }
+ }
+ }
+ }
+
+ }
+
+ public override void WriteFieldSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression);
+ bool isLiteral = (bool) reflection.Evaluate(apiIsLiteralFieldExpression);
+ bool isInitOnly = (bool) reflection.Evaluate(apiIsInitOnlyFieldExpression);
+ bool isSerialized = (bool) reflection.Evaluate(apiIsSerializedFieldExpression);
+ XPathNavigator type = reflection.SelectSingleNode(apiReturnTypeExpression);
+
+ if (!isSerialized) WriteAttribute("T:System.NonSerializedAttribute", writer);
+ WriteAttributes(reflection, writer);
+ WriteVisibility(reflection, writer);
+ writer.WriteString(" ");
+ if (isStatic) {
+ if (isLiteral) {
+ writer.WriteKeyword("Const");
+ } else {
+ writer.WriteKeyword("Shared");
+ }
+ writer.WriteString(" ");
+ }
+ if (isInitOnly) {
+ writer.WriteKeyword("ReadOnly");
+ writer.WriteString(" ");
+ }
+ writer.WriteIdentifier(name);
+ writer.WriteString(" ");
+ writer.WriteKeyword("As");
+ writer.WriteString(" ");
+ WriteTypeReference(type, writer);
+
+ }
+
+ // Visibility
+ private void WriteVisibility(XPathNavigator reflection, SyntaxWriter writer) {
+
+ string visibility = (string)reflection.Evaluate(apiVisibilityExpression);
+ WriteVisibility(visibility, writer);
+ }
+
+ private void WriteVisibility (string visibility, SyntaxWriter writer) {
+
+ switch (visibility) {
+ case "public":
+ writer.WriteKeyword("Public");
+ break;
+ case "family":
+ writer.WriteKeyword("Protected");
+ break;
+ case "family or assembly":
+ writer.WriteKeyword("Protected Friend");
+ break;
+ case "family and assembly":
+ writer.WriteKeyword("Friend"); // not right, but same outside assembly
+ break;
+ case "assembly":
+ writer.WriteKeyword("Friend");
+ break;
+ case "private":
+ writer.WriteKeyword("Private");
+ break;
+ }
+
+ }
+
+ // Attributes
+
+ private void WriteAttribute (string reference, SyntaxWriter writer) {
+ WriteAttribute(reference, true, writer);
+ }
+
+ private void WriteAttribute (string reference, bool newLine, SyntaxWriter writer) {
+ writer.WriteString("<");
+ writer.WriteReferenceLink(reference);
+ writer.WriteString(">");
+ if (newLine) {
+ writer.WriteString(" _");
+ writer.WriteLine();
+ }
+ }
+
+ private void WriteAttributes (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator attributes = (XPathNodeIterator) reflection.Evaluate(apiAttributesExpression);
+
+ foreach (XPathNavigator attribute in attributes) {
+
+ XPathNavigator type = attribute.SelectSingleNode(attributeTypeExpression);
+ XPathNodeIterator arguments = (XPathNodeIterator) attribute.Select(attributeArgumentsExpression);
+ XPathNodeIterator assignments = (XPathNodeIterator) attribute.Select(attributeAssignmentsExpression);
+
+ writer.WriteString("<");
+ WriteTypeReference(type, writer);
+
+ if ((arguments.Count > 0) || (assignments.Count > 0)) {
+ writer.WriteString("(");
+ while (arguments.MoveNext()) {
+ XPathNavigator argument = arguments.Current;
+ if (arguments.CurrentPosition > 1) {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition) {
+ writer.WriteString(" _");
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ WriteValue(argument, writer);
+ }
+ if ((arguments.Count > 0) && (assignments.Count > 0)) writer.WriteString(", ");
+ while (assignments.MoveNext()) {
+ XPathNavigator assignment = assignments.Current;
+ if (assignments.CurrentPosition > 1) {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition) {
+ writer.WriteString(" _");
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ writer.WriteString((string) assignment.Evaluate(assignmentNameExpression));
+ writer.WriteString(" := ");
+ WriteValue(assignment, writer);
+
+ }
+ writer.WriteString(")");
+ }
+
+ writer.WriteString("> ");
+ writer.WriteString("_");
+ writer.WriteLine();
+ }
+
+ }
+
+ private void WriteValue (XPathNavigator parent, SyntaxWriter writer) {
+
+ XPathNavigator type = parent.SelectSingleNode(attributeTypeExpression);
+ XPathNavigator value = parent.SelectSingleNode(valueExpression);
+ if (value == null) Console.WriteLine("null value");
+
+ switch (value.LocalName) {
+ case "nullValue":
+ writer.WriteKeyword("Nothing");
+ break;
+ case "typeValue":
+ writer.WriteKeyword("GetType");
+ writer.WriteString("(");
+ WriteTypeReference(value.SelectSingleNode(typeExpression), writer);
+ writer.WriteString(")");
+ break;
+ case "enumValue":
+ XPathNodeIterator fields = value.SelectChildren(XPathNodeType.Element);
+ while (fields.MoveNext()) {
+ string name = fields.Current.GetAttribute("name", String.Empty);
+ if (fields.CurrentPosition > 1) {
+ writer.WriteString(" ");
+ writer.WriteKeyword("Or");
+ writer.WriteString(" ");
+ }
+ WriteTypeReference(type, writer);
+ writer.WriteString(".");
+ writer.WriteString(name);
+ }
+ break;
+ case "value":
+ string text = value.Value;
+ string typeId = type.GetAttribute("api", String.Empty);
+ switch (typeId) {
+ case "T:System.String":
+ writer.WriteString("\"");
+ writer.WriteString(text);
+ writer.WriteString("\"");
+ break;
+ case "T:System.Boolean":
+ bool bool_value = Convert.ToBoolean(text);
+ if (bool_value) {
+ writer.WriteKeyword("True");
+ } else {
+ writer.WriteKeyword("False");
+ }
+ break;
+ case "T:System.Char":
+ writer.WriteString("\"");
+ writer.WriteString(text);
+ writer.WriteString("\"C");
+ break;
+ }
+ break;
+ }
+ }
+
+
+ // Interfaces
+
+ private void WriteBaseClass (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNavigator baseClass = reflection.SelectSingleNode(apiBaseClassExpression);
+
+ if ((baseClass != null) && !((bool) baseClass.Evaluate(typeIsObjectExpression))) {
+ writer.WriteString(" _");
+ writer.WriteLine();
+ writer.WriteString("\t");
+ writer.WriteKeyword("Inherits");
+ writer.WriteString(" ");
+ WriteTypeReference(baseClass, writer);
+ }
+
+ }
+
+ private void WriteImplementedInterfaces (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator implements = reflection.Select(apiImplementedInterfacesExpression);
+
+ if (implements.Count == 0) return;
+
+ writer.WriteString(" _");
+ writer.WriteLine();
+ writer.WriteString("\t");
+ string subgroup = (string)reflection.Evaluate(apiSubgroupExpression);
+ if (subgroup == "interface")
+ writer.WriteKeyword("Inherits");
+ else
+ writer.WriteKeyword("Implements");
+ writer.WriteString(" ");
+ while (implements.MoveNext()) {
+ XPathNavigator implement = implements.Current;
+ if (implements.CurrentPosition > 1) {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition) {
+ writer.WriteString(" _");
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ WriteTypeReference(implement, writer);
+ }
+
+ }
+
+ // Generics
+
+ private void WriteGenericTemplates(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ WriteGenericTemplates(reflection, writer, false);
+ }
+
+ private void WriteGenericTemplates (XPathNavigator reflection, SyntaxWriter writer, bool writeVariance) {
+
+ XPathNodeIterator templates = reflection.Select(apiTemplatesExpression);
+
+ if (templates.Count == 0) return;
+ writer.WriteString("(");
+ writer.WriteKeyword("Of");
+ writer.WriteString(" ");
+ while (templates.MoveNext()) {
+ XPathNavigator template = templates.Current;
+ if (templates.CurrentPosition > 1) writer.WriteString(", ");
+
+ if (writeVariance)
+ {
+ bool contravariant = (bool)template.Evaluate(templateIsContravariantExpression);
+ bool covariant = (bool)template.Evaluate(templateIsCovariantExpression);
+
+ if (contravariant)
+ {
+ writer.WriteKeyword("In");
+ writer.WriteString(" ");
+ }
+ if (covariant)
+ {
+ writer.WriteKeyword("Out");
+ writer.WriteString(" ");
+ }
+ }
+
+ string name = template.GetAttribute("name", String.Empty);
+ writer.WriteString(name);
+
+ // write out constraints
+
+ bool constrained = (bool) template.Evaluate(templateIsConstrainedExpression);
+ if (constrained) {
+ writer.WriteString(" ");
+ writer.WriteKeyword("As");
+ writer.WriteString(" ");
+
+ bool value = (bool) template.Evaluate(templateIsValueTypeExpression);
+ bool reference = (bool) template.Evaluate(templateIsReferenceTypeExpression);
+ bool constructor = (bool) template.Evaluate(templateIsConstructableExpression);
+ XPathNodeIterator constraints = template.Select(templateConstraintsExpression);
+
+ int count = constraints.Count;
+ if (value) count++;
+ if (reference) count++;
+ if (constructor) count++;
+
+ if (count > 1) writer.WriteString("{");
+
+ int index = 0;
+ if (value) {
+ if (index > 0) writer.WriteString(", ");
+ writer.WriteKeyword("Structure");
+ index++;
+ }
+ if (reference) {
+ if (index > 0) writer.WriteString(", ");
+ writer.WriteKeyword("Class");
+ index++;
+ }
+ if (constructor) {
+ if (index > 0) writer.WriteString(", ");
+ writer.WriteKeyword("New");
+ index++;
+ }
+ foreach (XPathNavigator constraint in constraints) {
+ if (index > 0) writer.WriteString(", ");
+ WriteTypeReference(constraint, writer);
+ index++;
+ }
+
+ if (count > 1) writer.WriteString("}");
+
+ }
+
+ }
+ writer.WriteString(")");
+ }
+
+ // Parameters
+
+ private void WriteParameters (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+ if (parameters.Count == 0) return;
+
+ writer.WriteString(" ( _");
+ writer.WriteLine();
+ while (parameters.MoveNext()) {
+ XPathNavigator parameter = parameters.Current;
+ XPathNavigator type = parameter.SelectSingleNode(parameterTypeExpression);
+ string name = (string) parameter.Evaluate(parameterNameExpression);
+ bool isIn = (bool) parameter.Evaluate(parameterIsInExpression);
+ bool isOut = (bool) parameter.Evaluate(parameterIsOutExpression);
+ bool isParamArray = (bool) parameter.Evaluate(parameterIsParamArrayExpression);
+ bool isByRef = (bool) parameter.Evaluate(parameterIsRefExpression);
+
+ writer.WriteString("\t");
+ if (isOut) {
+ WriteAttribute("T:System.Runtime.InteropServices.OutAttribute", false, writer);
+ writer.WriteString(" ");
+ }
+ if (isParamArray) {
+ writer.WriteKeyword("ParamArray");
+ writer.WriteString(" ");
+ }
+ if (isByRef) {
+ writer.WriteKeyword("ByRef");
+ writer.WriteString(" ");
+ }
+ writer.WriteParameter(name);
+ writer.WriteString(" ");
+ writer.WriteKeyword("As");
+ writer.WriteString(" ");
+ WriteTypeReference(type, writer);
+ if (parameters.CurrentPosition < parameters.Count) writer.WriteString(",");
+ writer.WriteString(" _");
+ writer.WriteLine();
+ }
+ writer.WriteString(")");
+
+ }
+
+ // References
+
+ private void WriteTypeReference (XPathNavigator reference, SyntaxWriter writer) {
+ switch (reference.LocalName) {
+ case "arrayOf":
+ int rank = Convert.ToInt32( reference.GetAttribute("rank",String.Empty) );
+ XPathNavigator element = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(element, writer);
+ writer.WriteString("(");
+ for (int i=1; i<rank; i++) { writer.WriteString(","); }
+ writer.WriteString(")");
+ break;
+ case "pointerTo":
+ XPathNavigator pointee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(pointee, writer);
+ writer.WriteString("*");
+ break;
+ case "referenceTo":
+ XPathNavigator referee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(referee, writer);
+ break;
+ case "type":
+ string id = reference.GetAttribute("api", String.Empty);
+ WriteNormalTypeReference(id, writer);
+ XPathNodeIterator typeModifiers = reference.Select(typeModifiersExpression);
+ while (typeModifiers.MoveNext()) {
+ WriteTypeReference(typeModifiers.Current, writer);
+ }
+ break;
+ case "template":
+ string name = reference.GetAttribute("name", String.Empty);
+ writer.WriteString(name);
+ XPathNodeIterator modifiers = reference.Select(typeModifiersExpression);
+ while (modifiers.MoveNext()) {
+ WriteTypeReference(modifiers.Current, writer);
+ }
+ break;
+ case "specialization":
+ writer.WriteString("(");
+ writer.WriteKeyword("Of");
+ writer.WriteString(" ");
+ XPathNodeIterator arguments = reference.Select(specializationArgumentsExpression);
+ while (arguments.MoveNext()) {
+ if (arguments.CurrentPosition > 1) writer.WriteString(", ");
+ WriteTypeReference(arguments.Current, writer);
+ }
+ writer.WriteString(")");
+ break;
+ }
+ }
+
+ private void WriteNormalTypeReference (string reference, SyntaxWriter writer) {
+ switch (reference) {
+ case "T:System.Int16":
+ writer.WriteReferenceLink(reference, "Short");
+ break;
+ case "T:System.Int32":
+ writer.WriteReferenceLink(reference, "Integer");
+ break;
+ case "T:System.Int64":
+ writer.WriteReferenceLink(reference, "Long");
+ break;
+ case "T:System.UInt16":
+ writer.WriteReferenceLink(reference, "UShort");
+ break;
+ case "T:System.UInt32":
+ writer.WriteReferenceLink(reference, "UInteger");
+ break;
+ case "T:System.UInt64":
+ writer.WriteReferenceLink(reference, "ULong");
+ break;
+ default:
+ writer.WriteReferenceLink(reference);
+ break;
+ }
+ }
+
+ private void WriteMemberReference (XPathNavigator member, SyntaxWriter writer) {
+ string api = member.GetAttribute("api", String.Empty);
+ writer.WriteReferenceLink(api);
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/VisualBasicUsageSyntax.cs b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/VisualBasicUsageSyntax.cs
new file mode 100644
index 0000000..a32faf2
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/VisualBasicUsageSyntax.cs
@@ -0,0 +1,778 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ public class VisualBasicUsageSyntaxGenerator : SyntaxGeneratorTemplate {
+
+ public VisualBasicUsageSyntaxGenerator (XPathNavigator configuration) : base(configuration) {
+ if (String.IsNullOrEmpty(Language)) Language = "VisualBasicUsage";
+ }
+
+ public override void WriteNamespaceSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string)reflection.Evaluate(apiNameExpression);
+
+ writer.WriteKeyword("Imports");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(name);
+ }
+
+ private void TypeDeclaration(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ TypeDeclaration(reflection, writer, false);
+ }
+
+ private void TypeDeclaration (XPathNavigator reflection, SyntaxWriter writer, bool writeVariance) {
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
+
+ writer.WriteKeyword("Dim");
+ writer.WriteString(" ");
+ writer.WriteParameter("instance");
+ writer.WriteString(" ");
+ writer.WriteKeyword("As");
+ writer.WriteString(" ");
+ if (declaringType != null) {
+ WriteTypeReference(declaringType, writer);
+ writer.WriteString(".");
+ }
+ if (reservedWords.ContainsKey(name)) {
+ writer.WriteString("[");
+ writer.WriteIdentifier(name);
+ writer.WriteString("]");
+ } else {
+ writer.WriteIdentifier(name);
+ }
+ WriteGenericTemplates(reflection, writer, writeVariance);
+ }
+
+ private void WriteGenericTemplates(XPathNavigator type, SyntaxWriter writer, bool writeVariance)
+ {
+ XPathNodeIterator templates = type.Select(apiTemplatesExpression);
+
+ if (templates.Count == 0) return;
+ writer.WriteString("(");
+ writer.WriteKeyword("Of");
+ writer.WriteString(" ");
+ while (templates.MoveNext())
+ {
+ XPathNavigator template = templates.Current;
+ if (templates.CurrentPosition > 1) writer.WriteString(", ");
+ if (writeVariance)
+ {
+ bool contravariant = (bool)template.Evaluate(templateIsContravariantExpression);
+ bool covariant = (bool)template.Evaluate(templateIsCovariantExpression);
+
+ if (contravariant)
+ {
+ writer.WriteKeyword("In");
+ writer.WriteString(" ");
+ }
+ if (covariant)
+ {
+ writer.WriteKeyword("Out");
+ writer.WriteString(" ");
+ }
+ }
+
+ string name = template.GetAttribute("name", String.Empty);
+ writer.WriteString(name);
+ }
+ writer.WriteString(")");
+
+ }
+
+ private void WriteGenericTemplates (XPathNavigator type, SyntaxWriter writer) {
+ WriteGenericTemplates(type, writer, false);
+ }
+
+ private void ParameterDeclaration (string name, XPathNavigator type, SyntaxWriter writer) {
+ writer.WriteKeyword("Dim");
+ writer.WriteString(" ");
+ writer.WriteParameter(name);
+ writer.WriteString(" ");
+ writer.WriteKeyword("As");
+ writer.WriteString(" ");
+
+ string typeName = (string) type.Evaluate(apiNameExpression);
+
+ if (reservedWords.ContainsKey(typeName)) {
+ writer.WriteString("[");
+ WriteTypeReference(type, writer);
+ writer.WriteString("]");
+ } else {
+ WriteTypeReference(type, writer);
+ }
+
+ writer.WriteLine();
+ }
+
+ public override void WriteClassSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ bool isAbstract = (bool)reflection.Evaluate(apiIsAbstractTypeExpression);
+ bool isSealed = (bool)reflection.Evaluate(apiIsSealedTypeExpression);
+
+ if (isAbstract && isSealed) {
+ writer.WriteMessage("UnsupportedStaticClass_" + Language);
+ } else {
+ TypeDeclaration(reflection, writer);
+ }
+
+ }
+
+ public override void WriteStructureSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ TypeDeclaration(reflection, writer);
+ }
+
+ public override void WriteInterfaceSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ TypeDeclaration(reflection, writer, true); // Need to write variance info for interfaces and delegates
+ }
+
+ public override void WriteDelegateSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+
+ string name = (string)reflection.Evaluate(apiNameExpression);
+
+ writer.WriteKeyword("Dim");
+ writer.WriteString(" ");
+ writer.WriteParameter("instance");
+ writer.WriteString(" ");
+ writer.WriteKeyword("As");
+ writer.WriteString(" ");
+ writer.WriteKeyword("New");
+ writer.WriteString(" ");
+
+ if (reservedWords.ContainsKey(name)) {
+ writer.WriteString("[");
+ writer.WriteIdentifier(name);
+ writer.WriteString("]");
+ } else {
+ writer.WriteIdentifier(name);
+ }
+
+ WriteGenericTemplates(reflection, writer, true); // Need to write variance info for interfaces and delegates
+ writer.WriteString("(");
+ writer.WriteKeyword("AddressOf");
+ writer.WriteString(" HandlerMethod)");
+ }
+
+ public override void WriteEnumerationSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ TypeDeclaration(reflection, writer);
+ }
+
+ public override void WriteFieldSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+ bool isLiteral = (bool)reflection.Evaluate(apiIsLiteralFieldExpression);
+ bool isInitOnly = (bool)reflection.Evaluate(apiIsInitOnlyFieldExpression);
+ bool isFamily = (bool)reflection.Evaluate(apiIsFamilyMemberExpression);
+ XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
+ XPathNavigator fieldType = reflection.SelectSingleNode(apiReturnTypeExpression);
+
+ if (!(isStatic || isFamily)) ParameterDeclaration("instance", declaringType, writer);
+ ParameterDeclaration("value", fieldType, writer);
+
+ // get value
+ writer.WriteLine();
+ writer.WriteParameter("value");
+ writer.WriteString(" = ");
+ if (isStatic) {
+ WriteTypeReference(declaringType, writer);
+ } else {
+ if (isFamily) {
+ writer.WriteKeyword("Me");
+ } else {
+ writer.WriteParameter("instance");
+ }
+ }
+ writer.WriteString(".");
+ writer.WriteIdentifier(name);
+ writer.WriteLine();
+
+ // set value
+ if (isLiteral || isInitOnly) return;
+ writer.WriteLine();
+ if (isStatic) {
+ WriteTypeReference(declaringType, writer);
+ } else {
+ if (isFamily) {
+ writer.WriteKeyword("Me");
+ } else {
+ writer.WriteParameter("instance");
+ }
+ }
+ writer.WriteString(".");
+ writer.WriteIdentifier(name);
+ writer.WriteString(" = ");
+ writer.WriteParameter("value");
+
+ }
+
+ public override void WriteConstructorSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+
+ XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
+
+ // if static, no usage
+
+ WriteParameterDeclarations(reflection, writer);
+ writer.WriteLine();
+ writer.WriteKeyword("Dim");
+ writer.WriteString(" ");
+ writer.WriteParameter("instance");
+ writer.WriteString(" ");
+ writer.WriteKeyword("As New");
+ writer.WriteString(" ");
+
+ string typeName = (string)declaringType.Evaluate(apiNameExpression);
+
+ if (reservedWords.ContainsKey(typeName)) {
+ writer.WriteString("[");
+ WriteTypeReference(declaringType, writer);
+ writer.WriteString("]");
+ } else {
+ WriteTypeReference(declaringType, writer);
+ }
+
+ WriteMethodParameters(reflection, writer);
+ }
+
+ public override void WriteMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+ base.WriteMethodSyntax(reflection, writer);
+ }
+
+ public override void WriteNormalMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ bool isExtension = (bool)reflection.Evaluate(apiIsExtensionMethod);
+ if (isExtension) {
+ WriteExtensionMethodSyntax(reflection, writer);
+ } else {
+
+ //string name = (string)reflection.Evaluate(apiNameExpression);
+ XPathNavigator returnType = reflection.SelectSingleNode(apiReturnTypeExpression);
+ XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
+ //bool isExplicit = (bool)reflection.Evaluate(apiIsExplicitImplementationExpression);
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+ bool isFamily = (bool)reflection.Evaluate(apiIsFamilyMemberExpression);
+
+ if (!(isStatic || isFamily)) ParameterDeclaration("instance", declaringType, writer);
+ WriteParameterDeclarations(reflection, writer);
+ if (returnType != null) ParameterDeclaration("returnValue", returnType, writer);
+ writer.WriteLine();
+
+ if (returnType != null) {
+ writer.WriteParameter("returnValue");
+ writer.WriteString(" = ");
+ }
+
+ WriteMemberName(reflection, writer);
+ WriteMethodParameters(reflection, writer);
+
+ }
+ }
+
+ // what about generic methods?
+
+ private void WriteMemberName (XPathNavigator reflection, SyntaxWriter writer) {
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ bool isExplicit = (bool)reflection.Evaluate(apiIsExplicitImplementationExpression);
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+ bool isFamily = (bool)reflection.Evaluate(apiIsFamilyMemberExpression);
+ bool isDefault = (bool)reflection.Evaluate(apiIsDefaultMemberExpression);
+ XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
+ if (isExplicit) {
+ XPathNavigator member = reflection.SelectSingleNode(apiImplementedMembersExpression);
+ XPathNavigator contract = member.SelectSingleNode(memberDeclaringTypeExpression);
+ writer.WriteKeyword("CType");
+ writer.WriteString("(");
+ writer.WriteParameter("instance");
+ writer.WriteString(", ");
+ WriteTypeReference(contract, writer);
+ writer.WriteString(").");
+ WriteMemberReference(member, writer);
+ } else {
+ if (isStatic) {
+ WriteTypeReference(declaringType, writer);
+ } else {
+ if (isFamily) {
+ writer.WriteKeyword("Me");
+ } else {
+ writer.WriteString("instance");
+ }
+ }
+ if (!isDefault) {
+ writer.WriteString(".");
+ writer.WriteIdentifier(name);
+ }
+ }
+ }
+
+ private void WriteExtensionMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ XPathNavigator returnType = reflection.SelectSingleNode(apiReturnTypeExpression);
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+
+ // extract the first parameter as the extension type
+ parameters.MoveNext();
+ XPathNavigator extendedType = parameters.Current.SelectSingleNode(parameterTypeExpression);
+ string extendedTypeName = (string) parameters.Current.Evaluate(parameterNameExpression);
+
+ // write the declarations
+ ParameterDeclaration(extendedTypeName, extendedType, writer);
+ WriteParameterDeclarations(parameters.Clone(), writer);
+ if (returnType != null) ParameterDeclaration("returnValue", returnType, writer);
+ writer.WriteLine();
+
+ // write the method invocation
+ if (returnType != null) {
+ writer.WriteParameter("returnValue");
+ writer.WriteString(" = ");
+ }
+ writer.WriteParameter(extendedTypeName);
+ writer.WriteString(".");
+ writer.WriteIdentifier(name);
+ writer.WriteString("(");
+ WriteParameters(parameters.Clone(), reflection, writer);
+ writer.WriteString(")");
+
+ }
+
+ public override void WriteOperatorSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ string name = (string) reflection.Evaluate(apiNameExpression);
+ XPathNavigator returnType = reflection.SelectSingleNode(apiReturnTypeExpression);
+
+ // Determine operator identifier and type
+ string identifier;
+ int type;
+ switch (name) {
+ // unary math operators
+ case "UnaryPlus":
+ identifier = "+";
+ type = -1;
+ break;
+ case "UnaryNegation":
+ identifier = "-";
+ type = -1;
+ break;
+ case "Increment":
+ identifier = "++";
+ type = +1;
+ break;
+ case "Decrement":
+ identifier = "--";
+ type = +1;
+ break;
+ // unary logical operators
+ case "LogicalNot":
+ identifier = "Not";
+ type = -1;
+ break;
+ case "True":
+ identifier = "IsTrue";
+ type = -1;
+ break;
+ case "False":
+ identifier = "IsFalse";
+ type = -1;
+ break;
+ // binary comparison operators
+ case "Equality":
+ identifier = "=";
+ type = 2;
+ break;
+ case "Inequality":
+ identifier = "<>";
+ type = 2;
+ break;
+ case "LessThan":
+ identifier = "<";
+ type = 2;
+ break;
+ case "GreaterThan":
+ identifier = ">";
+ type = 2;
+ break;
+ case "LessThanOrEqual":
+ identifier = "<=";
+ type = 2;
+ break;
+ case "GreaterThanOrEqual":
+ identifier = ">=";
+ type = 2;
+ break;
+ // binary math operators
+ case "Addition":
+ identifier = "+";
+ type = 2;
+ break;
+ case "Subtraction":
+ identifier = "-";
+ type = 2;
+ break;
+ case "Multiply":
+ identifier = "*";
+ type = 2;
+ break;
+ case "Division":
+ identifier = "/";
+ type = 2;
+ break;
+ case "Exponent":
+ identifier = "^";
+ type = 2;
+ break;
+ case "Modulus":
+ identifier = "Mod";
+ type = 2;
+ break;
+ case "IntegerDivision":
+ identifier = @"\";
+ type = 2;
+ break;
+ // binary logical operators
+ case "BitwiseAnd":
+ identifier = "And";
+ type = 2;
+ break;
+ case "BitwiseOr":
+ identifier = "Or";
+ type = 2;
+ break;
+ case "ExclusiveOr":
+ identifier = "Xor";
+ type = 2;
+ break;
+ // bit-array operators
+ case "OnesComplement":
+ identifier = "~";
+ type = -1;
+ break;
+ case "LeftShift":
+ identifier = "<<";
+ type = 2;
+ break;
+ case "RightShift":
+ identifier = ">>";
+ type = 2;
+ break;
+ // concatenation
+ case "Concatenate":
+ identifier = "&";
+ type = 2;
+ break;
+ // didn't recognize an operator
+ default:
+ identifier = null;
+ type = 0;
+ break;
+ }
+
+ if (identifier == null) {
+ writer.WriteMessage("UnsupportedOperator_" + Language);
+ } else {
+
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+ if (parameters.Count != Math.Abs(type)) {
+ writer.WriteMessage("UnsupportedOperator_" + Language);
+ return;
+ } //throw new InvalidOperationException("An operator has the wrong number of parameters.");
+
+ WriteParameterDeclarations(reflection, writer);
+ ParameterDeclaration("returnValue", returnType, writer);
+ writer.WriteLine();
+ writer.WriteParameter("returnValue");
+ writer.WriteString(" = ");
+ switch (type) {
+ case -1:
+ writer.WriteIdentifier(identifier);
+ parameters.MoveNext();
+ writer.WriteParameter((string)parameters.Current.Evaluate(parameterNameExpression));
+ break;
+ case +1:
+ parameters.MoveNext();
+ writer.WriteParameter((string)parameters.Current.Evaluate(parameterNameExpression));
+ writer.WriteIdentifier(identifier);
+ break;
+ case 2:
+ writer.WriteString("(");
+
+ // parameter 1
+ parameters.MoveNext();
+ writer.WriteParameter((string)parameters.Current.Evaluate(parameterNameExpression));
+
+ writer.WriteString(" ");
+ writer.WriteIdentifier(identifier);
+ writer.WriteString(" ");
+
+ // parameter 2
+ parameters.MoveNext();
+ writer.WriteParameter((string)parameters.Current.Evaluate(parameterNameExpression));
+
+ writer.WriteString(")");
+ break;
+ }
+ }
+
+ }
+
+ public override void WriteCastSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ XPathNavigator parameter = reflection.SelectSingleNode(apiParametersExpression);
+ if (parameter == null) return;
+ XPathNavigator inputType = parameter.SelectSingleNode(typeExpression);
+ XPathNavigator outputType = reflection.SelectSingleNode(apiReturnTypeExpression);
+ if ((inputType == null) || (outputType == null)) return;
+
+ ParameterDeclaration("input", inputType, writer);
+ ParameterDeclaration("output", outputType, writer);
+ writer.WriteLine();
+ writer.WriteParameter("output");
+ writer.WriteString(" = ");
+ writer.WriteKeyword("CType");
+ writer.WriteString("(");
+ writer.WriteParameter("input");
+ writer.WriteString(", ");
+ WriteTypeReference(outputType, writer);
+ writer.WriteString(")");
+ }
+
+ public override void WritePropertySyntax (XPathNavigator reflection, SyntaxWriter writer) {
+
+ if (IsUnsupportedUnsafe(reflection, writer)) return;
+
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+ bool isFamily = (bool)reflection.Evaluate(apiIsFamilyMemberExpression);
+ XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
+ XPathNavigator propertyType = reflection.SelectSingleNode(apiReturnTypeExpression);
+ bool getter = (bool)reflection.Evaluate(apiIsReadPropertyExpression);
+ bool setter = (bool)reflection.Evaluate(apiIsWritePropertyExpression);
+
+ if (!(isStatic || isFamily)) ParameterDeclaration("instance", declaringType, writer);
+ WriteParameterDeclarations(reflection, writer);
+ ParameterDeclaration("value", propertyType, writer);
+
+ // get value
+ if (getter) {
+ string getVisibility = (string)reflection.Evaluate(apiGetVisibilityExpression);
+ if (string.IsNullOrEmpty(getVisibility) || (getVisibility != "assembly" &&
+ getVisibility != "private" && getVisibility != "family and assembly"))
+ {
+ writer.WriteLine();
+ writer.WriteParameter("value");
+ writer.WriteString(" = ");
+ WriteMemberName(reflection, writer);
+ WritePropertyParameters(reflection, writer);
+ writer.WriteLine();
+ }
+ }
+
+ // set value
+ if (setter) {
+ string setVisibility = (string)reflection.Evaluate(apiSetVisibilityExpression);
+ if (string.IsNullOrEmpty(setVisibility) || (setVisibility != "assembly" &&
+ setVisibility != "private" && setVisibility != "family and assembly"))
+ {
+ writer.WriteLine();
+ WriteMemberName(reflection, writer);
+ WritePropertyParameters(reflection, writer);
+ writer.WriteString(" = ");
+ writer.WriteParameter("value");
+ }
+ }
+
+ }
+
+ public override void WriteEventSyntax (XPathNavigator reflection, SyntaxWriter writer) {
+ bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
+ bool isFamily = (bool)reflection.Evaluate(apiIsFamilyMemberExpression);
+ XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
+ XPathNavigator handler = reflection.SelectSingleNode(apiHandlerOfEventExpression);
+
+ if (!(isStatic | isFamily)) ParameterDeclaration("instance", declaringType, writer);
+ ParameterDeclaration("handler", handler, writer);
+
+ // adder
+ writer.WriteLine();
+ writer.WriteKeyword("AddHandler");
+ writer.WriteString(" ");
+ WriteMemberName(reflection, writer);
+ writer.WriteString(", ");
+ writer.WriteParameter("handler");
+ writer.WriteLine();
+ }
+
+ private void WriteParameterDeclarations (XPathNavigator reflection, SyntaxWriter writer) {
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+ if (parameters.Count == 0) return;
+ WriteParameterDeclarations(parameters, writer);
+ }
+
+ private void WriteParameterDeclarations (XPathNodeIterator parameters, SyntaxWriter writer) {
+ while (parameters.MoveNext()) {
+ XPathNavigator parameter = parameters.Current;
+ XPathNavigator type = parameter.SelectSingleNode(parameterTypeExpression);
+ string name = (string)parameter.Evaluate(parameterNameExpression);
+ ParameterDeclaration(name, type, writer);
+ }
+ }
+
+ private void WriteMethodParameters (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+
+ writer.WriteString("(");
+ if (parameters.Count > 0) {
+ WriteParameters(parameters, reflection, writer);
+ }
+ writer.WriteString(")");
+
+ }
+
+ private void WritePropertyParameters (XPathNavigator reflection, SyntaxWriter writer) {
+
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+
+ if (parameters.Count == 0) return;
+
+ writer.WriteString("(");
+ WriteParameters(parameters, reflection, writer);
+ writer.WriteString(")");
+
+ }
+
+
+ private void WriteParameters(XPathNodeIterator parameters, XPathNavigator reflection, SyntaxWriter writer)
+ {
+ while (parameters.MoveNext())
+ {
+ XPathNavigator parameter = parameters.Current;
+ string name = (string)parameter.Evaluate(parameterNameExpression);
+ writer.WriteParameter(name);
+
+ if (parameters.CurrentPosition < parameters.Count)
+ {
+ writer.WriteString(", ");
+ if (writer.Position > maxPosition)
+ {
+ writer.WriteString("_");
+ writer.WriteLine();
+ writer.WriteString("\t");
+ }
+ }
+ }
+ }
+
+ private void WriteTypeReference (XPathNavigator reference, SyntaxWriter writer) {
+ switch (reference.LocalName) {
+ case "arrayOf":
+ int rank = Convert.ToInt32(reference.GetAttribute("rank", String.Empty));
+ XPathNavigator element = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(element, writer);
+ writer.WriteString("(");
+ for (int i = 1; i < rank; i++) { writer.WriteString(","); }
+ writer.WriteString(")");
+ break;
+ case "pointerTo":
+ XPathNavigator pointee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(pointee, writer);
+ writer.WriteString("*");
+ break;
+ case "referenceTo":
+ XPathNavigator referee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(referee, writer);
+ break;
+ case "type":
+ string id = reference.GetAttribute("api", String.Empty);
+ WriteNormalTypeReference(id, writer);
+ XPathNodeIterator typeModifiers = reference.Select(typeModifiersExpression);
+ while (typeModifiers.MoveNext()) {
+ WriteTypeReference(typeModifiers.Current, writer);
+ }
+ break;
+ case "template":
+ string name = reference.GetAttribute("name", String.Empty);
+ writer.WriteString(name);
+ XPathNodeIterator modifiers = reference.Select(typeModifiersExpression);
+ while (modifiers.MoveNext()) {
+ WriteTypeReference(modifiers.Current, writer);
+ }
+ break;
+ case "specialization":
+ writer.WriteString("(");
+ writer.WriteKeyword("Of");
+ writer.WriteString(" ");
+ XPathNodeIterator arguments = reference.Select(specializationArgumentsExpression);
+ while (arguments.MoveNext()) {
+ if (arguments.CurrentPosition > 1) writer.WriteString(", ");
+ WriteTypeReference(arguments.Current, writer);
+ }
+ writer.WriteString(")");
+ break;
+ }
+ }
+
+ private void WriteNormalTypeReference (string reference, SyntaxWriter writer) {
+ switch (reference) {
+ case "T:System.Int16":
+ writer.WriteReferenceLink(reference, "Short");
+ break;
+ case "T:System.Int32":
+ writer.WriteReferenceLink(reference, "Integer");
+ break;
+ case "T:System.Int64":
+ writer.WriteReferenceLink(reference, "Long");
+ break;
+ case "T:System.UInt16":
+ writer.WriteReferenceLink(reference, "UShort");
+ break;
+ case "T:System.UInt32":
+ writer.WriteReferenceLink(reference, "UInteger");
+ break;
+ case "T:System.UInt64":
+ writer.WriteReferenceLink(reference, "ULong");
+ break;
+ default:
+ writer.WriteReferenceLink(reference);
+ break;
+ }
+ }
+
+ private void WriteMemberReference (XPathNavigator member, SyntaxWriter writer) {
+ string api = member.GetAttribute("api", String.Empty);
+ writer.WriteReferenceLink(api);
+ }
+
+ private static Dictionary<string, object> reservedWords = new Dictionary<string, object>();
+
+ static VisualBasicUsageSyntaxGenerator () {
+ reservedWords.Add("Alias", null);
+ reservedWords.Add("Assembly", null);
+ reservedWords.Add("Class", null);
+ reservedWords.Add("Delegate", null);
+ reservedWords.Add("Function", null);
+ reservedWords.Add("Handles", null);
+ reservedWords.Add("Interface", null);
+ reservedWords.Add("Loop", null);
+ reservedWords.Add("Module", null);
+ reservedWords.Add("New", null);
+ reservedWords.Add("Next", null);
+ reservedWords.Add("Nothing", null);
+ reservedWords.Add("Operator", null);
+ reservedWords.Add("Option", null);
+ reservedWords.Add("Property", null);
+ reservedWords.Add("Structure", null);
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/XamlUsageSyntax.cs b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/XamlUsageSyntax.cs
new file mode 100644
index 0000000..5a6b590
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/XamlUsageSyntax.cs
@@ -0,0 +1,953 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Xml.XPath;
+using System.Configuration;
+using System.IO;
+
+namespace Microsoft.Ddue.Tools
+{
+ public class XamlUsageSyntaxGenerator : SyntaxGeneratorTemplate
+ {
+
+ public XamlUsageSyntaxGenerator(XPathNavigator configuration)
+ : base(configuration)
+ {
+ LoadConfigNode(configuration);
+ if (String.IsNullOrEmpty(Language)) Language = "XAML";
+ }
+
+ public override void WriteSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ writer.WriteStartBlock(Language);
+
+ // Check the list of assemblies for which to generate XAML syntax
+ string assemblyName = (string)reflection.Evaluate(apiContainingAssemblyExpression);
+ string namespaceName = (string)reflection.Evaluate(apiContainingNamespaceNameExpression);
+ if (!xamlAssemblies.ContainsKey(assemblyName.ToLower()))
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.nonXamlAssemblyBoilerplate, writer);
+ }
+ else
+ {
+ string group = (string)reflection.Evaluate(apiGroupExpression);
+ switch (group)
+ {
+ case "namespace":
+ WriteNamespaceSyntax(reflection, writer);
+ break;
+ case "type":
+ WriteTypeSyntax(reflection, writer);
+ break;
+ case "member":
+ WriteMemberSyntax(reflection, writer);
+ break;
+ }
+ WriteXamlXmlnsUri(assemblyName, namespaceName, writer);
+ }
+
+ writer.WriteEndBlock();
+ }
+
+ private void WriteXamlXmlnsUri(string assemblyName, string namespaceName, SyntaxWriter writer)
+ {
+ Dictionary<string, List<string>> clrNamespaces;
+ if (xamlAssemblies.TryGetValue(assemblyName.ToLower(), out clrNamespaces))
+ {
+ List<string> xmlnsUriList;
+ if (clrNamespaces.TryGetValue(namespaceName, out xmlnsUriList))
+ {
+ foreach (string xmlnsUri in xmlnsUriList)
+ {
+ // start the syntax block
+ writer.WriteStartSubBlock("xamlXmlnsUri");
+ writer.WriteString(xmlnsUri);
+ writer.WriteEndSubBlock();
+ }
+ }
+ }
+ }
+
+ // list of classes whose subclasses do NOT get XAML syntax
+ protected List<string> excludedAncestorList = new List<string>();
+
+ // list of assemblies whose members get XAML syntax
+ // the nested Dictionary is a list of assembly's namespaces that have one or more xmlns uris for xaml
+ private Dictionary<string, Dictionary<string, List<string>>> xamlAssemblies = new Dictionary<string, Dictionary<string, List<string>>>();
+
+
+ private void LoadConfigNode(XPathNavigator configuration)
+ {
+ // get the filter files
+ XPathNodeIterator filterNodes = configuration.Select("filter");
+ if (filterNodes.Count == 0)
+ {
+ LoadConfiguration(configuration);
+ return;
+ }
+
+ foreach (XPathNavigator filterNode in filterNodes)
+ {
+ string filterFiles = filterNode.GetAttribute("files", String.Empty);
+ if ((filterFiles == null) || (filterFiles.Length == 0))
+ throw new ConfigurationErrorsException("The XamlUsageSyntaxGenerator filter/@files attribute must specify a path.");
+ ParseDocuments(filterFiles);
+ }
+ }
+
+ private void LoadConfiguration(XPathNavigator configuration)
+ {
+ // get the list of excluded ancestor classes
+ foreach (XPathNavigator excludedClass in configuration.Select("xamlExcludedAncestors/class"))
+ {
+ string apiId = excludedClass.GetAttribute("api", string.Empty);
+ if (apiId.Length > 0 && !excludedAncestorList.Contains(apiId))
+ excludedAncestorList.Add(apiId);
+ }
+
+ // get the list of XAML assemblies; members in other assemblies get no xaml syntax, just 'not applicable' boilerplate
+ foreach (XPathNavigator xamlAssembly in configuration.Select("xamlAssemblies/assembly"))
+ {
+ string assemblyName = xamlAssembly.GetAttribute("name", string.Empty);
+ if (string.IsNullOrEmpty(assemblyName))
+ continue; // should emit warning message
+
+ Dictionary<string, List<string>> clrNamespaces;
+ if (!xamlAssemblies.TryGetValue(assemblyName.ToLower(), out clrNamespaces))
+ {
+ clrNamespaces = new Dictionary<string, List<string>>();
+ xamlAssemblies.Add(assemblyName.ToLower(), clrNamespaces);
+ }
+
+ foreach (XPathNavigator xmlnsNode in xamlAssembly.Select("xmlns[@uri][clrNamespace]"))
+ {
+ string xmlnsUri = xmlnsNode.GetAttribute("uri", string.Empty);
+ if (string.IsNullOrEmpty(xmlnsUri))
+ continue; // should emit warning message
+
+ foreach (XPathNavigator clrNamespaceNode in xmlnsNode.Select("clrNamespace[@name]"))
+ {
+ string namespaceName = clrNamespaceNode.GetAttribute("name", string.Empty);
+ if (string.IsNullOrEmpty(namespaceName))
+ continue; // should emit warning message
+
+ List<string> xmlnsUriList;
+ if (!clrNamespaces.TryGetValue(namespaceName, out xmlnsUriList))
+ {
+ xmlnsUriList = new List<string>();
+ clrNamespaces.Add(namespaceName, xmlnsUriList);
+ }
+ if (!xmlnsUriList.Contains(xmlnsUri))
+ xmlnsUriList.Add(xmlnsUri);
+ }
+ }
+ }
+ }
+
+ public void ParseDocuments(string wildcardPath)
+ {
+ string filterFiles = Environment.ExpandEnvironmentVariables(wildcardPath);
+ if ((filterFiles == null) || (filterFiles.Length == 0))
+ throw new ConfigurationErrorsException("The XamlUsageSyntaxGenerator filter path is an empty string.");
+
+ //WriteMessage(MessageLevel.Info, String.Format("XamlUsageSyntaxGenerator: Searching for files that match '{0}'.", filterFiles));
+ string directoryPart = Path.GetDirectoryName(filterFiles);
+ if (String.IsNullOrEmpty(directoryPart))
+ directoryPart = Environment.CurrentDirectory;
+ directoryPart = Path.GetFullPath(directoryPart);
+ string filePart = Path.GetFileName(filterFiles);
+ string[] files = Directory.GetFiles(directoryPart, filePart);
+ foreach (string file in files)
+ ParseDocument(file);
+ //WriteMessage(MessageLevel.Info, String.Format("Found {0} files in {1}.", files.Length, filterFiles));
+ }
+
+ private void ParseDocument(string file)
+ {
+ try
+ {
+ XPathDocument document = new XPathDocument(file);
+
+ XPathNavigator xamlSyntaxNode = document.CreateNavigator().SelectSingleNode("/*");
+ LoadConfiguration(xamlSyntaxNode);
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationErrorsException(string.Format("Exception parsing XamlUsageSyntaxGenerator filter file: {0}. Exception message: {1}", file, e.Message));
+ }
+ }
+
+ public override void WriteNamespaceSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ // empty xaml syntax for namespace topics
+ }
+
+ private void WriteXamlBoilerplate(XamlBoilerplateID bpID, SyntaxWriter writer)
+ {
+ WriteXamlBoilerplate(bpID, null, writer);
+ }
+
+ private void WriteXamlBoilerplate(XamlBoilerplateID bpID, XPathNavigator typeReflection, SyntaxWriter writer)
+ {
+ string xamlBlockId = System.Enum.GetName(typeof(XamlBoilerplateID), bpID);
+ if (xamlBlockId != null)
+ {
+ writer.WriteStartSubBlock(xamlBlockId);
+ if (typeReflection != null)
+ WriteTypeReference(typeReflection, writer);
+ writer.WriteEndSubBlock();
+ }
+ }
+
+ public override void WriteClassSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ string name = reflection.Evaluate(apiNameExpression).ToString();
+ bool isAbstract = (bool)reflection.Evaluate(apiIsAbstractTypeExpression);
+ bool isSealed = (bool)reflection.Evaluate(apiIsSealedTypeExpression);
+ bool isSerializable = (bool)reflection.Evaluate(apiIsSerializableTypeExpression);
+ //
+ if (isAbstract && !isSealed)
+ {
+ // Output boilerplate for abstract class
+ WriteXamlBoilerplate(XamlBoilerplateID.classXamlSyntax_abstract, writer);
+ }
+ else if (!HasDefaultConstructor(reflection))
+ {
+ if (HasTypeConverterAttribute(reflection))
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.classXamlSyntax_noDefaultCtorWithTypeConverter, writer);
+ }
+ else
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.classXamlSyntax_noDefaultCtor, writer);
+ }
+ }
+ else if (IsExcludedSubClass(reflection))
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.classXamlSyntax_excludedSubClass, writer);
+ }
+ else
+ {
+ // show the default XAML syntax for classes
+ // Note: skipped the test for TypeConverterAttribute shown in the flowchart because same syntax either way
+ ObjectElementUsageForClassStruct(reflection, writer);
+ }
+ }
+
+ private void ObjectElementUsageForClassStruct(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ string typeName = (string)reflection.Evaluate(apiNameExpression);
+ bool isGeneric = (bool)reflection.Evaluate(apiIsGenericExpression);
+ string xamlBlockId = System.Enum.GetName(typeof(XamlHeadingID), XamlHeadingID.xamlObjectElementUsageHeading);
+
+ string contentPropertyId = (string)reflection.Evaluate(contentPropertyIdExpression);
+ if (contentPropertyId == "")
+ contentPropertyId = (string)reflection.Evaluate(ancestorContentPropertyIdExpression);
+
+ // start the syntax block
+ writer.WriteStartSubBlock(xamlBlockId);
+
+ writer.WriteString("<");
+ if (isGeneric)
+ {
+ writer.WriteIdentifier(typeName);
+
+ // for generic types show the type arguments
+ XPathNodeIterator templates = (XPathNodeIterator)reflection.Evaluate(apiTemplatesExpression);
+ if (templates.Count > 0)
+ {
+ writer.WriteString(" x:TypeArguments=\"");
+ while (templates.MoveNext())
+ {
+ XPathNavigator template = templates.Current;
+ string name = template.GetAttribute("name", String.Empty);
+ writer.WriteString(name);
+ if (templates.CurrentPosition < templates.Count)
+ writer.WriteString(",");
+ }
+ writer.WriteString("\"");
+ }
+ }
+ else
+ {
+ // for non-generic types just show the name
+ writer.WriteIdentifier(typeName);
+ }
+ if (contentPropertyId == string.Empty)
+ {
+ writer.WriteString(" .../>");
+ }
+ else
+ {
+ // close the start tag
+ writer.WriteString(">");
+
+ // the inner xml of the Object Element syntax for a type with a content property
+ // is a link to the content property
+ writer.WriteLine();
+ writer.WriteString(" ");
+ writer.WriteReferenceLink(contentPropertyId);
+ writer.WriteLine();
+
+ // write the end tag
+ writer.WriteString("</");
+ writer.WriteIdentifier(typeName);
+ writer.WriteString(">");
+ }
+
+ // end the sub block
+ writer.WriteEndSubBlock();
+ }
+
+
+ public override void WriteStructureSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ string name = (string)reflection.Evaluate(apiNameExpression);
+ bool notWriteable = (bool)reflection.Evaluate(noSettablePropertiesExpression);
+
+ if (notWriteable)
+ {
+ // Output boilerplate for struct with no writeable properties
+ WriteXamlBoilerplate(XamlBoilerplateID.structXamlSyntax_nonXaml, writer);
+ }
+ else
+ {
+ // All writeable structs in XAML assemblies are usable in XAML
+ // always show the Object Element Usage syntax
+ ObjectElementUsageForClassStruct(reflection, writer);
+
+ // For structs with TypeConverterAttribute,
+ // if we can show multiple syntax blocks, also output AttributeUsage boilerplate
+ if (HasTypeConverterAttribute(reflection))
+ WriteXamlBoilerplate(XamlBoilerplateID.structXamlSyntax_attributeUsage, writer);
+ }
+ }
+
+ public override void WriteInterfaceSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.interfaceOverviewXamlSyntax, writer);
+ }
+
+ public override void WriteDelegateSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.delegateOverviewXamlSyntax, writer);
+ }
+
+ public override void WriteEnumerationSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.enumerationOverviewXamlSyntax, writer);
+ }
+
+ public override void WriteConstructorSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.constructorOverviewXamlSyntax, writer);
+ }
+
+ public override void WriteMethodSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.methodOverviewXamlSyntax, writer);
+ }
+
+ public override void WriteAttachedPropertySyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ string propertyName = (string)reflection.Evaluate(apiNameExpression);
+ string containingTypeName = (string)reflection.Evaluate(apiContainingTypeNameExpression);
+ bool isSettable = (bool)reflection.Evaluate(apiIsWritePropertyExpression);
+ XPathNavigator returnType = reflection.SelectSingleNode(apiReturnTypeExpression);
+ if (!isSettable)
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.propertyXamlSyntax_readOnly, writer);
+ }
+ else
+ {
+ // xaml syntax block for attached property
+ string xamlBlockId = System.Enum.GetName(typeof(XamlHeadingID), XamlHeadingID.xamlAttributeUsageHeading);
+ writer.WriteStartSubBlock(xamlBlockId);
+ writer.WriteString("<");
+ writer.WriteParameter("object");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(containingTypeName + "." + propertyName);
+ writer.WriteString("=\"");
+ WriteTypeReference(returnType, writer);
+ writer.WriteString("\" .../>");
+ writer.WriteEndSubBlock();
+ }
+ }
+
+ public override void WritePropertySyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ //containingTypeSubgroupExpression
+ string propertyName = (string)reflection.Evaluate(apiNameExpression);
+ bool isSettable = (bool)reflection.Evaluate(apiIsWritePropertyExpression);
+ bool isSetterPublic = (bool)reflection.Evaluate(apiIsSetterPublicExpression);
+ bool isAbstract = (bool)reflection.Evaluate(apiIsAbstractProcedureExpression);
+ string propertyVisibility = (string)reflection.Evaluate(apiVisibilityExpression);
+ XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
+
+ XPathNavigator returnType = reflection.SelectSingleNode(apiReturnTypeExpression);
+ bool notWriteableReturnType = (bool)returnType.Evaluate(noSettablePropertiesExpression);
+ string returnTypeId = returnType.GetAttribute("api", string.Empty);
+ string returnTypeSubgroup = (string)returnType.Evaluate(apiSubgroupExpression);
+ bool returnTypeIsAbstract = (bool)returnType.Evaluate(apiIsAbstractTypeExpression);
+ bool returnTypeIsReadonlyStruct = (returnTypeSubgroup == "structure" && notWriteableReturnType && !IsPrimitiveType(returnTypeId));
+
+ XPathNavigator containingType = reflection.SelectSingleNode(apiContainingTypeExpression);
+ string containingTypeSubgroup = (string)containingType.Evaluate(apiSubgroupExpression);
+
+ // an ordinary property, not an attached prop
+ if (containingTypeSubgroup == "interface")
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.propertyXamlSyntax_noXamlSyntaxForInterfaceMembers, writer);
+ }
+ else if ((bool)containingType.Evaluate(apiIsAbstractTypeExpression) && (bool)containingType.Evaluate(apiIsSealedTypeExpression))
+ {
+ // the property's containing type is static if it's abstract and sealed
+ // members of a static class cannot be used in XAML.
+ WriteXamlBoilerplate(XamlBoilerplateID.propertyXamlSyntax_nonXamlParent, writer);
+ }
+ else if (IsExcludedSubClass(containingType))
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.propertyXamlSyntax_parentIsExcludedSubClass, writer);
+ }
+ else if (!DoesParentSupportXaml(reflection))
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.propertyXamlSyntax_nonXamlParent, writer);
+ }
+ else if (propertyVisibility != "public")
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.propertyXamlSyntax_notPublic, writer);
+ }
+ else if (isAbstract)
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.propertyXamlSyntax_abstract, writer);
+ }
+ else if (parameters.Count > 0)
+ {
+ // per DDUERELTools bug 1373: indexer properties cannot be used in XAML
+ WriteXamlBoilerplate(XamlBoilerplateID.propertyXamlSyntax_nonXaml, writer);
+ }
+ else if (IsContentProperty(reflection) && !returnTypeIsReadonlyStruct)
+ {
+ PropertyContentElementUsageSimple(reflection, writer);
+ }
+ else if (!isSettable || !isSetterPublic)
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.propertyXamlSyntax_readOnly, writer);
+ }
+ else if (returnTypeIsAbstract)
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.propertyXamlSyntax_abstractType, returnType, writer);
+ }
+ else if (IsPrimitiveType(returnTypeId))
+ {
+ PropertyAttributeUsage(reflection, writer);
+ }
+ else if (returnTypeSubgroup == "enumeration")
+ {
+ PropertyAttributeUsage(reflection, writer);
+ }
+ else
+ {
+ bool hasDefaultConstructor = HasDefaultConstructor(returnType);
+ if (HasTypeConverterAttribute(returnType))
+ {
+ if (hasDefaultConstructor && !returnTypeIsReadonlyStruct)
+ {
+ PropertyElementUsageGrande(reflection, writer);
+ }
+ PropertyAttributeUsage(reflection, writer);
+ }
+ else if (hasDefaultConstructor && !returnTypeIsReadonlyStruct)
+ {
+ PropertyElementUsageGrande(reflection, writer);
+ }
+ else
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.propertyXamlSyntax_nonXaml, writer);
+ }
+ }
+ }
+
+ // A simple Property Element Usage block for a content property
+ // syntax looks like:
+ // <object>
+ // <linkToType .../>
+ // </object>
+ private void PropertyContentElementUsageSimple(XPathNavigator propertyReflection, SyntaxWriter writer)
+ {
+ string xamlBlockId = System.Enum.GetName(typeof(XamlHeadingID), XamlHeadingID.xamlContentElementUsageHeading);
+ XPathNavigator returnType = propertyReflection.SelectSingleNode(apiReturnTypeExpression);
+
+ // start the syntax block
+ writer.WriteStartSubBlock(xamlBlockId);
+
+ // <object>
+ writer.WriteString("<");
+ writer.WriteParameter("object");
+ writer.WriteString(">");
+ writer.WriteLine();
+ // <linkToType .../>
+ writer.WriteString(" <");
+ WriteTypeReference(returnType, writer);
+ writer.WriteString(" .../>");
+ writer.WriteLine();
+ // </object>
+ writer.WriteString("</");
+ writer.WriteParameter("object");
+ writer.WriteString(">");
+
+ writer.WriteEndSubBlock();
+ }
+
+ // A grandiose Property Element Usage block
+ // syntax looks like:
+ // <object>
+ // <object.PropertyName>
+ // <linkToType .../>
+ // </object.PropertyName>
+ // </object>
+ private void PropertyElementUsageGrande(XPathNavigator propertyReflection, SyntaxWriter writer)
+ {
+ string xamlBlockId = System.Enum.GetName(typeof(XamlHeadingID), XamlHeadingID.xamlPropertyElementUsageHeading);
+ string propertyName = (string)propertyReflection.Evaluate(apiNameExpression);
+ XPathNavigator returnType = propertyReflection.SelectSingleNode(apiReturnTypeExpression);
+
+ // start the syntax block
+ writer.WriteStartSubBlock(xamlBlockId);
+
+ // <object>
+ writer.WriteString("<");
+ writer.WriteParameter("object");
+ writer.WriteString(">");
+ writer.WriteLine();
+ // <object.PropertyName>
+ writer.WriteString(" <");
+ writer.WriteParameter("object");
+ writer.WriteString(".");
+ writer.WriteIdentifier(propertyName);
+ writer.WriteString(">");
+ writer.WriteLine();
+ // <linkToType .../>
+ writer.WriteString(" <");
+ WriteTypeReference(returnType, writer);
+ writer.WriteString(" .../>");
+ writer.WriteLine();
+ // </object.PropertyName>
+ writer.WriteString(" </");
+ writer.WriteParameter("object");
+ writer.WriteString(".");
+ writer.WriteIdentifier(propertyName);
+ writer.WriteString(">");
+ writer.WriteLine();
+ // </object>
+ writer.WriteString("</");
+ writer.WriteParameter("object");
+ writer.WriteString(">");
+
+ writer.WriteEndSubBlock();
+ }
+
+ // An Attribute Usage block
+ private void PropertyAttributeUsage(XPathNavigator propertyReflection, SyntaxWriter writer)
+ {
+ string xamlBlockId = System.Enum.GetName(typeof(XamlHeadingID), XamlHeadingID.xamlAttributeUsageHeading);
+ string propertyName = (string)propertyReflection.Evaluate(apiNameExpression);
+ XPathNavigator returnType = propertyReflection.SelectSingleNode(apiReturnTypeExpression);
+
+ // start the syntax block
+ writer.WriteStartSubBlock(xamlBlockId);
+
+ // syntax looks like:
+ // <object PropertyName="linkToType" .../>
+ writer.WriteString("<");
+ writer.WriteParameter("object");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(propertyName);
+ writer.WriteString("=\"");
+ WriteTypeReference(returnType, writer);
+ writer.WriteString("\" .../>");
+
+ writer.WriteEndSubBlock();
+ }
+
+ public override void WriteEventSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ string eventName = (string)reflection.Evaluate(apiNameExpression);
+ string eventVisibility = (string)reflection.Evaluate(apiVisibilityExpression);
+ bool isAbstract = (bool)reflection.Evaluate(apiIsAbstractProcedureExpression);
+ XPathNavigator eventHandler = reflection.SelectSingleNode(apiHandlerOfEventExpression);
+
+ XPathNavigator containingType = reflection.SelectSingleNode(apiContainingTypeExpression);
+ string containingTypeSubgroup = (string)containingType.Evaluate(apiSubgroupExpression);
+ bool containingTypeIsAbstract = (bool)containingType.Evaluate(apiIsAbstractTypeExpression);
+ bool containingTypeIsSealed = (bool)containingType.Evaluate(apiIsSealedTypeExpression);
+
+ if (containingTypeSubgroup == "interface")
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.eventXamlSyntax_noXamlSyntaxForInterfaceMembers, writer);
+ }
+ else if (containingTypeIsAbstract && containingTypeIsSealed)
+ {
+ // the event's containing type is static if it's abstract and sealed
+ // members of a static class cannot be used in XAML.
+ WriteXamlBoilerplate(XamlBoilerplateID.eventXamlSyntax_nonXamlParent, writer);
+ }
+ else if (IsExcludedSubClass(containingType))
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.eventXamlSyntax_parentIsExcludedSubClass, writer);
+ }
+ else if (!DoesParentSupportXaml(reflection))
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.eventXamlSyntax_nonXamlParent, writer);
+ }
+ else if (eventVisibility != "public")
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.eventXamlSyntax_notPublic, writer);
+ }
+ else if (isAbstract)
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.eventXamlSyntax_abstract, writer);
+ }
+ else
+ {
+ // start the syntax block
+ string xamlBlockId = System.Enum.GetName(typeof(XamlHeadingID), XamlHeadingID.xamlAttributeUsageHeading);
+ writer.WriteStartSubBlock(xamlBlockId);
+
+ // syntax looks like:
+ // <object eventName="eventHandlerLink" .../>
+ writer.WriteString("<");
+ writer.WriteParameter("object");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(eventName);
+ writer.WriteString("=\"");
+ WriteTypeReference(eventHandler, writer);
+ writer.WriteString("\" .../>");
+
+ writer.WriteEndSubBlock();
+ }
+ }
+
+ public override void WriteAttachedEventSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ string eventName = (string)reflection.Evaluate(apiNameExpression);
+ string containingTypeName = (string)reflection.Evaluate(apiContainingTypeNameExpression);
+ XPathNavigator eventHandler = reflection.SelectSingleNode(apiHandlerOfEventExpression);
+
+ // xaml syntax block for attached event
+ string xamlBlockId = System.Enum.GetName(typeof(XamlHeadingID), XamlHeadingID.xamlAttributeUsageHeading);
+ writer.WriteStartSubBlock(xamlBlockId);
+
+ writer.WriteString("<");
+ writer.WriteParameter("object");
+ writer.WriteString(" ");
+ writer.WriteIdentifier(containingTypeName + "." + eventName);
+ writer.WriteString("=\"");
+ WriteTypeReference(eventHandler, writer);
+ writer.WriteString(string.Format("\" .../>"));
+
+ writer.WriteEndSubBlock();
+ }
+
+ public override void WriteFieldSyntax(XPathNavigator reflection, SyntaxWriter writer)
+ {
+ WriteXamlBoilerplate(XamlBoilerplateID.fieldOverviewXamlSyntax, writer);
+ }
+
+ // References
+
+ private void WriteTypeReference(XPathNavigator reference, SyntaxWriter writer)
+ {
+ switch (reference.LocalName)
+ {
+ case "arrayOf":
+ int rank = Convert.ToInt32(reference.GetAttribute("rank", String.Empty));
+ XPathNavigator element = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(element, writer);
+ writer.WriteString("[");
+ for (int i = 1; i < rank; i++) { writer.WriteString(","); }
+ writer.WriteString("]");
+ break;
+ case "pointerTo":
+ XPathNavigator pointee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(pointee, writer);
+ writer.WriteString("*");
+ break;
+ case "referenceTo":
+ XPathNavigator referee = reference.SelectSingleNode(typeExpression);
+ WriteTypeReference(referee, writer);
+ break;
+ case "type":
+ string id = reference.GetAttribute("api", String.Empty);
+
+ XPathNavigator outerTypeReference = reference.SelectSingleNode(typeOuterTypeExpression);
+ if (outerTypeReference != null)
+ {
+ WriteTypeReference(outerTypeReference, writer);
+ writer.WriteString(".");
+ }
+
+ WriteNormalTypeReference(id, writer);
+ XPathNodeIterator typeModifiers = reference.Select(typeModifiersExpression);
+ while (typeModifiers.MoveNext())
+ {
+ WriteTypeReference(typeModifiers.Current, writer);
+ }
+ break;
+ case "template":
+ string name = reference.GetAttribute("name", String.Empty);
+ writer.WriteString(name);
+ XPathNodeIterator modifiers = reference.Select(typeModifiersExpression);
+ while (modifiers.MoveNext())
+ {
+ WriteTypeReference(modifiers.Current, writer);
+ }
+ break;
+ case "specialization":
+ writer.WriteString("<");
+ XPathNodeIterator arguments = reference.Select(specializationArgumentsExpression);
+ while (arguments.MoveNext())
+ {
+ if (arguments.CurrentPosition > 1) writer.WriteString(", ");
+ WriteTypeReference(arguments.Current, writer);
+ }
+ writer.WriteString(">");
+ break;
+ }
+ }
+
+ private void WriteNormalTypeReference(string reference, SyntaxWriter writer)
+ {
+ switch (reference)
+ {
+ case "T:System.Void":
+ writer.WriteReferenceLink(reference, "void");
+ break;
+ case "T:System.String":
+ writer.WriteReferenceLink(reference, "string");
+ break;
+ case "T:System.Boolean":
+ writer.WriteReferenceLink(reference, "bool");
+ break;
+ case "T:System.Byte":
+ writer.WriteReferenceLink(reference, "byte");
+ break;
+ case "T:System.SByte":
+ writer.WriteReferenceLink(reference, "sbyte");
+ break;
+ case "T:System.Char":
+ writer.WriteReferenceLink(reference, "char");
+ break;
+ case "T:System.Int16":
+ writer.WriteReferenceLink(reference, "short");
+ break;
+ case "T:System.Int32":
+ writer.WriteReferenceLink(reference, "int");
+ break;
+ case "T:System.Int64":
+ writer.WriteReferenceLink(reference, "long");
+ break;
+ case "T:System.UInt16":
+ writer.WriteReferenceLink(reference, "ushort");
+ break;
+ case "T:System.UInt32":
+ writer.WriteReferenceLink(reference, "uint");
+ break;
+ case "T:System.UInt64":
+ writer.WriteReferenceLink(reference, "ulong");
+ break;
+ case "T:System.Single":
+ writer.WriteReferenceLink(reference, "float");
+ break;
+ case "T:System.Double":
+ writer.WriteReferenceLink(reference, "double");
+ break;
+ case "T:System.Decimal":
+ writer.WriteReferenceLink(reference, "decimal");
+ break;
+ default:
+ writer.WriteReferenceLink(reference);
+ break;
+ }
+ }
+
+ // utility routines
+
+
+ // A default constructor is a a parameterless, public constructor method
+ // This is called for:
+ // a class
+ // the declaring type of a member
+ // the type of a property
+ private bool HasDefaultConstructor(XPathNavigator typeReflection)
+ {
+ // all structs have implicit default constructors
+ string subgroup = (string)typeReflection.Evaluate(apiSubgroupExpression);
+ if (subgroup == "structure")
+ return true;
+
+ return (bool)typeReflection.Evaluate(hasDefaultConstructorExpression);
+ }
+
+ // This is called to check for a "TypeConverterAttribute" on:
+ // a class or structure topic
+ // the declaring type of a property or event member
+ // the type of a property
+ private bool HasTypeConverterAttribute(XPathNavigator typeReflection)
+ {
+ return (bool)typeReflection.Evaluate(hasTypeConverterAttributeExpression);
+ }
+
+ // Get the id of the content property, if any, for the property's containing type
+ // return true if the content property id matches the current property's id
+ private bool IsContentProperty(XPathNavigator propertyReflection)
+ {
+ string propertyName = (string)propertyReflection.Evaluate(apiNameExpression);
+ XPathNavigator containingType = propertyReflection.SelectSingleNode(apiContainingTypeExpression);
+ string containingTypeName = (string)containingType.Evaluate(apiNameExpression);
+ string namespaceId = (string)propertyReflection.Evaluate(apiContainingNamespaceIdExpression);
+ string propertyId = string.Concat("P:", namespaceId.Substring(2), ".", string.Concat(containingTypeName, ".", propertyName));
+ string contentPropertyId = (string)containingType.Evaluate(contentPropertyIdExpression);
+ if (propertyId == contentPropertyId)
+ return true;
+ else
+ return false;
+ }
+
+ // Check the list of subclasses to exclude
+ // This is called to check the class ancestors of
+ // a class
+ // the declaring type of a property or event member
+ private bool IsExcludedSubClass(XPathNavigator typeReflection)
+ {
+ XPathNodeIterator ancestors = (XPathNodeIterator)typeReflection.Evaluate(apiAncestorsExpression);
+
+ foreach (XPathNavigator ancestor in ancestors)
+ {
+ string ancestorId = ancestor.GetAttribute("api", string.Empty);
+ if (excludedAncestorList.Contains(ancestorId))
+ return true;
+ }
+ return false;
+ }
+
+ // Check the parent type of a property or event.
+ // Does it have the necessary characteristics so the property or event can be used in XAML?
+ // Is PARENT CLASS abstract OR does it have a default ctor OR a class-level TypeConverter attribute?
+ private bool DoesParentSupportXaml(XPathNavigator memberReflection)
+ {
+ XPathNavigator containingType = memberReflection.SelectSingleNode(apiContainingTypeExpression);
+ if ((bool)containingType.Evaluate(apiIsAbstractTypeExpression))
+ return true;
+
+ if (HasDefaultConstructor(containingType))
+ return true;
+
+ if (HasTypeConverterAttribute(containingType))
+ return true;
+
+ // A property that returns a String doesn't need a TypeConverterAttribute, so return true here
+ XPathNavigator returnType = memberReflection.SelectSingleNode(apiReturnTypeExpression);
+ if (returnType != null)
+ {
+ string returnTypeId = returnType.GetAttribute("api", string.Empty);
+ if (returnTypeId == "T:System.String")
+ return true;
+ }
+
+ return false;
+ }
+
+ private bool IsPrimitiveType(string typeId)
+ {
+ // The primitive types are Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, Char, Double, and Single.
+ switch (typeId)
+ {
+ case "T:System.Boolean":
+ case "T:System.Byte":
+ case "T:System.SByte":
+ case "T:System.Int16":
+ case "T:System.UInt16":
+ case "T:System.Int32":
+ case "T:System.UInt32":
+ case "T:System.Int64":
+ case "T:System.UInt64":
+ case "T:System.IntPtr":
+ case "T:System.Char":
+ case "T:System.Double":
+ case "T:System.Single":
+ case "T:System.String": // String is not a primitive but is treated as one for this XAML purpose
+ return true;
+ default:
+ return false;
+ }
+ }
+
+
+ private XPathExpression hasTypeConverterAttributeExpression = XPathExpression.Compile("boolean(attributes/attribute/type[@api='T:System.ComponentModel.TypeConverterAttribute'])");
+
+ private XPathExpression hasDefaultConstructorExpression = XPathExpression.Compile("boolean(typedata/@defaultConstructor)");
+
+ private XPathExpression contentPropertyNameExpression = XPathExpression.Compile("string(attributes/attribute[type[contains(@api,'.ContentPropertyAttribute')]]/argument/value/.)");
+ private XPathExpression contentPropertyIdExpression = XPathExpression.Compile("string(typedata/@contentProperty)");
+ private XPathExpression ancestorContentPropertyIdExpression = XPathExpression.Compile("string(family/ancestors/type/@contentProperty)");
+
+ private XPathExpression noSettablePropertiesExpression = XPathExpression.Compile("boolean(typedata/@noSettableProperties)");
+
+ private XPathExpression apiIsSetterPublicExpression = XPathExpression.Compile("boolean((memberdata[@visibility='public'] and not(propertydata[@set-visibility!='public'])) or propertydata[@set-visibility='public'])");
+ }
+
+ public enum XamlBoilerplateID
+ {
+ // boilerplate for classes in xaml assemblies
+ classXamlSyntax_abstract,
+ classXamlSyntax_excludedSubClass,
+ classXamlSyntax_noDefaultCtor,
+ classXamlSyntax_noDefaultCtorWithTypeConverter,
+ // boilerplate for structs in xaml assemblies
+ structXamlSyntax_nonXaml,
+ structXamlSyntax_attributeUsage,
+ // boilerplate for events in xaml assemblies
+ eventXamlSyntax_parentIsExcludedSubClass,
+ eventXamlSyntax_noXamlSyntaxForInterfaceMembers,
+ eventXamlSyntax_nonXamlParent,
+ eventXamlSyntax_notPublic,
+ eventXamlSyntax_abstract,
+ eventXamlSyntax_nonXaml,
+ // boilerplate for properties in xaml assemblies
+ propertyXamlSyntax_parentIsExcludedSubClass,
+ propertyXamlSyntax_noXamlSyntaxForInterfaceMembers,
+ propertyXamlSyntax_nonXamlParent,
+ propertyXamlSyntax_notPublic,
+ propertyXamlSyntax_abstract,
+ propertyXamlSyntax_readOnly,
+ propertyXamlSyntax_abstractType,
+ propertyXamlSyntax_nonXaml,
+ // syntax used with all enums in xaml assemblies
+ enumerationOverviewXamlSyntax,
+ // boilerplate used with all method, field, etc. in xaml assemblies
+ delegateOverviewXamlSyntax,
+ interfaceOverviewXamlSyntax,
+ constructorOverviewXamlSyntax,
+ fieldOverviewXamlSyntax,
+ methodOverviewXamlSyntax,
+ // boilerplate used with all types and members in all non-xaml assemblies
+ nonXamlAssemblyBoilerplate
+ }
+
+ // XAML headings
+ public enum XamlHeadingID
+ {
+ xamlAttributeUsageHeading,
+ xamlObjectElementUsageHeading,
+ xamlPropertyElementUsageHeading,
+ xamlContentElementUsageHeading,
+ xamlSyntaxBoilerplateHeading
+ }
+
+
+}