/// <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 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); } } } } }