/// <summary> /// Checks the placement and formatting of parameters to a method invocation or a method declaration. /// </summary> /// <param name="element">The element.</param> /// <param name="parameterList">The argument list.</param> /// <param name="methodArguments">The arguments or parameters to the method.</param> /// <param name="methodStartLineNumber">The line number on which the method begins.</param> /// <param name="openBracketType">The type of the argument list opening bracket.</param> /// <param name="closeBracketType">The type of the argument list closing bracket.</param> private void CheckParameters( Element element, CodeUnit parameterList, IArgumentList methodArguments, int methodStartLineNumber, TokenType openBracketType, TokenType closeBracketType) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(parameterList, "parameterList"); Param.AssertNotNull(methodArguments, "methodArguments"); Param.AssertGreaterThanZero(methodStartLineNumber, "methodStartLineNumber"); Param.Ignore(openBracketType); Param.Ignore(closeBracketType); OpenBracketToken openingBracket = this.CheckMethodOpeningBracket(element, parameterList, openBracketType); if (openingBracket != null) { this.CheckMethodClosingBracket(element, parameterList, openingBracket, closeBracketType, methodArguments); if (methodArguments.Count > 0) { this.CheckMethodArgumentList(element, parameterList, methodArguments, openingBracket, methodStartLineNumber); } } }
/// <summary> /// argument_list = "[" [ argument *( "," argument ) ] "]" /// argument = expression /// </summary> /// <param name="openBracket"></param> /// <param name="arguments"></param> /// <param name="closeBracket"></param> public ArmBracketedArgumentListAst(OpenBracketToken openBracket, IList <ArmExpressionAst> arguments, CloseBracketToken closeBracket) { this.OpenBracket = openBracket ?? throw new ArgumentNullException(nameof(openBracket)); this.ArgumentList = new ReadOnlyCollection <ArmExpressionAst>( arguments ?? throw new ArgumentNullException(nameof(arguments)) ); this.CloseBracket = closeBracket ?? throw new ArgumentNullException(nameof(closeBracket)); }
/// <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); } } } } }
public override void Accept(SyntaxVisitor visitor) { if (visitor.VisitAttributeListSyntax(this, VisitKind.Enter)) { OpenBracketToken.Accept(visitor); foreach (var attribute in Attributes) { attribute.Accept(visitor); } CloseBracketToken.Accept(visitor); visitor.VisitAttributeListSyntax(this, VisitKind.Leave); } }
public void TestMethodArrayParamWithSpace() => Verify( "M.N(string[ , , ] s)", methodDeclaration: MethodDeclaration( QualifiedName("M.N"), argumentList: ParameterList( Parameter( ArrayType(Identifier("string"), ArrayRankSpecifier( OpenBracketToken.With(trailingTrivia: SpaceTrivia().ToImmutableArray()), CloseBracketToken.With(trailingTrivia: SpaceTrivia().ToImmutableArray()), CommaToken.With(trailingTrivia: SpaceTrivia().ToImmutableArray()), CommaToken.With(trailingTrivia: SpaceTrivia().ToImmutableArray()))), IdentifierToken("s") ) )) );
/// <summary> /// Checks a method or method invocation to ensure that the opening bracket is /// on the same line as the method declaration. /// </summary> /// <param name="element">The element containing the expression.</param> /// <param name="parameterList">The argument list.</param> /// <param name="openingBracketType">The type of the bracket that opens the argument list.</param> /// <returns>Returns the opening bracket.</returns> private OpenBracketToken CheckMethodOpeningBracket(Element element, CodeUnit parameterList, TokenType openingBracketType) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(parameterList, "parameterList"); Param.Ignore(openingBracketType); // Find the opening bracket. OpenBracketToken openingBracket = null; Token firstDeclarationToken = element.FirstDeclarationToken; if (firstDeclarationToken != null) { Token previous = parameterList.FindPreviousSiblingToken(); if (previous != null && previous.Is(openingBracketType)) { openingBracket = (OpenBracketToken)previous; } if (openingBracket != null) { // Find the last word before the opening bracket. Token lastWord = openingBracket.FindPreviousToken(); if (lastWord != null && openingBracket.LineNumber != lastWord.LineNumber) { this.AddViolation( element, openingBracket.LineNumber, Rules.OpeningParenthesisMustBeOnDeclarationLine, element.FriendlyTypeText); } } } return(openingBracket); }
/// <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)); } } } }
/// <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); } } } }