Пример #1
0
        /// <summary>
        /// Processes a newline character found while checking line spacing rules.
        /// </summary>
        /// <param name="precedingItem">The preceding item before the newline.</param>
        /// <param name="item">The newline item.</param>
        /// <param name="count">The current newline count.</param>
        private void CheckLineSpacingNewline(LexicalElement precedingItem, LexicalElement item, int count)
        {
            Param.Ignore(precedingItem);
            Param.AssertNotNull(item, "item");
            Param.AssertGreaterThanOrEqualToZero(count, "count");

            // If we've seen two end-of-line characters in a row, then there is a blank
            // line in the code. 
            if (count == 2)
            {
                // Check whether we've seen at least one token before this blank line.
                if (precedingItem != null && !precedingItem.Generated)
                {
                    if (precedingItem.Is(TokenType.OpenCurlyBracket))
                    {
                        // The blank line comes just after an opening curly bracket.
                        this.AddViolation(
                            precedingItem.FindParentElement(),
                            precedingItem.LineNumber,
                            Rules.OpeningCurlyBracketsMustNotBeFollowedByBlankLine);
                    }
                    else if (IsXmlHeader(precedingItem))
                    {
                        // The blank line comes just after an Xml header.
                        this.AddViolation(
                            precedingItem.FindParentElement(),
                            precedingItem.LineNumber,
                            Rules.ElementDocumentationHeadersMustNotBeFollowedByBlankLine);
                    }
                }
            }
            else if (count == 3 && !item.Generated)
            {
                // There are two or more blank lines in a row.
                this.AddViolation(
                    item.FindParentElement(),
                    item.LineNumber,
                    Rules.CodeMustNotContainMultipleBlankLinesInARow);
            }
        }
Пример #2
0
        /// <summary>
        /// Checks for tabs in the given comment.
        /// </summary>
        /// <param name="comment">The comment token.</param>
        private void CheckTabsInComment(LexicalElement comment)
        {
            Param.AssertNotNull(comment, "comment");

            int lineEnds = 0;

            for (int i = 0; i < comment.Text.Length; ++i)
            {
                if (comment.Text[i] == '\t')
                {
                    this.AddViolation(comment.FindParentElement(), comment.LineNumber + lineEnds, Rules.TabsMustNotBeUsed);
                }
                else if (comment.Text[i] == '\n')
                {
                    ++lineEnds;
                }
            }
        }
