ReplaceNamespaceDocEntries

Topics: Features
Jul 13, 2009 at 9:20 AM

Hello

I am thinking about how the behaviour of resolving NamespaceDoc classes to Namespace Documentation summaries is done in DocProject.

Can someone explain me how to?

Thanks Jed.

Jul 14, 2009 at 12:33 AM

Sorry to say that the sandcastle community is like olive oil.

 

// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PathUtil.cs" company="EvePanix">
//   Copyright (c) Jedzia 2009, EvePanix. All rights reserved.
//
// Author: Jedzia
// Contact: Jedzia (jed69@gmx.de)
//
// This file is part of OmberZombie.
//
// This is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License (GPL) as
// published by the Free Software Foundation version 2 of the License.
// -------------------------------------------------------------------------------------------------------------
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// .
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// .
// This is distributed in the hope that it will be useful.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// .
// You should have received a copy of the GNU General Public License
// along with OmberZombie; if not, write to:
// .
// Free Software Foundation, Inc.
// 59 Temple Place
// Suite 330
// Boston
// MA  02111-1307  USA
// </copyright>
// <summary>
//   Provides custom helper functions for use with DocProject.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Jedzia.SHFBRelContent
{
    #region Imports

    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.IO;
    using System.Text.RegularExpressions;
    using System.Xml;

    using DaveSexton.DocProject;
    using DaveSexton.DocProject.Engine;

    using EnvDTE;

    using structzDocSite;

    #endregion

    /// <summary>
    /// Provides custom helper functions for use with DocProject.
    /// </summary>
    static class PathUtil
    {
        #region Delegates

        /// <summary>
        /// Represents a directory filter method.
        /// </summary>
        /// <param name="dir">
        /// The Current DirectoryInfo to apply filtering to.
        /// </param>
        public delegate bool Dirfunction(DirectoryInfo dir);

        /// <summary>
        /// Represents a file filter method.
        /// </summary>
        /// <param name="file">
        /// The Current FileInfo to apply filtering to.
        /// </param>
        public delegate bool Filefunction(FileInfo file);

        /// <summary>
        /// Represents the method that will display a log message.
        /// </summary>
        /// <param name="message">
        /// The message to display.
        /// </param>
        public delegate void Logfunction(string message);

        /// <summary>
        /// Represents the method that will display a tracer message that is 
        /// shown during DocProject builds.
        /// </summary>
        /// <param name="message">
        /// The message to display.
        /// </param>
        public delegate void TracerMessage(string message);

        #endregion

        /// <summary>
        /// Users desktop path.
        /// </summary>
        public static readonly string DesktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

        /// <summary>
        /// Users MyDocuments path.
        /// </summary>
        public static readonly string MyDocumentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

        /// <summary>
        /// Creates a relative path from one file
        /// or folder to another.
        /// </summary>
        /// <param name="fromDirectory">
        /// Contains the directory that defines the
        /// start of the relative path.
        /// </param>
        /// <param name="toPath">
        /// Contains the path that defines the
        /// endpoint of the relative path.
        /// </param>
        /// <returns>
        /// The relative path from the start
        /// directory to the end path.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// </exception>
        public static string RelativePathTo(string fromDirectory, string toPath)
        {
            if (fromDirectory == null)
            {
                throw new ArgumentNullException("fromDirectory");
            }

            if (toPath == null)
            {
                throw new ArgumentNullException("toPath");
            }

            bool isRooted = Path.IsPathRooted(fromDirectory) && Path.IsPathRooted(toPath);

            if (isRooted)
            {
                bool isDifferentRoot =
                    String.Compare(Path.GetPathRoot(fromDirectory), Path.GetPathRoot(toPath), true) != 0;
                if (isDifferentRoot)
                {
                    return toPath;
                }
            }

            StringCollection relativePath = new StringCollection();
            string[] fromDirectories = fromDirectory.Split(Path.DirectorySeparatorChar);

            string[] toDirectories = toPath.Split(Path.DirectorySeparatorChar);

            int length = Math.Min(fromDirectories.Length, toDirectories.Length);

            int lastCommonRoot = -1;

            // find common root
            for (int x = 0; x < length; x++)
            {
                if (String.Compare(fromDirectories[x], toDirectories[x], true) != 0)
                {
                    break;
                }

                lastCommonRoot = x;
            }

            if (lastCommonRoot == -1)
            {
                return toPath;
            }

            // add relative folders in from path
            for (int x = lastCommonRoot + 1; x < fromDirectories.Length; x++)
            {
                if (fromDirectories[x].Length > 0)
                {
                    relativePath.Add("..");
                }
            }

            // add to folders to path
            for (int x = lastCommonRoot + 1; x < toDirectories.Length; x++)
            {
                relativePath.Add(toDirectories[x]);
            }

            // create relative path
            string[] relativeParts = new string[relativePath.Count];
            relativePath.CopyTo(relativeParts, 0);

            string newPath = String.Join(Path.DirectorySeparatorChar.ToString(), relativeParts);

            return newPath;
        }

        /// <summary>
        /// Traverse a directory tree(stack based).
        /// </summary>
        /// <param name="root">
        /// The root directory.
        /// </param>
        /// <returns>
        /// A list of fileInfos representing the found files.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// <c>ArgumentException</c>.
        /// </exception>
        public static List<FileInfo> TraverseTree(string root)
        {
            return TraverseTree(root, null);
        }

        /// <summary>
        /// Traverse a directory tree(stack based).
        /// </summary>
        /// <param name="root">The root directory.</param>
        /// <param name="filefunction">The filefunction. When this is not null then its called with the file name
        /// and should return
        /// <b>true</b> if that file should be added to the result list. You
        /// can perform filename filtering with that.</param>
        /// <returns>
        /// A list of fileInfos representing the found files.
        /// </returns>
        public static List<FileInfo> TraverseTree(string root, Filefunction filefunction)
        {
            return TraverseTree(root, filefunction, null);
        }

        /// <summary>
        /// Traverses a directory with wildcards.
        /// </summary>
        /// <param name="root">The root directory.</param>
        /// <param name="logfunction">The method used for logging purposes.</param>
        /// <param name="dirpattern">The pattern that the directories have to match.</param>
        /// <param name="filepattern">The pattern that the files have to match.</param>
        /// <returns>
        /// A list of fileInfos representing the found files.
        /// </returns>
        public static List<FileInfo> TraverseWithWildcards(
            string root, Logfunction logfunction, string dirpattern, string filepattern)
        {
            return TraverseTree(
                root,
                delegate(DirectoryInfo info) { return Match(info.Name, dirpattern, false); },
                delegate(FileInfo info) { return Match(info.Name, filepattern, false); },
                null);
        }

        /// <summary>
        /// Traverses a directory with wildcards.
        /// </summary>
        /// <param name="root">The root directory.</param>
        /// <param name="logfunction">The method used for logging purposes.</param>
        /// <param name="filepattern">The pattern that the files have to match.</param>
        /// <returns>
        /// A list of fileInfos representing the found files.
        /// </returns>
        public static List<FileInfo> TraverseWithWildcards(string root, Logfunction logfunction, string filepattern)
        {
            return TraverseTree(
                root, null, delegate(FileInfo info) { return Match(info.Name, filepattern, false); }, null);
        }

        /// <summary>
        /// Traverse a directory tree(stack based).
        /// </summary>
        /// <exception cref="ArgumentException">
        /// <c>ArgumentException</c>.
        /// </exception>
        /// <param name="root">The root directory.</param>
        /// <param name="filefunction">The filefunction. When this is not null then its called with the file name
        /// and should return
        /// <b>true</b> if that file should be added to the result list. You
        /// can perform filename filtering with that.</param>
        /// <param name="logfunction">The method used for logging purposes.</param>
        /// <returns>
        /// A list of fileInfos representing the found files.
        /// </returns>
        public static List<FileInfo> TraverseTree(string root, Filefunction filefunction, Logfunction logfunction)
        {
            return TraverseTree(root, null, filefunction, logfunction);
        }

        /// <summary>
        /// Traverse a directory tree(stack based).
        /// </summary>
        /// <param name="root">The root directory.</param>
        /// <param name="dirfunction">The dirfunction. When this is not null then its called with the directory name
        /// and should return
        /// <b>true</b> if that directory should be added to the result list. You
        /// can perform directory filtering with that.</param>
        /// <param name="filefunction">The filefunction. When this is not null then its called with the file name
        /// and should return
        /// <b>true</b> if that file should be added to the result list. You
        /// can perform filename filtering with that.</param>
        /// <param name="logfunction">The method used for logging purposes.</param>
        /// <returns>
        /// A list of fileInfos representing the found files.
        /// </returns>
        /// <exception cref="ArgumentException">The specified root directory does not exist</exception>
        public static List<FileInfo> TraverseTree(
           string root, Dirfunction dirfunction, Filefunction filefunction, Logfunction logfunction)
        {
            // Data structure to hold names of subfolders to be
            // examined for files.
            Stack<string> dirs = new Stack<string>(20);
            List<FileInfo> fileInfos = new List<FileInfo>(20);

            if (!Directory.Exists(root))
            {
                throw new ArgumentException("The specified root directory does not exist: " + root, "root");
            }

            dirs.Push(root);

            while (dirs.Count > 0)
            {
                string currentDir = dirs.Pop();
                string[] subDirs;
                try
                {
                    subDirs = Directory.GetDirectories(currentDir);
                }

                    // An UnauthorizedAccessException exception will be thrown if we do not have
                // discovery permission on a folder or file. It may or may not be acceptable 
                // to ignore the exception and continue enumerating the remaining files and 
                // folders. It is also possible (but unlikely) that a DirectoryNotFound exception 
                // will be raised. This will happen if currentDir has been deleted by
                // another application or thread after our call to Directory.Exists. The 
                // choice of which exceptions to catch depends entirely on the specific task 
                // you are intending to perform and also on how much you know with certainty 
                // about the systems on which this code will run.
                catch (UnauthorizedAccessException e)
                {
                    if (logfunction != null)
                    {
                        logfunction(e.Message);
                    }

                    continue;
                }
                catch (DirectoryNotFoundException e)
                {
                    if (logfunction != null)
                    {
                        logfunction(e.Message);
                    }

                    continue;
                }

                string[] files;
                try
                {
                    files = Directory.GetFiles(currentDir);
                }
                catch (UnauthorizedAccessException e)
                {
                    if (logfunction != null)
                    {
                        logfunction(e.Message);
                    }

                    continue;
                }
                catch (DirectoryNotFoundException e)
                {
                    if (logfunction != null)
                    {
                        logfunction(e.Message);
                    }

                    continue;
                }

                // Perform the required action on each file here.
                // Modify this block to perform your required task.
                foreach (string file in files)
                {
                    try
                    {
                        // Perform whatever action is required in your scenario.
                        FileInfo fi = new FileInfo(file);
                        bool addfile = true;
                        if (filefunction != null)
                        {
                            addfile = filefunction(fi);
                        }

                        if (addfile)
                        {
                            fileInfos.Add(fi);
                        }

                        // Console.WriteLine("{0}: {1}, {2}", fi.Name, fi.Length, fi.CreationTime);
                    }
                    catch (FileNotFoundException e)
                    {
                        // If file was deleted by a separate application
                        // or thread since the call to TraverseTree()
                        // then just continue.
                        if (logfunction != null)
                        {
                            logfunction(e.Message);
                        }

                        continue;
                    }
                }

                // Push the subdirectories onto the stack for traversal.
                // This could also be done before handing the files.
                foreach (string str in subDirs)
                {
                    DirectoryInfo di = new DirectoryInfo(str);
                    bool adddir = true;
                    if (dirfunction != null)
                    {
                        adddir = dirfunction(di);
                    }

                    if (adddir)
                    {
                        dirs.Push(str);
                    }
                }
            }

            return fileInfos;
        }

        /// <summary>
        /// match.
        /// </summary>
        /// <param name="eval">
        /// The eval.
        /// </param>
        /// <param name="pattern">
        /// The pattern.
        /// </param>
        /// <param name="caseSensitive">
        /// The case sensitive.
        /// </param>
        /// <returns>
        /// The match.
        /// </returns>
        public static bool Match(string eval, string pattern, bool caseSensitive)
        {
            bool match = false;

            // Make input parameters lower-case if case is not an issue
            if (!caseSensitive)
            {
                eval = eval.ToLower();
                pattern = pattern.ToLower();
            }

            // Escape regexp special character in pattern
            pattern = pattern.Replace(".", @"\.");

            // Replace valid wildcards with regexp equivalents
            pattern = pattern.Replace('?', '.').Replace("*", ".*");

            // Add boundaries to pattern
            pattern = @"\A" + pattern + @"\z";

            // Search for a match
            try
            {
                match = Regex.IsMatch(eval, pattern);
            }
            catch /* (ArgumentException ex) */
            {
                // Syntax error in the regular expression
            }

            // Return result
            return match;
        }

        /// <summary>
        /// Copies a directory with subdirs.
        /// </summary>
        /// <param name="source">
        /// The source.
        /// </param>
        /// <param name="destination">
        /// The destination.
        /// </param>
        public static void CopyDirectory(string source, string destination)
        {
            if (!destination.EndsWith(Path.DirectorySeparatorChar.ToString()))
            {
                destination += Path.DirectorySeparatorChar;
            }

            if (!Directory.Exists(destination))
            {
                Directory.CreateDirectory(destination);
            }

            string[] entries = Directory.GetFileSystemEntries(source);

            foreach (string item in entries)
            {
                if (Directory.Exists(item))
                {
                    CopyDirectory(item, destination + Path.GetFileName(item));
                }
                else
                {
                    File.Copy(item, destination + Path.GetFileName(item), true);
                }
            }
        }

        /// <summary>
        /// Copy files recursive after the "Create Conceptual Build Files" step.
        /// </summary>
        /// <param name="context">The build context.</param>
        /// <param name="fromRelativeDir">The source dir path, relative from the project root.</param>
        /// <param name="toRelativeDir">The destination dir path, relative from the project root.</param>
        /// <param name="tracerMessageMethod"><param name="excludeDirFilter"></param>
        /// The message handler method. Can be null.</param>
        /// <param name="excludeDirFilter">The exclusion filter for directories.
        /// Something like ".svn". Can be null or empty.</param>
        public static void CopyRelativeContent(
            BuildContext context,
            string fromRelativeDir,
            string toRelativeDir,
            TracerMessage tracerMessageMethod,
            string excludeDirFilter)
        {
            IBuildStep step = context.CurrentStep;
            if (step.Name != "Create Conceptual Build Files")
            {
                return;
            }

            // conti = false;
            // int i = context.PercentComplete;
            string cur = context.ProjectDirectory;

            string mur = Path.Combine(cur, fromRelativeDir);
            CopyAbsolute(context, mur, toRelativeDir, tracerMessageMethod, excludeDirFilter);
        }

        /// <summary>
        /// Copy files recursive after the "Create Conceptual Build Files" step.
        /// </summary>
        /// <param name="context">The build context.</param>
        /// <param name="fromAbsoluteDir">The absolute source dir path.</param>
        /// <param name="toRelativeDir">The destination dir, relative from the project root.</param>
        /// <param name="tracerMessageMethod">
        /// The message handler method. Can be null.</param>
        /// <param name="excludeDirFilter">The exclusion filter for directories.
        /// Something like ".svn". Can be null or empty.</param>
        public static void CopyAbsoluteContent(
            BuildContext context,
            string fromAbsoluteDir,
            string toRelativeDir,
            TracerMessage tracerMessageMethod,
            string excludeDirFilter)
        {
            IBuildStep step = context.CurrentStep;
            if (step.Name != "Create Conceptual Build Files")
            {
                return;
            }

            CopyAbsolute(context, fromAbsoluteDir, toRelativeDir, tracerMessageMethod, excludeDirFilter);
        }

        /// <summary>
        /// Copy files recursive after the "Create Conceptual Build Files" step.
        /// </summary>
        /// <param name="process">The build process.</param>
        /// <param name="context">The builds context.</param>
        /// <param name="fromSolutionDir">The relative source dir path pointing 
        /// from the solution directory.</param>
        /// <param name="toRelativeDir">The destination dir, relative from the project root.</param>
        /// <param name="tracerMessageMethod">
        /// The message handler method. Can be null.</param>
        /// <param name="excludeDirFilter">The exclusion filter for directories.
        /// Something like ".svn". Can be null or empty.</param>
        /// <exception cref="NotSupportedException">Error CopySolutionContent: To use this function the builder context must be in Visual Studio mode to resolve the Solution directory.</exception>
        public static void CopySolutionContent(
            BuildProcess process,
            BuildContext context,
            string fromSolutionDir,
            string toRelativeDir,
            TracerMessage tracerMessageMethod,
            string excludeDirFilter)
        {
            IBuildStep step = context.CurrentStep;
            if (step.Name != "Create Conceptual Build Files")
            {
                return;
            }

            DTE vs = context.Engine.Options.GetService<DTE>();
            if (vs == null)
            {
                const string message =
                    "Error CopySolutionContent: To use this function the " +
                    "builder context must be in Visual Studio mode to resolve the " + "Solution directory.";
                if (tracerMessageMethod != null)
                {
                    tracerMessageMethod(message);
                    return;
                }

                throw new NotSupportedException(message);
            }

            string originalSolutionPath = (string)vs.Solution.Properties.Item("Path").Value;
            string originalSolutionDir = Path.GetDirectoryName(originalSolutionPath);
            string fromAbsoluteDir = Path.Combine(originalSolutionDir, fromSolutionDir);

            CopyAbsolute(context, fromAbsoluteDir, toRelativeDir, tracerMessageMethod, excludeDirFilter);
        }

        private static void CopyAbsolute(
            BuildContext context,
            string fromAbsoluteDir,
            string toRelativeDir,
            TracerMessage tracerMessage,
            string excludeDir)
        {
            string toDir = Path.Combine(context.ProjectDirectory, toRelativeDir);
            if (!Directory.Exists(toDir))
            {
                Directory.CreateDirectory(toDir);
            }

            DirectoryInfo finfo = new DirectoryInfo(fromAbsoluteDir);
            if (finfo.Exists)
            {
                RecursiveCopyFiles(finfo.FullName, toDir, true, false, tracerMessage, excludeDir);
            }
        }

        /// <summary>
        /// Copy files recursive.
        /// </summary>
        /// <param name="sourceDir">The source dir.</param>
        /// <param name="destDir">The destination dir.</param>
        /// <param name="fRecursive">process directories recursive.</param>
        /// <param name="overWrite">if set to <c>true</c> [overwrite existing files].</param>
        /// <param name="tracerMessage"><param name="excludeDir"></param>
        /// The message handler method. Can be null.</param>
        /// <param name="excludeDir">The exclusion filter for directories.
        /// Something like ".svn". Can be null or empty.</param>
        private static void RecursiveCopyFiles(
            string sourceDir,
            string destDir,
            bool fRecursive,
            bool overWrite,
            TracerMessage tracerMessage,
            string excludeDir)
        {
            int i;
            int posSep;
            string sDir;
            string[] aDirs;
            string sFile;
            string[] aFiles;

            /*Add trailing separators to the supplied paths if they don't exist.*/
            if (!sourceDir.EndsWith(Path.DirectorySeparatorChar.ToString()))
            {
                sourceDir += Path.DirectorySeparatorChar;
            }

            if (!destDir.EndsWith(Path.DirectorySeparatorChar.ToString()))
            {
                destDir += Path.DirectorySeparatorChar;
            }

            /*Recursive switch to continue drilling down into dir structure.*/
            if (fRecursive)
            {
                /*Get a list of directories from the current parent.*/
                aDirs = Directory.GetDirectories(sourceDir);
                for (i = 0; i <= aDirs.GetUpperBound(0); i++)
                {
                    /*Get the position of the last separator in the current path.*/
                    posSep = aDirs[i].LastIndexOf(@"\");

                    /*Get the path of the source directory.*/
                    sDir = aDirs[i].Substring(posSep + 1, aDirs[i].Length - (posSep + 1));

                    // do not use directories to be excluded
                    if (!string.IsNullOrEmpty(excludeDir))
                    {
                        if (sDir == excludeDir)
                        {
                            continue;
                        }
                    }

                    /*Create the new directory in the destination directory.*/
                    Directory.CreateDirectory(destDir + sDir);

                    /*Since we are in recursive mode, copy the children also*/
                    RecursiveCopyFiles(aDirs[i], destDir + sDir, fRecursive, overWrite, tracerMessage, ".svn");
                }
            }

            /*Get the files from the current parent.*/
            aFiles = Directory.GetFiles(sourceDir);

            /*Copy all files.*/
            for (i = 0; i <= aFiles.GetUpperBound(0); i++)
            {
                /*Get the position of the trailing separator.*/
                posSep = aFiles[i].LastIndexOf(@"\");

                /*Get the full path of the source file.*/
                sFile = aFiles[i].Substring(posSep + 1, aFiles[i].Length - (posSep + 1));

                try
                {
                    /*Copy the file.*/
                    File.Copy(aFiles[i], destDir + sFile, false);
                    if (tracerMessage != null)
                    {
                        tracerMessage("Copied " + sFile + " to " + destDir);
                    }
                }
                catch (Exception ex)
                {
                    if (overWrite == false)
                    {
                        if (tracerMessage != null)
                        {
                            tracerMessage("Skipping..." + ex.Message);
                        }
                    }
                    else
                    {
                        File.Copy(aFiles[i], destDir + sFile, true);
                        string message = "Overwriting old " + sFile + " in " + destDir;
                        if (tracerMessage != null)
                        {
                            tracerMessage(message);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Transform NamespaceDoc and ProjectDoc classes into valid "N:TheNamespace" tags.
        /// </summary>
        /// <param name="context">The builds context.</param>
        /// <param name="tracerMessageMethod">
        /// The message handler method. Can be null.</param>
        public static void TransformNamespaceDocs(
            BuildContext context,
            TracerMessage tracerMessageMethod)
        {
            const string namespaceDocClassName = "NamespaceDoc";
            const string projectDocClassName = "ProjectDoc";

            TransformNamespaceDocs(context, namespaceDocClassName, projectDocClassName, tracerMessageMethod);
        }

        /// <summary>
        /// Transform NamespaceDoc and ProjectDoc classes into valid "N:TheNamespace" tags.
        /// </summary>
        /// <param name="context">The builds context.</param>
        /// <param name="namespaceDocClassName">Name of the NamespaceDoc class. Default: "NamespaceDoc"</param>
        /// <param name="projectDocClassName">Name of the ProjectDoc class. Default: "ProjectDoc</param>
        /// <param name="tracerMessageMethod">
        /// The message handler method. Can be null.</param>
        /// <remarks>See <seealso cref="http://msbuildextasks.codeplex.com/sourcecontrol/changeset/view/2783?projectName=msbuildextasks#52139"/> MSBuild Extended Tasks</remarks>
        public static void TransformNamespaceDocs(
            BuildContext context,
            string namespaceDocClassName,
            string projectDocClassName,
            TracerMessage tracerMessageMethod)
        {
            if (context.CurrentStepIndex != 0) return;

            if (tracerMessageMethod != null)
                tracerMessageMethod("Step 1b: Renaming NamespaceDocs");
            foreach (Source var in context.Sources)
            {
                if (string.IsNullOrEmpty(var.XmlDocumentation)) continue;

                string root = Path.Combine(context.ProjectDirectory, @"buildhelp\assembler\Comments");
                string docpath = Path.Combine(root, var.XmlDocumentation.FileName);

                FileInfo file = new FileInfo(docpath);

                bool change = false;
                bool projFound = false;

                XmlDocument doc = new XmlDocument();
                doc.Load(file.FullName);
                XmlNodeList memberNodes = doc.SelectNodes("//member[@name]");
                if (memberNodes != null)
                {
                    foreach (XmlElement memberElement in memberNodes)
                    {
                        string pattern = string.Format(@"^T:(.*?)\.{0}$", namespaceDocClassName);

                        // NamespaceDoc class detection
                        Regex regex = new Regex(
                            pattern,
                            RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase |
                            RegexOptions.IgnorePatternWhitespace);
                        Match match = regex.Match(memberElement.GetAttribute("name"));
                        if (match.Success)
                        {
                            change = true;
                            memberElement.SetAttribute("name", match.Result("N:$1"));
                            if (tracerMessageMethod != null)
                                tracerMessageMethod("Found Namespace Doc " + match.Result("N:$1"));
                        }
                        // ProjectDoc class detection
                        if (projFound) continue;

                        string projPattern = string.Format(@"^T:{0}$", projectDocClassName);
                        Regex projRegex = new Regex(projPattern,
                            RegexOptions.Compiled | RegexOptions.CultureInvariant
                            | RegexOptions.IgnoreCase |
                            RegexOptions.IgnorePatternWhitespace);
                        Match projMatch = projRegex.Match(memberElement.GetAttribute("name"));
                        if (!projMatch.Success) continue;

                        if (tracerMessageMethod != null)
                            tracerMessageMethod("Found Project Doc " + projMatch.Result("R:Project"));
                        change = true;
                        memberElement.SetAttribute("name", projMatch.Result("R:Project"));
                        projFound = true;

                        // since only 1 "R:Project" can exist we break;
                    }
                }

                if (!change) continue;
                doc.Save(file.FullName);
                if (tracerMessageMethod != null)
                {
                    tracerMessageMethod("TransformNamespaceDocs: Saving transformations to: " + file.FullName);
                }
            }
        }
    }
}

Jul 14, 2009 at 12:35 AM

        /// <summary>
        /// Called after a <paramref name="step" /> has been executed during a help build.
        /// </summary>
        /// <param name="step"><see cref="IBuildStep" /> implementation that was executed.</param>
        /// <param name="context">Provides information about the build process.</param>
        public override void AfterExecuteStep(IBuildStep step, BuildContext context)
        {
            const string fromdirRelative = @"Documentation\DocumentX\Images";
            const string toDirRelative = @"Help\" + @"Images";

            // Fix NamespaceDocs classes tags.
            PathUtil.TransformNamespaceDocs(context,this.TraceMessage);

            // Copy solution image files in. 
            //SVNL: http://omberzombie.svn.sourceforge.net/viewvc/omberzombie/trunk/Dist/SHFBRelContent/SHFBRelContent/
            PathUtil.CopySolutionContent(this,context, fromdirRelative,
                toDirRelative, this.TraceMessage, ".svn");

            TraceLine();
            TraceLine("Step {0} Time Elapsed: {1}", context.CurrentStepIndex + 1, DateTime.Now - stepStart);
        }


Jul 14, 2009 at 12:41 AM

My way to fix NamespaceDox.

But please dave. find a way for blondes.

Ah explanaytionz: Copy in from SVN content ... ignore SVN .. i need that. i am from the C64

regards, jed

Jul 14, 2009 at 11:46 AM

Please excuse my speech .... i am german

that is a nice thread

 

Naja

Implement easyness or SHFBCOPYRelContent .......

You have to say "YES", dave. that you implement namespaxD0rx

und how

und why

. Please clarify this

I am the last one whoo ( in german: uuuuuuuuuuuuuuuuuuuuuu )

will give you a kiss for that what youve done for tje ....

grrrrr, my builder sucks.

N:UK.Ministry.SillyWalking

Re .. ouch you idiot ...

regards, ...ouch

Stefanie

ouch.

SVN

 

Jul 15, 2009 at 1:38 PM

Hi,

DocProject doesn't support NamespaceDoc classes, but there is a better (in my opinion) alternative.

To add namespace documentation, simply add an XML documentation file to your DocProject's or DocSite's Comments folder and use the N: prefix.

The file name should have the same name as the XML documentation file that is normally used for the assembly that contains the target namespace.  You can add these files manually or dynamically at build time.

Alternatively, you can open the Topic Editor window, select a namespace node in Topic Explorer, and begin writing your documentation.  When you save the solution it will create the appropriate files in the Comments folder for you.

- Dave