コード例 #1
0
        /* Function: MarkTextBoxes
         *
         * Finds all text boxes in a comment and marks their tokens as <Tokenization.CommentParsingType.CommentDecoration>.
         * Vertical lines will only be detected if they are continuous throughout the comment and horizontal lines if they
         * are connected to it.  Freestanding horizontal lines are *not* detected here.  This function tolerates differing
         * symbols on corners and where embedded horizontal lines connect to the vertical.  It also tolerates tokens
         * marked with <Tokenization.CommentParsingType.CommentSymbol> differing.
         *
         * Examples:
         *
         * The box below will be marked completely, including the middle horizontal line.
         *
         * > // +----------+
         * > // | Title    |
         * > // +----------+
         * > // | Text     |
         * > // +----------+
         *
         * The middle horizontal line below will not be marked, because it is not attached.
         *
         * > // +----------+
         * > // | Title    |
         * > // | -------- |
         * > // | Text     |
         * > // +----------+
         *
         * Nor will the horizontal line below since there is no vertical.
         *
         * > // Title
         * > // ----------
         * > // Text
         *
         * Freestanding horizontal lines are not detected because they may be intended literally, such as when part of
         * a code section.  If you're not in such a section use <IsHorizontalLine()> before parsing a line to filter it out.
         *
         * > // (start code)
         * > // +-----+
         * > // | box |
         * > // +-----+
         * > // (end code)
         */
        public static void MarkTextBoxes(PossibleDocumentationComment comment)
        {
            char symbolA, symbolB, symbolC;
            int  symbolACount, symbolBCount, symbolCCount;

            char leftSymbol       = '\0';
            char rightSymbol      = '\0';
            int  leftSymbolCount  = 0;
            int  rightSymbolCount = 0;

            bool symbolIsAloneOnLine    = false;
            bool testedForVerticalLines = false;

            LineIterator  line = comment.Start;
            TokenIterator lineStart, lineEnd;

            // This should be okay to use since line numbers start at one.
            IDObjects.NumberSet horizontalLines = new IDObjects.NumberSet();

            // Skip leading blank lines since it's okay if they're not part of the text box.
            while (line < comment.End && line.IsEmpty(LineBoundsMode.CommentContent))
            {
                line.Next();
            }

            while (line < comment.End && line.IsEmpty(LineBoundsMode.CommentContent) == false)
            {
                line.GetBounds(LineBoundsMode.ExcludeWhitespace, out lineStart, out lineEnd);

                // Shrink the line to exclude its comment symbols, if any.  We didn't do this using the line bounds mode because
                // we need to know whether there was any whitespace between them and any horizontal lines.

                bool commentSymbolWithoutWhitespaceAtStart = false;
                bool commentSymbolWithoutWhitespaceAtEnd   = false;

                if (lineStart.CommentParsingType == CommentParsingType.CommentSymbol)
                {
                    commentSymbolWithoutWhitespaceAtStart = true;

                    do
                    {
                        lineStart.Next();
                    }while (lineStart.CommentParsingType == CommentParsingType.CommentSymbol);

                    if (lineStart.FundamentalType == FundamentalType.Whitespace)
                    {
                        commentSymbolWithoutWhitespaceAtStart = false;

                        do
                        {
                            lineStart.Next();
                        }while (lineStart.FundamentalType == FundamentalType.Whitespace);
                    }
                }

                lineEnd.Previous();
                if (lineEnd.CommentParsingType == CommentParsingType.CommentSymbol)
                {
                    commentSymbolWithoutWhitespaceAtEnd = true;

                    do
                    {
                        lineEnd.Previous();
                    }while (lineEnd.CommentParsingType == CommentParsingType.CommentSymbol);

                    if (lineEnd.FundamentalType == FundamentalType.Whitespace)
                    {
                        commentSymbolWithoutWhitespaceAtEnd = false;

                        do
                        {
                            lineEnd.Previous();
                        }while (lineEnd.FundamentalType == FundamentalType.Whitespace);
                    }
                }
                lineEnd.Next();


                // Horizontal line detection

                bool isHorizontalLine = false;

                CountSymbolLine(ref lineStart, lineEnd, out symbolA, out symbolB, out symbolC,
                                out symbolACount, out symbolBCount, out symbolCCount);

                if (commentSymbolWithoutWhitespaceAtStart == true &&
                    commentSymbolWithoutWhitespaceAtEnd == true &&
                    symbolACount >= 4 && symbolBCount == 0)
                {
                    isHorizontalLine = true;
                }

                else if (commentSymbolWithoutWhitespaceAtStart == true &&
                         symbolACount >= 4 &&
                         (symbolBCount == 0 || (symbolBCount <= 3 && symbolCCount == 0)))
                {
                    isHorizontalLine = true;
                }

                else if (commentSymbolWithoutWhitespaceAtEnd == true &&
                         ((symbolACount >= 1 && symbolACount <= 3 && symbolBCount >= 4 && symbolCCount == 0) ||
                          (symbolACount >= 4 && symbolBCount == 0)))
                {
                    isHorizontalLine = true;
                }

                else if ((symbolACount >= 4 && symbolBCount == 0) ||
                         (symbolACount >= 1 && symbolACount <= 3 && symbolBCount >= 4 && symbolCCount <= 3))
                {
                    isHorizontalLine = true;
                }

                // The horizontal line has to be the only thing on the line to count.
                if (isHorizontalLine && lineStart == lineEnd)
                {
                    horizontalLines.Add(line.LineNumber);
                }


                // Vertical line detection

                else if (testedForVerticalLines == false)
                {
                    // We permit the very first line to be different to allow for this:
                    //    /** text
                    //     * text
                    //     */
                    //
                    // However, don't skip the first line if it's a one line comment or we wouldn't be able to handle this:
                    //    ### text
                    //
                    if (line != comment.Start ||
                        (comment.End.LineNumber - comment.Start.LineNumber) == 1)
                    {
                        if (CountEdgeSymbols(line, out leftSymbol, out rightSymbol, out leftSymbolCount, out rightSymbolCount,
                                             out symbolIsAloneOnLine) == false)
                        {
                            return;
                        }

                        testedForVerticalLines = true;
                    }
                }

                else                 // testedForVerticalLines == true
                {
                    char lineLeftSymbol, lineRightSymbol;
                    int  lineLeftSymbolCount, lineRightSymbolCount;
                    bool lineSymbolIsAloneOnLine;

                    CountEdgeSymbols(line, out lineLeftSymbol, out lineRightSymbol, out lineLeftSymbolCount, out lineRightSymbolCount,
                                     out lineSymbolIsAloneOnLine);


                    // Account for a lone symbol being the right symbol.

                    if (lineSymbolIsAloneOnLine == true && symbolIsAloneOnLine == false && leftSymbolCount == 0 && rightSymbolCount > 0)
                    {
                        if (lineLeftSymbol != rightSymbol || lineLeftSymbolCount != rightSymbolCount)
                        {
                            return;
                        }
                    }
                    else if (lineSymbolIsAloneOnLine == false && symbolIsAloneOnLine == true && lineLeftSymbolCount == 0 && lineRightSymbolCount > 0)
                    {
                        if (lineRightSymbol != leftSymbol || lineRightSymbolCount != leftSymbolCount)
                        {
                            return;
                        }

                        rightSymbol      = leftSymbol;
                        leftSymbol       = '\0';
                        rightSymbolCount = leftSymbolCount;
                        leftSymbolCount  = 0;
                    }

                    // Otherwise it's okay to do a straight compare.
                    else
                    {
                        if (lineLeftSymbol != leftSymbol || lineLeftSymbolCount != leftSymbolCount)
                        {
                            leftSymbol      = '\0';
                            leftSymbolCount = 0;
                        }

                        if (lineRightSymbol != rightSymbol || lineRightSymbolCount != rightSymbolCount)
                        {
                            rightSymbol      = '\0';
                            rightSymbolCount = 0;
                        }

                        if (leftSymbolCount == 0 && rightSymbolCount == 0)
                        {
                            return;
                        }
                    }

                    // Turn off the overall alone flag if this line didn't have it.
                    if (lineSymbolIsAloneOnLine == false)
                    {
                        symbolIsAloneOnLine = false;
                    }
                }


                line.Next();
            }


            // If we stopped because we hit a blank line, this comment is only acceptable for marking text boxes if all the lines
            // left are blank.

            while (line < comment.End && line.IsEmpty(LineBoundsMode.CommentContent))
            {
                line.Next();
            }

            if (line != comment.End)
            {
                return;
            }


            // If we made it this far without returning it means we have a valid text box which we have to mark as comment decoration.

            line = comment.Start;

            while (line < comment.End)
            {
                line.GetBounds(LineBoundsMode.CommentContent, out lineStart, out lineEnd);

                if (horizontalLines.Contains(line.LineNumber))
                {
                    while (lineStart < lineEnd)
                    {
                        lineStart.CommentParsingType = CommentParsingType.CommentDecoration;
                        lineStart.Next();
                    }
                }

                else if (lineEnd > lineStart)
                {
                    // We test the characters against the symbols to account for any exceptions we allowed to go through
                    // in previous code.

                    for (int i = 0; i < leftSymbolCount; i++)
                    {
                        if (lineStart.Character == leftSymbol)
                        {
                            lineStart.CommentParsingType = CommentParsingType.CommentDecoration;
                            lineStart.Next();
                        }
                    }

                    lineEnd.Previous();
                    for (int i = 0; i < rightSymbolCount; i++)
                    {
                        if (lineEnd.Character == rightSymbol)
                        {
                            lineEnd.CommentParsingType = CommentParsingType.CommentDecoration;
                            lineEnd.Previous();
                        }
                    }
                }

                line.Next();
            }
        }