Пример #3
0
        private void CheckLineSpacingNonWhitespace(
            CsDocument document, LexicalElement precedingItem, LexicalElement item, bool fileHeader, bool firstTokenOnLine, int count)
        {
            Param.AssertNotNull(document, "document");
            Param.Ignore(precedingItem);
            Param.AssertNotNull(item, "item");
            Param.Ignore(fileHeader);
            Param.Ignore(firstTokenOnLine);
            Param.AssertGreaterThanOrEqualToZero(count, "count");

            // Skip generated tokens.
            if (!item.Generated)
            {
                // If there is at least one blank line in front of the current token.
                if (count > 1)
                {
                    if (item.Is(TokenType.CloseCurlyBracket))
                    {
                        // The blank line is just before a closing curly bracket.
                        this.AddViolation(
                            item.FindParentElement(),
                            item.LineNumber,
                            Rules.ClosingCurlyBracketsMustNotBePrecededByBlankLine);
                    }
                    else if (item.Is(TokenType.OpenCurlyBracket))
                    {
                        // The blank line is just before an opening curly bracket.
                        this.AddViolation(
                            item.FindParentElement(),
                            item.LineNumber,
                            Rules.OpeningCurlyBracketsMustNotBePrecededByBlankLine);
                    }
                    else if (item.Is(TokenType.Else) ||
                        item.Is(TokenType.Catch) ||
                        item.Is(TokenType.Finally))
                    {
                        // The blank line is just before an else, catch, or finally statement.
                        this.AddViolation(
                            item.FindParentElement(),
                            item.LineNumber,
                            Rules.ChainedStatementBlocksMustNotBePrecededByBlankLine);
                    }
                    else if (item.Is(TokenType.WhileDo))
                    {
                        // The blank line is just before the while keyword from a do/while statement.
                        this.AddViolation(
                            item.FindParentElement(),
                            item.LineNumber,
                            Rules.WhileDoFooterMustNotBePrecededByBlankLine);
                    }

                    // Check if there is a blank line after a single-line comment. The exceptions
                    // are if this is the file header, or if the line after the blank line contains
                    // another comment or an Xml header. This is ok if the comment is not
                    // the first item on its line.
                    if (!fileHeader &&
                        precedingItem != null &&
                        precedingItem.Is(CommentType.SingleLineComment) &&
                        !item.Is(LexicalElementType.Comment) &&
                        !IsXmlHeader(item))
                    {
                        Comment precedingComment = (Comment)precedingItem;

                        // Now check whether the comment is the first item on its line. If the comment
                        // is not the first item on the line, then this is not a violation.
                        bool itemSeen = false;
                        for (LexicalElement lineItem = precedingComment.FindPreviousLexicalElement(); lineItem != null; lineItem = lineItem.FindPreviousLexicalElement())
                        {
                            if (lineItem.LexicalElementType == LexicalElementType.EndOfLine)
                            {
                                break;
                            }
                            else if (lineItem.LexicalElementType != LexicalElementType.WhiteSpace)
                            {
                                itemSeen = true;
                                break;
                            }
                        }

                        // Now make sure this comment does not begin with '////'. If so, this is the signal
                        // that StyleCop should ignore this particular error. This is used when the 
                        // developer is commenting out a line of code. In this case it is not a true comment.
                        string trimmedComment = precedingComment.Text.Trim();
                        if (!itemSeen && !trimmedComment.StartsWith(@"////", StringComparison.Ordinal))
                        {
                            // The blank line appears after a file header, we want to allow this.
                            if (!IsCommentInFileHeader(precedingComment))
                            {
                                this.AddViolation(
                                    precedingComment.FindParentElement(),
                                    precedingComment.LineNumber,
                                    Rules.SingleLineCommentsMustNotBeFollowedByBlankLine);
                            }
                        }
                    }
                }
                else if (count == 1)
                {
                    // There is one line return in front of the current token, which means
                    // the line in front of the current token is not blank. Check if the current
                    // token is an Xml header.
                    if (IsXmlHeader(item))
                    {
                        // This is a violation unless the previous line contains another
                        // Xml header, an opening curly bracket, or a preprocessor directive.
                        if (precedingItem != null &&
                            !IsXmlHeader(precedingItem) &&
                            !precedingItem.Is(TokenType.OpenCurlyBracket) &&
                            !IsPreprocessorDirective(precedingItem))
                        {
                            this.AddViolation(
                                item.FindParentElement(),
                                item.LineNumber,
                                Rules.ElementDocumentationHeaderMustBePrecededByBlankLine);
                        }
                    }
                    else if (item.Is(CommentType.SingleLineComment))
                    {
                        // The current line contains a single line comment and the previous line
                        // is not blank. This is a violation unless the previous line contains
                        // another single line comment, an opening curly bracket, a preprocessor
                        // directive, or if the last character on the previous line is a colon,
                        // which can only mean that it is a label or a case statement, in which
                        // case this is ok.
                        if (precedingItem != null &&
                            !precedingItem.Is(CommentType.SingleLineComment) &&
                            !precedingItem.Is(TokenType.OpenCurlyBracket) &&
                            !precedingItem.Is(TokenType.LabelColon) &&
                            !IsPreprocessorDirective(precedingItem))
                        {
                            // Now make sure this comment does not begin with '////'. If so, this is the signal
                            // that StyleCop should ignore this particular error. This is used when the 
                            // developer is commenting out a line of code. In this case it is not a true comment.
                            string trimmedComment = item.Text.Trim();
                            if (!trimmedComment.StartsWith(@"////", StringComparison.Ordinal))
                            {
                                this.AddViolation(
                                    item.FindParentElement(),
                                    item.LineNumber,
                                    Rules.SingleLineCommentMustBePrecededByBlankLine);
                            }
                        }
                    }

                    if (precedingItem != null && precedingItem.Is(TokenType.CloseCurlyBracket))
                    {
                        // Closing curly brackets cannot be followed directly by another bracket keyword.
                        CloseCurlyBracketToken closingCurlyBracket = (CloseCurlyBracketToken)precedingItem;
                        if (closingCurlyBracket.MatchingBracket != null &&
                            closingCurlyBracket.MatchingBracket.LineNumber != closingCurlyBracket.LineNumber &&
                            firstTokenOnLine &&
                            !item.Is(TokenType.CloseCurlyBracket) &&
                            !item.Is(TokenType.Finally) &&
                            !item.Is(TokenType.Catch) &&
                            !item.Is(TokenType.WhileDo) &&
                            !item.Is(TokenType.Else) &&
                            !IsPreprocessorDirective(item))
                        {
                            this.AddViolation(
                                closingCurlyBracket.FindParentElement(),
                                closingCurlyBracket.LineNumber,
                                Rules.ClosingCurlyBracketMustBeFollowedByBlankLine);
                        }
                    }
                }
            }
        }