/// <summary>
        /// Checks the positioning of method parameters which are split across multiple lines.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="parameterList">The argument list.</param>
        /// <param name="arguments">The method arguments.</param>
        /// <param name="openingBracket">The opening bracket token.</param>
        private void CheckSplitMethodArgumentList(Element element, CodeUnit parameterList, IArgumentList arguments, OpenBracketToken openingBracket)
        {
            Param.AssertNotNull(element, "element");
            Param.AssertNotNull(parameterList, "parameterList");
            Param.AssertNotNull(arguments, "arguments");
            Param.AssertNotNull(openingBracket, "openingBracket");

            Token previousComma = null;
            bool commaOnSameLineAsPreviousParameterViolation = false;

            for (int i = 0; i < arguments.Count; ++i)
            {
                CodeLocation location = arguments.Location(i);
                int argumentStartLine = location.LineNumber;

                CodeUnit argument = arguments.Argument(i);

                // Some types of parameters or arguments are not allowed to span across multiple lines.
                if (location.LineSpan > 1 && !arguments.MaySpanMultipleLines(i))
                {
                    this.AddViolation(element, argumentStartLine, Rules.ParameterMustNotSpanMultipleLines);
                }

                if (i == 0)
                {
                    // The first argument must start on the line after the opening bracket
                    if (argumentStartLine != openingBracket.LineNumber + 1)
                    {
                        int commentLineSpan = MeasureCommentLinesAfter(openingBracket);

                        if (argumentStartLine != openingBracket.LineNumber + commentLineSpan + 1)
                        {
                            this.AddViolation(element, argumentStartLine, Rules.SplitParametersMustStartOnLineAfterDeclaration, element.FriendlyTypeText);
                        }
                    }
                }
                else
                {
                    // The argument must begin on the line after the previous comma.
                    Debug.Assert(previousComma != null, "The previous comma should have been set.");
                    if (!commaOnSameLineAsPreviousParameterViolation)
                    {
                        if (argumentStartLine != previousComma.LineNumber + 1)
                        {
                            int commentLineSpan = MeasureCommentLinesAfter(previousComma);

                            if (argumentStartLine != previousComma.LineNumber + commentLineSpan + 1)
                            {
                                this.AddViolation(element, argumentStartLine, Rules.ParameterMustFollowComma);
                            }
                        }
                    }
                }

                commaOnSameLineAsPreviousParameterViolation = false;

                // Find the comma after the token list.
                if (i < arguments.Count - 1)
                {
                    Token lastTokenInArgument = argument.FindLastDescendentToken();
                    if (lastTokenInArgument != null)
                    {
                        for (Token token = lastTokenInArgument.FindNextDescendentTokenOf(parameterList); token != null; token = token.FindNextDescendentTokenOf(parameterList))
                        {
                            if (token.TokenType == TokenType.Comma)
                            {
                                previousComma = token;

                                // The comma must be on the same line as the previous argument.
                                if (previousComma.LineNumber != location.EndPoint.LineNumber)
                                {
                                    int commentLineSpan = MeasureCommentLinesBetween(argument.FindLastChildToken(), previousComma, false);

                                    if (previousComma.LineNumber != location.EndPoint.LineNumber + commentLineSpan)
                                    {
                                        this.AddViolation(element, token.LineNumber, Rules.CommaMustBeOnSameLineAsPreviousParameter);
                                        commaOnSameLineAsPreviousParameterViolation = true;
                                    }
                                }

                                break;
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Checks a method or method invocation to ensure that the closing bracket is
        /// on the same line as the last argument.
        /// </summary>
        /// <param name="element">The element containing the expression.</param>
        /// <param name="parameterList">The argument list.</param>
        /// <param name="openingBracket">The opening bracket.</param>
        /// <param name="closingBracketType">The type of the closing bracket.</param>
        /// <param name="arguments">The arguments to the method.</param>
        private void CheckMethodClosingBracket(
            Element element, CodeUnit parameterList, OpenBracketToken openingBracket, TokenType closingBracketType, IArgumentList arguments)
        {
            Param.AssertNotNull(element, "element");
            Param.AssertNotNull(parameterList, "parameterList");
            Param.AssertNotNull(openingBracket, "openingBracket");
            Param.Ignore(closingBracketType);
            Param.AssertNotNull(arguments, "arguments");

            // Find the closing bracket.
            CloseBracketToken closingBracket = null;

            Token next = parameterList.FindNextSiblingToken();
            if (next != null && next.Is(closingBracketType))
            {
                closingBracket = (CloseBracketToken)next;
            }

            if (closingBracket != null)
            {
                if (arguments.Count == 0)
                {
                    // The closing bracket must be on the same line as the opening bracket.
                    if (openingBracket.LineNumber != closingBracket.LineNumber)
                    {
                        // If the brackets are not on the same line, determine if this is because there are comments
                        // between the brackets.
                        int commentLineSpan = MeasureCommentLinesBetween(openingBracket, closingBracket, false);

                        if (openingBracket.LineNumber + commentLineSpan != closingBracket.LineNumber)
                        {
                            this.AddViolation(element, closingBracket.LineNumber, Rules.ClosingParenthesisMustBeOnLineOfOpeningParenthesis);
                        }
                    }
                }
                else
                {
                    // The closing bracket must be on the same line as the end of the last method argument.
                    int lastArgumentEndLine = arguments.Location(arguments.Count - 1).EndPoint.LineNumber;
                    if (lastArgumentEndLine != closingBracket.LineNumber)
                    {
                        int commentLineSpan = MeasureCommentLinesBetween(arguments.Argument(arguments.Count - 1).FindLastDescendentToken(), closingBracket, false);

                        if (lastArgumentEndLine + commentLineSpan != closingBracket.LineNumber)
                        {
                            this.AddViolation(element, closingBracket.LineNumber, Rules.ClosingParenthesisMustBeOnLineOfLastParameter);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Checks the argument list to a method or method invocation to ensure that the arguments are 
        /// positioned correctly.
        /// </summary>
        /// <param name="element">The element containing the expression.</param>
        /// <param name="parameterList">The element's argument list.</param>
        /// <param name="arguments">The arguments to the method.</param>
        /// <param name="openingBracket">The opening bracket token.</param>
        /// <param name="methodLineNumber">The line number on which the method begins.</param>
        private void CheckMethodArgumentList(Element element, CodeUnit parameterList, IArgumentList arguments, OpenBracketToken openingBracket, int methodLineNumber)
        {
            Param.AssertNotNull(element, "element");
            Param.AssertNotNull(parameterList, "parameterList");
            Param.AssertNotNull(arguments, "arguments");
            Param.AssertNotNull(openingBracket, "openingBracket");
            Param.AssertGreaterThanZero(methodLineNumber, "methodLineNumber");

            // Determine whether all of the parameters are on the same line as one another.
            bool someParametersShareLine;
            bool someParameterOnDifferentLines;

            DetermineMethodParameterPlacementScheme(
                arguments, out someParametersShareLine, out someParameterOnDifferentLines);

            // All parameters must either be on the same line, or each argument must begin on its own line.
            if (someParametersShareLine && someParameterOnDifferentLines)
            {
                this.AddViolation(
                    element,
                    methodLineNumber,
                    Rules.ParametersMustBeOnSameLineOrSeparateLines,
                    element.FriendlyTypeText);
            }

            // Determine whether all of the parameters are on the same line as one another.
            if (someParameterOnDifferentLines)
            {
                this.CheckSplitMethodArgumentList(element, parameterList, arguments, openingBracket);
            }
            else if (arguments.Count > 0)
            {
                // The first argument must start on the same line as the opening bracket, or 
                // on the line after it.
                int firstArgumentStartLine = arguments.Location(0).LineNumber;

                if (firstArgumentStartLine != openingBracket.LineNumber &&
                    firstArgumentStartLine != openingBracket.LineNumber + 1)
                {
                    int commentLineSpan = MeasureCommentLinesAfter(openingBracket);

                    if (firstArgumentStartLine != openingBracket.LineNumber + commentLineSpan + 1)
                    {
                        this.AddViolation(element, firstArgumentStartLine, Rules.ParameterListMustFollowDeclaration);
                    }
                }
            }
        }
Example #4
0
        /// <summary>
        /// Checks the placement of curly brackets within the given item.
        /// </summary>
        /// <param name="item">The item containing the brackets to check.</param>
        /// <param name="parentElement">The element containing the brackets.</param>
        /// <param name="parentStatement">The statement containing the brackets, if any.</param>
        /// <param name="openBracket">The opening curly bracket within the token list.</param>
        /// <param name="allowAllOnOneLine">Indicates whether the brackets are allowed to be all on one line.</param>
        private void CheckBracketPlacement(
            CodeUnit item,
            Element parentElement, 
            Statement parentStatement, 
            OpenBracketToken openBracket, 
            bool allowAllOnOneLine)
        {
            Param.AssertNotNull(item, "item");
            Param.AssertNotNull(parentElement, "parentElement");
            Param.Ignore(parentStatement);
            Param.AssertNotNull(openBracket, "openBracket");
            Param.Ignore(allowAllOnOneLine);

            if (openBracket.MatchingBracket != null &&
                !openBracket.Generated && 
                !openBracket.MatchingBracket.Generated)
            {
                // Check if the two brackets are on the same line as each other.
                if (openBracket.LineNumber == openBracket.MatchingBracket.LineNumber)
                {
                    // This is an error if the brackets are not allowed to be all on the same line.
                    if (!allowAllOnOneLine)
                    {
                        // Statements within constructor initializers are allowed to be all on the same line
                        // since sometimes this is the only way to write the statement.
                        if (parentStatement == null)
                        {
                            this.AddViolation(parentElement, openBracket.LineNumber, Rules.ElementMustNotBeOnSingleLine, parentElement.FriendlyTypeText);
                        }
                        else if (parentStatement.StatementType != StatementType.ConstructorInitializer)
                        {
                            this.AddViolation(parentElement, openBracket.LineNumber, Rules.StatementMustNotBeOnSingleLine);
                        }
                    }
                    else
                    {
                        // The brackets are only allowed to be on the same line if the entire statement is on the same line.
                        Token first = item.FindFirstDescendentToken();
                        Token last = item.FindLastDescendentToken();

                        if (first != null && last != null && first.LineNumber != last.LineNumber)
                        {
                            this.AddViolation(parentElement, openBracket.LineNumber, Rules.CurlyBracketsForMultiLineStatementsMustNotShareLine, GetOpeningOrClosingBracketText(openBracket));
                        }
                    }
                }
                else
                {
                    // The brackets are on different lines. Both brackets must be on a line all by themselves.
                    if (LayoutRules.BracketSharesLine(openBracket, false))
                    {
                        this.AddViolation(parentElement, openBracket.LineNumber, Rules.CurlyBracketsForMultiLineStatementsMustNotShareLine, GetOpeningOrClosingBracketText(openBracket));
                    }

                    if (LayoutRules.BracketSharesLine(openBracket.MatchingBracket, true))
                    {
                        this.AddViolation(parentElement, openBracket.MatchingBracket.LineNumber, Rules.CurlyBracketsForMultiLineStatementsMustNotShareLine, GetOpeningOrClosingBracketText(openBracket.MatchingBracket));
                    }
                }
            }
        }