コード例 #1
0
        /// <summary>
        /// Beatifies XML comments.
        /// </summary>
        /// <param name="outputComment">The output comment.</param>
        /// <param name="inputComment">The comment to be wrapped and beautified.</param>
        /// <param name="prefix">The current comment line's prefix.</param>
        private static void WrapXml(StringBuilder outputComment, string inputComment, string prefix)
        {
            // The main idea around formatting XML is to put tags on their own lines when the text can't fit within the margin.  To accomplish this,
            // we'll format the entire tag and then see how long is it.
            StringBuilder commentBody = new StringBuilder();

            FormatCommentCommand.WrapLine(commentBody, inputComment, prefix);

            // This will pull apart the XML into the tags and the content.
            Match  match    = FormatCommentCommand.xmlParts.Match(inputComment);
            string startTag = match.Groups["startTag"].Value;
            string body     = match.Groups["body"].Value;
            string endTag   = match.Groups["endTag"].Value;

            // Extract the element name.  The name will be used to determine if the tags appear on their own comment lines or if they can be
            // collapsed onto a single line with their comment.  For example, the ' <summary>' tag is generally emitted on its own line whereas the '
            // <param>' tag is usually combined with the comments.
            Regex  xmlElementName = new Regex(@"<(?<name>\w+).*>");
            string elementName    = xmlElementName.Match(startTag).Groups["name"].Value;

            // If the tags and the content is too long to fit on a line after formatting, we'll put the tags on their own lines.  We also force a
            // certain class of tags to appear on their own line distinct from the content; it's just easier to read this way.
            if (commentBody.Length >= Properties.Settings.Default.WrapMargin || FormatCommentCommand.breakingElements.Contains(elementName))
            {
                // Write the start tag.
                outputComment.Append(prefix);
                outputComment.Append(' ');
                outputComment.Append(startTag);
                outputComment.AppendLine();

                // This will format the body of the tag to wrap at the right margin.
                FormatCommentCommand.columnPosition = 0;
                FormatCommentCommand.WrapLine(outputComment, body, prefix);
                if (FormatCommentCommand.columnPosition != 0)
                {
                    outputComment.AppendLine();
                }

                // Write the closing tag.
                outputComment.Append(prefix);
                outputComment.Append(' ');
                outputComment.Append(endTag);
                outputComment.AppendLine();
            }
            else
            {
                // If the XML tags and the line fit within the margin, we just write it to the output comment.
                outputComment.Append(commentBody.ToString());
                outputComment.AppendLine();
            }

            // Reset the wrapping parameters for the next comment line in the block.
            FormatCommentCommand.columnPosition = 0;
        }
コード例 #2
0
        /// <summary>
        /// Formats a block of comments and beautifies the XML comments.
        /// </summary>
        /// <param name="inputComment">The block of comment lines to format.</param>
        /// <returns>A right justified and beautified block of comments.</returns>
        private static string FormatCommentstring(string inputComment)
        {
            // These variables control the state of the wrapping.
            FormatCommentCommand.columnPosition = 0;

            // This buffer keeps track of the reconstructed comment block.
            StringBuilder outputComment = new StringBuilder();

            // This breaks the input comment into individual lines.
            string[] commentLines = inputComment.Split(new string[] { "\r\n" }, StringSplitOptions.None | StringSplitOptions.RemoveEmptyEntries);

            // Parse the line into prefixes (the comment start sequence and whitespace) and the actual comment on the line.
            for (int index = 0; index < commentLines.Length; index++)
            {
                // This parses the comment and the prefix out of the current comment line.  The prefix is all characters up to the comment delimiter
                // character.  The comment represents all the characters after the delimiter stripped of the leading and trailing space.
                Match  match   = FormatCommentCommand.commentRegex.Match(commentLines[index]);
                string prefix  = match.Groups["prefix"].Value;
                string comment = match.Groups["comment"].Value;

                // We assume there was some intent if an author left an entire line blank and so we treat it as a paragraph break.  That is, we don't
                // wrap over it.
                if (comment.Length == 0)
                {
                    if (FormatCommentCommand.columnPosition != 0)
                    {
                        outputComment.AppendLine();
                    }

                    outputComment.AppendLine(prefix);
                    FormatCommentCommand.columnPosition = 0;
                    continue;
                }

                // We're going to attempt to format the special comment directives so that they'll wrap nicely.  If a single-line directive is too
                // long, we'll wrap it so the directives end up on separate lines.  This test is used to distinguish between the special directives
                // used for commenting functions, classes and modules from regular block comments.
                bool isCommentDirective = prefix.EndsWith("///", StringComparison.Ordinal);

                // This section will provide formatting for XML tags inside comment blocks.  The tags are examined to see if the text and tags will
                // fit within the margins.  If not, the tags are placed on their own lines and the comment inside the tags is formatted to wrap
                // around the margins.  The algorithm will also eat up partial lines in order to fill out the XML content to the margin.
                if (isCommentDirective && xmlStartTag.IsMatch(comment) && !xmlEmptyElement.IsMatch(comment))
                {
                    while (!xmlEndTag.IsMatch(comment) && index < commentLines.Length)
                    {
                        match    = FormatCommentCommand.commentRegex.Match(commentLines[++index]);
                        comment += ' ' + match.Groups["comment"].Value;
                    }

                    FormatCommentCommand.WrapXml(outputComment, comment, prefix);
                    continue;
                }

                // This is used to force a line break on comment lines that meet certain criteria, such as bullet marks and examples.
                bool isBreakingLine = false;

                // Lines that begin with an Asterisk are considered bullet marks and do not wrap and are given an extra margin.
                if (comment.StartsWith("*", StringComparison.Ordinal))
                {
                    // If the previous line was waiting for some wrapping to occur, it's going to be disappointed.  This line is going to start all
                    // on its own.
                    if (FormatCommentCommand.columnPosition != 0)
                    {
                        outputComment.AppendLine();
                    }

                    FormatCommentCommand.columnPosition = 0;

                    // The prefix will be indented for all bullet marks.
                    prefix += "    ";

                    // This will force a line break after the bullet mark is formatted.
                    isBreakingLine = true;
                }

                // Lines that end with colons do not wrap.
                if (comment.EndsWith(":", StringComparison.Ordinal))
                {
                    isBreakingLine = true;
                }

                // This is where all the work is done to right justify the block comment to the margin.
                FormatCommentCommand.WrapLine(outputComment, comment, prefix);

                // This will force a new line for comment lines that don't wrap such as bullet marks and colons.
                if (isBreakingLine)
                {
                    outputComment.AppendLine();
                    FormatCommentCommand.columnPosition = 0;
                }
            }

            // This will finish off any incomplete lines.
            if (FormatCommentCommand.columnPosition > 0)
            {
                outputComment.AppendLine();
            }

            // At this point we've transformed the input block of comments into a right justified block.
            return(outputComment.ToString());
        }