/// <summary> /// Checks the placement of the given statement. /// </summary> /// <param name="element"> /// The element containing the statement. /// </param> /// <param name="statement"> /// The statement to check. /// </param> /// <param name="previousStatement"> /// The statement just before this statement. /// </param> private void CheckStatementFormattingRulesForStatement(CsElement element, Statement statement, Statement previousStatement) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(statement, "statement"); Param.Ignore(previousStatement); // Check if the statement is empty. if (statement.StatementType == StatementType.Empty) { Debug.Assert(statement.Tokens.First != null, "The statement has no tokens."); // There is a special case where an empty statement is allowed. In some cases, a label statement must be used to mark the end of a // scope. C# requires that labels have at least one statement after them. In the developer wants to use a label to mark the end of the // scope, he does not want to put a statement after the label. The best course of action is to insert a single semicolon here. For example:\ //// { //// if (true) //// { //// goto end; //// } //// end:; //// } if (previousStatement == null || previousStatement.StatementType != StatementType.Label) { this.AddViolation(element, statement.LineNumber, Rules.CodeMustNotContainEmptyStatements); } } else if (previousStatement != null) { // Make sure this statement is not on the same line as the previous statement. Node <CsToken> statementFirstTokenNode = statement.Tokens.First; Node <CsToken> previousStatementLastTokenNode = previousStatement.Tokens.Last; if (statementFirstTokenNode.Value.Location.StartPoint.LineNumber == previousStatementLastTokenNode.Value.Location.EndPoint.LineNumber) { this.AddViolation(element, statementFirstTokenNode.Value.LineNumber, Rules.CodeMustNotContainMultipleStatementsOnOneLine); } } // Check the curly bracket spacing in this statement. this.CheckStatementCurlyBracketPlacement(element, statement); // Check the child statements under this statement. this.CheckStatementFormattingRulesForStatements(element, statement.ChildStatements); // Check the expressions under this statement. this.CheckStatementFormattingRulesForExpressions(element, statement.ChildExpressions); }
private void CheckStatementCurlyBracketPlacement(CsElement element, Statement statement) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(statement, "statement"); switch (statement.StatementType) { case StatementType.Else: // Check that there is nothing between the starting else keyword and the opening bracket. this.CheckChainedStatementCurlyBracketPlacement(element, statement); this.CheckBlockStatementsCurlyBracketPlacement(element, statement); // Check that there is nothing between the closing bracket and the else keyword of the attached else statement. ElseStatement elseStatement = (ElseStatement)statement; if (elseStatement.AttachedElseStatement != null) { this.CheckTrailingStatementCurlyBracketPlacement(element, statement); } break; case StatementType.Catch: case StatementType.Finally: // Check that there is nothing between the starting catch or finally keyword and the opening bracket. this.CheckChainedStatementCurlyBracketPlacement(element, statement); this.CheckBlockStatementsCurlyBracketPlacement(element, statement); break; case StatementType.If: this.CheckBlockStatementsCurlyBracketPlacement(element, statement); // Check that there is nothing between the closing bracket and the else keyword of the attached else statement. IfStatement ifStatement = (IfStatement)statement; if (ifStatement.AttachedElseStatement != null) { this.CheckTrailingStatementCurlyBracketPlacement(element, statement); } break; case StatementType.Try: // Check that there is nothing between the starting try keyword and the opening bracket. this.CheckBlockStatementsCurlyBracketPlacement(element, statement); TryStatement tryStatement = (TryStatement)statement; if (tryStatement.FinallyStatement != null || (tryStatement.CatchStatements != null && tryStatement.CatchStatements.Count > 0)) { // There is something attached to the end of this try statement. Check that there is nothing between // the closing bracket of the try statement and the start of the attached statement. this.CheckTrailingStatementCurlyBracketPlacement(element, tryStatement); } if (tryStatement.CatchStatements != null && tryStatement.CatchStatements.Count > 0) { CatchStatement[] catchStatementArray = new CatchStatement[tryStatement.CatchStatements.Count]; tryStatement.CatchStatements.CopyTo(catchStatementArray, 0); for (int i = 0; i < catchStatementArray.Length; ++i) { if (catchStatementArray.Length > i + 1 || tryStatement.FinallyStatement != null) { // There is something attached to the end of this catch statement, either another catch or a finally. // Check that there is nothing between the closing bracket of this catch statement and the start of the attached // statement. this.CheckTrailingStatementCurlyBracketPlacement(element, catchStatementArray[i]); } } } break; case StatementType.Checked: case StatementType.Fixed: case StatementType.For: case StatementType.Foreach: case StatementType.Lock: case StatementType.Switch: case StatementType.Unchecked: case StatementType.Unsafe: case StatementType.Using: case StatementType.While: // Check that there is nothing between the starting keyword and the opening bracket. this.CheckBlockStatementsCurlyBracketPlacement(element, statement); break; case StatementType.DoWhile: this.CheckBlockStatementsCurlyBracketPlacement(element, statement); this.CheckTrailingStatementCurlyBracketPlacement(element, statement); break; default: break; } }