コード例 #2
0
        /* Function: FindIncludeInOutput
         * Extracts and returns any comment content marked "include in output".  All comment symbols and extra indents
         * will be removed.  Returns null if the comment doesn't have any.
         */
        protected string FindIncludeInOutput(PossibleDocumentationComment comment)
        {
            Comments.LineFinder.MarkTextBoxes(comment);

            LineIterator iterator = comment.Start;


            // Find the "include in output" header if it exists

            while (iterator < comment.End &&
                   iterator.Match(IncludeInOutputRegex, LineBoundsMode.CommentContent).Success == false)
            {
                iterator.Next();
            }

            if (iterator >= comment.End)
            {
                return(null);
            }


            // Find the bounds of the content excluding whitespace and the shared indent level

            iterator.Next();

            while (iterator < comment.End && iterator.IsEmpty(LineBoundsMode.CommentContent))
            {
                iterator.Next();
            }

            LineIterator start        = iterator;
            LineIterator end          = iterator;
            int          commonIndent = 9999;

            while (iterator < comment.End)
            {
                if (iterator.IsEmpty(LineBoundsMode.CommentContent))
                {
                    iterator.Next();
                }
                else
                {
                    if (iterator.Indent(LineBoundsMode.CommentContent) < commonIndent)
                    {
                        commonIndent = iterator.Indent(LineBoundsMode.CommentContent);
                    }

                    iterator.Next();
                    end = iterator;
                }
            }


            // Build and return the comment content

            if (start >= end)
            {
                return(null);
            }

            StringBuilder output = new StringBuilder();

            do
            {
                int indentDifference = start.Indent(LineBoundsMode.CommentContent) - commonIndent;

                if (indentDifference > 0)
                {
                    output.Append(' ', indentDifference);
                }

                start.AppendTo(output, LineBoundsMode.CommentContent);
                output.AppendLine();

                start.Next();
            }while (start < end);

            return(output.ToString());
        }