/// <summary>
        /// Determines whether a method's parameters share lines or are on different lines.
        /// </summary>
        /// <param name="arguments">The method arguments.</param>
        /// <param name="someParametersShareLine">Returns true if some of the parameters are on the same line.</param>
        /// <param name="someParameterOnDifferentLines">Returns true if some of the parameters are on different lines.</param>
        private static void DetermineMethodParameterPlacementScheme(
            IArgumentList arguments, out bool someParametersShareLine, out bool someParameterOnDifferentLines)
        {
            Param.AssertNotNull(arguments, "arguments");

            someParametersShareLine       = false;
            someParameterOnDifferentLines = false;

            CodeLocation previousArgumentLocation = null;

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

                if (i > 0)
                {
                    if (previousArgumentLocation.StartPoint.LineNumber == argumentLocation.EndPoint.LineNumber)
                    {
                        someParametersShareLine = true;
                    }
                    else
                    {
                        someParameterOnDifferentLines = true;
                    }
                }

                previousArgumentLocation = argumentLocation;
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Checks a method or method invocation to ensure that the closing bracket is
        /// on the same line as the last parameter.
        /// </summary>
        /// <param name="element">
        /// The element containing the expression.
        /// </param>
        /// <param name="parameterListTokens">
        /// The tokens that form the parameter list.
        /// </param>
        /// <param name="openingBracketNode">
        /// 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(
            CsElement element, CsTokenList parameterListTokens, Node <CsToken> openingBracketNode, CsTokenType closingBracketType, IArgumentList arguments)
        {
            Param.AssertNotNull(element, "element");
            Param.AssertNotNull(parameterListTokens, "parameterListTokens");
            Param.AssertNotNull(openingBracketNode, "openingBracket");
            Param.Ignore(closingBracketType);
            Param.AssertNotNull(arguments, "arguments");

            // Find the closing bracket.
            Node <CsToken> closingBracketNode = null;

            for (Node <CsToken> tokenNode = parameterListTokens.Last; tokenNode != null; tokenNode = tokenNode.Previous)
            {
                if (tokenNode.Value.CsTokenType == closingBracketType)
                {
                    closingBracketNode = tokenNode;
                    break;
                }
            }

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

                        if (openingBracketNode.Value.LineNumber + commentLineSpan != closingBracketNode.Value.LineNumber)
                        {
                            this.AddViolation(element, closingBracketNode.Value.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 != closingBracketNode.Value.LineNumber)
                    {
                        int commentLineSpan = MeasureCommentLinesBetween(arguments.Tokens(arguments.Count - 1).Last, closingBracketNode, false);

                        if (lastArgumentEndLine + commentLineSpan != closingBracketNode.Value.LineNumber)
                        {
                            this.AddViolation(element, closingBracketNode.Value.LineNumber, Rules.ClosingParenthesisMustBeOnLineOfLastParameter);
                        }
                    }
                }
            }
        }
        /// <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);
                    }
                }
            }
        }
        /// <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 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);
                    }
                }
            }
        }
        /// <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>
        /// Determines whether a method's parameters share lines or are on different lines.
        /// </summary>
        /// <param name="arguments">The method arguments.</param>
        /// <param name="someParametersShareLine">Returns true if some of the parameters are on the same line.</param>
        /// <param name="someParameterOnDifferentLines">Returns true if some of the parameters are on different lines.</param>
        private static void DetermineMethodParameterPlacementScheme(
            IArgumentList arguments, out bool someParametersShareLine, out bool someParameterOnDifferentLines)
        {
            Param.AssertNotNull(arguments, "arguments");

            someParametersShareLine = false;
            someParameterOnDifferentLines = false;

            CodeLocation previousArgumentLocation = null;
            for (int i = 0; i < arguments.Count; ++i)
            {
                CodeLocation argumentLocation = arguments.Location(i);

                if (i > 0)
                {
                    if (previousArgumentLocation.StartPoint.LineNumber == argumentLocation.EndPoint.LineNumber)
                    {
                        someParametersShareLine = true;
                    }
                    else
                    {
                        someParameterOnDifferentLines = true;
                    }
                }

                previousArgumentLocation = argumentLocation;
            }
        }
        /// <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;
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Checks the positioning of method parameters which are split across multiple lines.
        /// </summary>
        /// <param name="element">
        /// The element.
        /// </param>
        /// <param name="arguments">
        /// The method arguments.
        /// </param>
        /// <param name="openingBracketNode">
        /// The opening bracket token.
        /// </param>
        /// <param name="friendlyTypeText">
        /// The friendly type text to use in reporting violations.
        /// </param>
        private void CheckSplitMethodArgumentList(CsElement element, IArgumentList arguments, Node <CsToken> openingBracketNode, string friendlyTypeText)
        {
            Param.AssertNotNull(element, "element");
            Param.AssertNotNull(arguments, "arguments");
            Param.AssertNotNull(openingBracketNode, "openingBracketNode");

            Node <CsToken> previousComma = null;
            bool           commaOnSameLineAsPreviousParameterViolation = false;

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

                CsTokenList tokens = arguments.Tokens(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 != openingBracketNode.Value.LineNumber + 1)
                    {
                        int commentLineSpan = MeasureCommentLinesAfter(openingBracketNode);

                        if (argumentStartLine != openingBracketNode.Value.LineNumber + commentLineSpan + 1)
                        {
                            this.AddViolation(element, argumentStartLine, Rules.SplitParametersMustStartOnLineAfterDeclaration, friendlyTypeText);
                        }
                    }
                }
                else
                {
                    // The parameter 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.Value.LineNumber + 1)
                        {
                            int commentLineSpan = MeasureCommentLinesAfter(previousComma);

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

                commaOnSameLineAsPreviousParameterViolation = false;

                // Find the comma after the token list.
                if (i < arguments.Count - 1)
                {
                    for (Node <CsToken> tokenNode = tokens.Last.Next; tokenNode != null; tokenNode = tokenNode.Next)
                    {
                        if (tokenNode.Value.CsTokenType == CsTokenType.Comma)
                        {
                            previousComma = tokenNode;

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

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

                            break;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Checks the positioning of method parameters which are split across multiple lines.
        /// </summary>
        /// <param name="element">
        /// The element.
        /// </param>
        /// <param name="arguments">
        /// The method arguments.
        /// </param>
        /// <param name="openingBracketNode">
        /// The opening bracket token.
        /// </param>
        /// <param name="friendlyTypeText">
        /// The friendly type text to use in reporting violations.
        /// </param>
        private void CheckSplitMethodArgumentList(CsElement element, IArgumentList arguments, Node<CsToken> openingBracketNode, string friendlyTypeText)
        {
            Param.AssertNotNull(element, "element");
            Param.AssertNotNull(arguments, "arguments");
            Param.AssertNotNull(openingBracketNode, "openingBracketNode");

            Node<CsToken> previousComma = null;
            bool commaOnSameLineAsPreviousParameterViolation = false;

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

                CsTokenList tokens = arguments.Tokens(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 != openingBracketNode.Value.LineNumber + 1)
                    {
                        int commentLineSpan = MeasureCommentLinesAfter(openingBracketNode);

                        if (argumentStartLine != openingBracketNode.Value.LineNumber + commentLineSpan + 1)
                        {
                            this.AddViolation(element, argumentStartLine, Rules.SplitParametersMustStartOnLineAfterDeclaration, friendlyTypeText);
                        }
                    }
                }
                else
                {
                    // The parameter 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.Value.LineNumber + 1)
                        {
                            int commentLineSpan = MeasureCommentLinesAfter(previousComma);

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

                commaOnSameLineAsPreviousParameterViolation = false;

                // Find the comma after the token list.
                if (i < arguments.Count - 1)
                {
                    for (Node<CsToken> tokenNode = tokens.Last.Next; tokenNode != null; tokenNode = tokenNode.Next)
                    {
                        if (tokenNode.Value.CsTokenType == CsTokenType.Comma)
                        {
                            previousComma = tokenNode;

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

                                if (previousComma.Value.LineNumber != location.EndPoint.LineNumber + commentLineSpan)
                                {
                                    this.AddViolation(element, tokenNode.Value.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 parameter.
        /// </summary>
        /// <param name="element">
        /// The element containing the expression.
        /// </param>
        /// <param name="parameterListTokens">
        /// The tokens that form the parameter list.
        /// </param>
        /// <param name="openingBracketNode">
        /// 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(
            CsElement element, CsTokenList parameterListTokens, Node<CsToken> openingBracketNode, CsTokenType closingBracketType, IArgumentList arguments)
        {
            Param.AssertNotNull(element, "element");
            Param.AssertNotNull(parameterListTokens, "parameterListTokens");
            Param.AssertNotNull(openingBracketNode, "openingBracket");
            Param.Ignore(closingBracketType);
            Param.AssertNotNull(arguments, "arguments");

            // Find the closing bracket.
            Node<CsToken> closingBracketNode = null;
            for (Node<CsToken> tokenNode = parameterListTokens.Last; tokenNode != null; tokenNode = tokenNode.Previous)
            {
                if (tokenNode.Value.CsTokenType == closingBracketType)
                {
                    closingBracketNode = tokenNode;
                    break;
                }
            }

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

                        if (openingBracketNode.Value.LineNumber + commentLineSpan != closingBracketNode.Value.LineNumber)
                        {
                            this.AddViolation(element, closingBracketNode.Value.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 != closingBracketNode.Value.LineNumber)
                    {
                        int commentLineSpan = MeasureCommentLinesBetween(arguments.Tokens(arguments.Count - 1).Last, closingBracketNode, false);

                        if (lastArgumentEndLine + commentLineSpan != closingBracketNode.Value.LineNumber)
                        {
                            this.AddViolation(element, closingBracketNode.Value.LineNumber, Rules.ClosingParenthesisMustBeOnLineOfLastParameter);
                        }
                    }
                }
            }
        }