/// <summary> /// Checks a open bracket for spacing. /// </summary> /// <param name="token">The token to check.</param> private void CheckOpenSquareBracket(Token token) { Param.AssertNotNull(token, "token"); // Open brackets should be never be preceded by whitespace. LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem != null) { if (previousItem.LexicalElementType == LexicalElementType.WhiteSpace || previousItem.LexicalElementType == LexicalElementType.EndOfLine) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.OpeningSquareBracketsMustBeSpacedCorrectly); } } // Open brackets should never be followed by whitespace. LexicalElement nextItem = token.FindNextLexicalElement(); if (nextItem != null && (nextItem.LexicalElementType == LexicalElementType.WhiteSpace || nextItem.LexicalElementType == LexicalElementType.EndOfLine)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.OpeningSquareBracketsMustBeSpacedCorrectly); } }
private void CheckOpenParen(CodeUnit root, Token token) { Param.AssertNotNull(root, "root"); Param.AssertNotNull(token, "token"); bool firstOnLine = false; bool lastOnLine = false; // Open parenthesis should never be preceded by whitespace unless it is the // first thing on the line or it follows a keyword or it follows a symbol or a number. LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem != null) { if (previousItem.LexicalElementType == LexicalElementType.WhiteSpace) { for (LexicalElement item = previousItem.FindPreviousLexicalElement(); item != null; item = item.FindPreviousLexicalElement()) { if (item.LexicalElementType == LexicalElementType.WhiteSpace) { continue; } else if (item.LexicalElementType == LexicalElementType.EndOfLine) { firstOnLine = true; break; } else if ( item.Is(TokenType.Case) || item.Is(TokenType.Catch) || item.Is(TokenType.CloseSquareBracket) || item.Is(TokenType.Comma) || item.Is(TokenType.Equals) || item.Is(TokenType.Fixed) || item.Is(TokenType.For) || item.Is(TokenType.Foreach) || item.Is(TokenType.From) || ////item.Is(TokenType.Goto) || item.Is(TokenType.Group) || item.Is(TokenType.If) || item.Is(TokenType.In) || item.Is(TokenType.Into) || item.Is(TokenType.Join) || item.Is(TokenType.Let) || item.Is(TokenType.Lock) || item.Is(CommentType.MultilineComment) || ////item.Is(TokenType.New) || item.Is(TokenType.Number) || item.Is(TokenType.OperatorSymbol) || item.Is(TokenType.OpenCurlyBracket) || item.Is(TokenType.OrderBy) || item.Is(TokenType.Return) || item.Is(TokenType.Select) || item.Is(TokenType.Semicolon) || ////item.Is(CommentType.SingleLineComment) || item.Is(TokenType.Switch) || item.Is(TokenType.Throw) || item.Is(TokenType.Using) || item.Is(TokenType.Where) || item.Is(TokenType.While) || item.Is(TokenType.WhileDo) || item.Is(TokenType.Yield)) { break; } else { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.OpeningParenthesisMustBeSpacedCorrectly); } } } } // Open parens should never be followed by whitespace unless // it is the last thing on the line. LexicalElement next = token.FindPreviousLexicalElement(); if (next != null && (next.LexicalElementType == LexicalElementType.WhiteSpace || next.LexicalElementType == LexicalElementType.EndOfLine)) { // Look to see if there is any non whitespace character // on this line other than a comment. for (LexicalElement item = next.FindNextLexicalElement(); item != null; item = item.FindNextLexicalElement()) { if (item.LexicalElementType == LexicalElementType.EndOfLine) { lastOnLine = true; break; } else if (item.LexicalElementType != LexicalElementType.WhiteSpace && !item.Is(CommentType.SingleLineComment) && !item.Is(CommentType.MultilineComment)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.OpeningParenthesisMustBeSpacedCorrectly); break; } } } // Open parens cannot be the only thing on the line. if (firstOnLine && lastOnLine) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.OpeningParenthesisMustBeSpacedCorrectly); } }
private void CheckCloseParen(CodeUnit root, Token token) { Param.AssertNotNull(root, "root"); Param.AssertNotNull(token, "token"); // Close parens should never be preceded by whitespace. LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem != null && (previousItem.LexicalElementType == LexicalElementType.WhiteSpace || previousItem.LexicalElementType == LexicalElementType.EndOfLine)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.ClosingParenthesisMustBeSpacedCorrectly); } // Find out what comes after the closing paren. LexicalElement nextItem = token.FindNextLexicalElement(); LexicalElement nextNextItem = nextItem == null ? null : nextItem.FindNextLexicalElement(); if (nextItem != null) { if (token.Parent is CastExpression) { // There should not be any whitespace after the closing parenthesis in a cast expression. if (nextItem.LexicalElementType == LexicalElementType.WhiteSpace) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.ClosingParenthesisMustBeSpacedCorrectly); } } else if (nextItem.Is(TokenType.LabelColon) || (nextNextItem != null && nextNextItem.Is(TokenType.LabelColon))) { // If the next token is a colon, it's allowed to omit the whitespace only if we are in a switch\case statement. bool followsCase = false; for (LexicalElement item = token.FindPreviousLexicalElement(); item != null; item = item.FindPreviousLexicalElement()) { if (item.LexicalElementType == LexicalElementType.EndOfLine) { break; } else if (item.Is(TokenType.Case)) { followsCase = true; break; } } if ((followsCase && nextItem.LexicalElementType == LexicalElementType.WhiteSpace) || (!followsCase && nextItem.LexicalElementType != LexicalElementType.WhiteSpace)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.ClosingParenthesisMustBeSpacedCorrectly); } } else if (nextItem.LexicalElementType == LexicalElementType.WhiteSpace) { if (nextNextItem != null) { // Make sure that the character just after the whitespace is not a paren, bracket, a comma, or a semicolon. for (LexicalElement item = nextNextItem; item != null; item = item.FindNextLexicalElement()) { if (IsAllowedAfterClosingParenthesis(item)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.ClosingParenthesisMustBeSpacedCorrectly); } else if (item.LexicalElementType != LexicalElementType.WhiteSpace) { break; } } } } else { // For all other types, the parenthesis must be followed by whitespace, unless the next character is a paren, bracket, comma, or a semicolon. if (nextItem.LexicalElementType != LexicalElementType.EndOfLine && !IsAllowedAfterClosingParenthesis(nextItem)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.ClosingParenthesisMustBeSpacedCorrectly); } } } }
private void CheckSemicolonAndComma(Token token) { Param.AssertNotNull(token, "token"); bool comma = false; if (token.Text == ",") { comma = true; } else { Debug.Assert(token.Text == ";", "The token should either be a comma or a semicolon"); } // There is a special case here where we allow <,,> [,,] or (;;), or variations thereof. // In these cases, there should be no spaces around the comma or semicolon. string[] open = new string[] { "[", "<" }; string[] close = new string[] { "]", ">" }; if (!comma) { open = new string[] { "(" }; close = new string[] { ")" }; } bool specialCaseBackwards = true; bool specialCaseForwards = true; // Work backwards and look for the previous character on this line. bool found = false; LexicalElement item = token.FindPreviousLexicalElement(); if (item != null) { for (int i = 0; i < open.Length; ++i) { if (item.Text == open[i]) { found = true; break; } } if (!found) { if (item.Text == token.Text) { found = true; } else { specialCaseBackwards = false; } } } if (!found) { specialCaseBackwards = false; } // Work forwards and look for the next character on this line. found = false; item = token.FindNextLexicalElement(); if (item != null) { for (int i = 0; i < close.Length; ++i) { if (item.Text == close[i]) { found = true; break; } } if (!found) { if (item.Text == token.Text) { found = true; } else { specialCaseForwards = false; } } } if (!found) { specialCaseForwards = false; } if (!specialCaseBackwards) { LexicalElement previousItem = token.FindPreviousLexicalElement(); // Make sure this is not preceded by whitespace. if (previousItem != null && (previousItem.LexicalElementType == LexicalElementType.WhiteSpace || previousItem.LexicalElementType == LexicalElementType.EndOfLine)) { this.AddViolation( token.FindParentElement(), token.LineNumber, comma ? Rules.CommasMustBeSpacedCorrectly : Rules.SemicolonsMustBeSpacedCorrectly); } } if (!specialCaseForwards) { LexicalElement nextItem = token.FindNextLexicalElement(); // Make sure this is followed by whitespace or a close paren. if (nextItem != null && nextItem.LexicalElementType != LexicalElementType.WhiteSpace && nextItem.LexicalElementType != LexicalElementType.EndOfLine && !nextItem.Is(TokenType.CloseParenthesis)) { this.AddViolation( token.FindParentElement(), token.LineNumber, comma ? Rules.CommasMustBeSpacedCorrectly : Rules.SemicolonsMustBeSpacedCorrectly); } } }
/// <summary> /// Checks a symbol for spacing. /// </summary> /// <param name="root">The container to parse.</param> /// <param name="token">The token to check.</param> private void CheckSymbol(CodeUnit root, Token token) { Param.AssertNotNull(root, "root"); Param.AssertNotNull(token, "token"); // Symbols should have whitespace on both sides. LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem != null && previousItem.LexicalElementType != LexicalElementType.WhiteSpace && previousItem.LexicalElementType != LexicalElementType.EndOfLine) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.SymbolsMustBeSpacedCorrectly, token.Text); } LexicalElement nextItem = token.FindNextLexicalElement(); if (nextItem != null && nextItem.LexicalElementType != LexicalElementType.WhiteSpace && nextItem.LexicalElementType != LexicalElementType.EndOfLine) { // Make sure the previous token is not operator. if (previousItem != null) { for (LexicalElement item = previousItem.FindPreviousLexicalElement(); item != null; item = item.FindPreviousLexicalElement()) { if (item.Is(TokenType.Operator)) { return; } else if (item.LexicalElementType != LexicalElementType.WhiteSpace && item.LexicalElementType != LexicalElementType.EndOfLine && !item.Is(CommentType.SingleLineComment) && !item.Is(CommentType.MultilineComment) && item.LexicalElementType != LexicalElementType.PreprocessorDirective) { break; } } } this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.SymbolsMustBeSpacedCorrectly, token.Text); } }
/// <summary> /// Checks a label colon for spacing. /// </summary> /// <param name="token">The token to check.</param> private void CheckLabelColon(Token token) { Param.AssertNotNull(token, "token"); // A colon should always be followed by whitespace, but never preceded by whitespace. LexicalElement nextItem = token.FindNextLexicalElement(); if (nextItem == null) { if (nextItem.LexicalElementType != LexicalElementType.WhiteSpace && nextItem.LexicalElementType != LexicalElementType.EndOfLine) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.ColonsMustBeSpacedCorrectly); } } LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem != null) { if (previousItem.LexicalElementType == LexicalElementType.WhiteSpace || previousItem.LexicalElementType == LexicalElementType.EndOfLine || previousItem.Is(CommentType.SingleLineComment) || previousItem.Is(CommentType.MultilineComment)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.ColonsMustBeSpacedCorrectly); } } }
/// <summary> /// Checks a unary symbol for spacing. /// </summary> /// <param name="token">The token to check.</param> private void CheckUnarySymbol(Token token) { Param.AssertNotNull(token, "token"); // These symbols should be preceded by whitespace but not followed by whitespace. They can // also be preceded by an open paren or an open square bracket. LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem != null) { if (previousItem.LexicalElementType != LexicalElementType.WhiteSpace && previousItem.LexicalElementType != LexicalElementType.EndOfLine && !previousItem.Is(TokenType.OpenParenthesis) && !previousItem.Is(TokenType.OpenSquareBracket)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.SymbolsMustBeSpacedCorrectly, token.Text); } } LexicalElement nextItem = token.FindNextLexicalElement(); if (nextItem == null) { if (nextItem.LexicalElementType == LexicalElementType.WhiteSpace || nextItem.LexicalElementType == LexicalElementType.EndOfLine || nextItem.Is(CommentType.SingleLineComment) || nextItem.Is(CommentType.MultilineComment)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.SymbolsMustBeSpacedCorrectly, token.Text); } } }
/// <summary> /// Checks a positive sign for spacing. /// </summary> /// <param name="token">The token to check.</param> private void CheckPositiveSign(Token token) { Param.AssertNotNull(token, "token"); // A positive sign should be preceded by whitespace. It // can also be preceded by an open paren or an open bracket. LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem != null) { if (previousItem.LexicalElementType != LexicalElementType.WhiteSpace && previousItem.LexicalElementType != LexicalElementType.EndOfLine && !previousItem.Is(TokenType.OpenParenthesis) && !previousItem.Is(TokenType.OpenSquareBracket) && !previousItem.Is(TokenType.CloseParenthesis)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.PositiveSignsMustBeSpacedCorrectly); } } LexicalElement nextItem = token.FindNextLexicalElement(); if (nextItem != null) { if (nextItem.LexicalElementType == LexicalElementType.WhiteSpace || nextItem.LexicalElementType == LexicalElementType.EndOfLine || nextItem.Is(CommentType.SingleLineComment) || nextItem.Is(CommentType.MultilineComment)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.PositiveSignsMustBeSpacedCorrectly); } } }
private void CheckUnsafeAccessSymbols(Token token, bool type) { Param.AssertNotNull(token, "token"); Param.Ignore(type); // In a type declaration, the symbol must have whitespace on the right but // not on the left. If this is not a type declaration, the opposite is true. if (type) { // The symbol should be followed by whitespace. It // can also be followed by a closing paren or a closing bracket, // or another token of the same type. LexicalElement nextItem = token.FindNextLexicalElement(); if (nextItem != null) { if (nextItem.LexicalElementType != LexicalElementType.WhiteSpace && nextItem.LexicalElementType != LexicalElementType.EndOfLine && !nextItem.Is(TokenType.OpenParenthesis) && !nextItem.Is(TokenType.OpenSquareBracket) && !nextItem.Is(TokenType.CloseParenthesis) && !nextItem.Is(token.TokenType)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.DereferenceAndAccessOfSymbolsMustBeSpacedCorrectly); } } // The symbol must not be preceded by whitespace. LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem != null) { if (previousItem.LexicalElementType == LexicalElementType.WhiteSpace || previousItem.LexicalElementType == LexicalElementType.EndOfLine || previousItem.Is(CommentType.SingleLineComment) || previousItem.Is(CommentType.MultilineComment)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.DereferenceAndAccessOfSymbolsMustBeSpacedCorrectly); } } } else { // The symbol should be preceded by whitespace. It // can also be preceded by an open paren or an open bracket, or // another token of the same type. LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem != null) { if (previousItem.LexicalElementType != LexicalElementType.WhiteSpace && previousItem.LexicalElementType != LexicalElementType.EndOfLine && !previousItem.Is(TokenType.OpenParenthesis) && !previousItem.Is(TokenType.OpenSquareBracket) && !previousItem.Is(TokenType.CloseParenthesis) && !previousItem.Is(token.TokenType)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.DereferenceAndAccessOfSymbolsMustBeSpacedCorrectly); } } // The symbol must not be followed by whitespace. LexicalElement nextItem = token.FindNextLexicalElement(); if (nextItem == null) { if (nextItem.LexicalElementType == LexicalElementType.WhiteSpace || nextItem.LexicalElementType == LexicalElementType.EndOfLine || nextItem.Is(CommentType.SingleLineComment) || nextItem.Is(CommentType.MultilineComment)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.DereferenceAndAccessOfSymbolsMustBeSpacedCorrectly); } } } }
/// <summary> /// Checks a member access symbol for spacing. /// </summary> /// <param name="root">The container to parse.</param> /// <param name="token">The token to check.</param> private void CheckMemberAccessSymbol(CodeUnit root, Token token) { Param.AssertNotNull(root, "root"); Param.AssertNotNull(token, "token"); // Member access symbols should not have any whitespace on either side. LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem == null) { if (previousItem.LexicalElementType == LexicalElementType.WhiteSpace || previousItem.LexicalElementType == LexicalElementType.EndOfLine || previousItem.Is(CommentType.SingleLineComment) || previousItem.Is(CommentType.MultilineComment)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.MemberAccessSymbolsMustBeSpacedCorrectly); } } LexicalElement nextItem = token.FindNextLexicalElement(); if (nextItem == null) { if (nextItem.LexicalElementType == LexicalElementType.WhiteSpace || nextItem.LexicalElementType == LexicalElementType.EndOfLine || nextItem.Is(CommentType.SingleLineComment) || nextItem.Is(CommentType.MultilineComment)) { // Make sure the previous token is not the operator keyword. if (previousItem != null) { for (LexicalElement item = previousItem.FindPreviousLexicalElement(); item != null; item = item.FindPreviousLexicalElement()) { if (item.Is(TokenType.Operator)) { return; } else if (item.LexicalElementType != LexicalElementType.WhiteSpace && item.LexicalElementType != LexicalElementType.EndOfLine && !item.Is(CommentType.SingleLineComment) && !item.Is(CommentType.MultilineComment)) { break; } } } this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.MemberAccessSymbolsMustBeSpacedCorrectly); } } }
/// <summary> /// Checks an increment or decrement sign for spacing. /// </summary> /// <param name="token">The token to check.</param> private void CheckIncrementDecrement(Token token) { Param.AssertNotNull(token, "token"); // Increment and decrement symbols should have whitespace on only one side. The non-whitespace // side is also allowed to butt up against a bracket or a parenthesis, however. bool before = false; bool after = false; LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem == null) { before = true; } else { if (previousItem.LexicalElementType == LexicalElementType.WhiteSpace || previousItem.LexicalElementType == LexicalElementType.EndOfLine || previousItem.Is(CommentType.SingleLineComment) || previousItem.Is(CommentType.MultilineComment)) { before = true; } } LexicalElement nextItem = token.FindNextLexicalElement(); if (nextItem == null) { after = true; } else { if (nextItem.LexicalElementType == LexicalElementType.WhiteSpace || nextItem.LexicalElementType == LexicalElementType.EndOfLine || nextItem.Is(CommentType.SingleLineComment) || nextItem.Is(CommentType.MultilineComment)) { after = true; } } // If there is no whitespace on either side, then make sure that at least one of the sides // is touching a square bracket or a parenthesis. The right side of the symbol is also // allowed to be up against a comma or a semicolon. if (!before && !after) { if (previousItem != null && (previousItem.Is(TokenType.OpenSquareBracket) || previousItem.Is(TokenType.OpenParenthesis))) { return; } if (nextItem != null) { if (nextItem.Is(TokenType.CloseSquareBracket) || nextItem.Is(TokenType.CloseParenthesis) || nextItem.Is(TokenType.Comma) || nextItem.Is(TokenType.Semicolon)) { return; } } // This is a violation. this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.IncrementDecrementSymbolsMustBeSpacedCorrectly); } else if (before && after) { // There is whitespace on both sides. this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.IncrementDecrementSymbolsMustBeSpacedCorrectly); } }
/// <summary> /// Checks a nullable type symbol for spacing. /// </summary> /// <param name="token">The token to check.</param> private void CheckNullableTypeSymbol(Token token) { Param.AssertNotNull(token, "token"); // Nullable type symbols should never be preceded by whitespace. LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem != null && (previousItem.LexicalElementType == LexicalElementType.WhiteSpace || previousItem.LexicalElementType == LexicalElementType.EndOfLine)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.NullableTypeSymbolsMustNotBePrecededBySpace); } }
/// <summary> /// Checks a closing attribute bracket for spacing. /// </summary> /// <param name="token">The token to check.</param> private void CheckAttributeTokenCloseBracket(Token token) { Param.AssertNotNull(token, "token"); // Closing attribute brackets should be never be preceded by whitespace. LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem != null) { if (previousItem.LexicalElementType == LexicalElementType.WhiteSpace || previousItem.LexicalElementType == LexicalElementType.EndOfLine) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.ClosingAttributeBracketsMustBeSpacedCorrectly); } } }
/// <summary> /// Checks a close bracket for spacing. /// </summary> /// <param name="root">The container to parse.</param> /// <param name="token">The token to check.</param> private void CheckCloseCurlyBracket(CodeUnit root, Token token) { Param.AssertNotNull(root, "root"); Param.AssertNotNull(token, "token"); // Close curly brackets should always be preceded by whitespace. LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem != null && previousItem.LexicalElementType != LexicalElementType.WhiteSpace && previousItem.LexicalElementType != LexicalElementType.EndOfLine) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.ClosingCurlyBracketsMustBeSpacedCorrectly); } // Close curly brackets should be followed either by whitespace, a close paren, // a semicolon, or a comma. LexicalElement nextItem = token.FindNextLexicalElement(); if (nextItem != null) { if (nextItem.LexicalElementType != LexicalElementType.WhiteSpace && nextItem.LexicalElementType != LexicalElementType.EndOfLine && !nextItem.Is(TokenType.CloseParenthesis) && !nextItem.Is(TokenType.Semicolon) && !nextItem.Is(TokenType.Comma)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.ClosingCurlyBracketsMustBeSpacedCorrectly); } if (nextItem.LexicalElementType == LexicalElementType.WhiteSpace) { // If this is followed by whitespace, make sure that the character just // after the whitespace is not a close paren, semicolon, or comma. for (LexicalElement item = nextItem.FindNextLexicalElement(); item != null; item = item.FindNextLexicalElement()) { if (item.Is(TokenType.CloseParenthesis) || item.Is(TokenType.Semicolon) || item.Is(TokenType.Comma)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.ClosingCurlyBracketsMustBeSpacedCorrectly); } else if (item.LexicalElementType != LexicalElementType.WhiteSpace) { break; } } } } }
/// <summary> /// Checks a open bracket for spacing. /// </summary> /// <param name="root">The container to parse.</param> /// <param name="token">The token to check.</param> private void CheckOpenCurlyBracket(CodeUnit root, Token token) { Param.AssertNotNull(root, "root"); Param.AssertNotNull(token, "token"); // Open curly brackets should be preceded either by whitespace, or an open paren. LexicalElement previousItem = token.FindPreviousLexicalElement(); if (previousItem != null) { if (previousItem.LexicalElementType != LexicalElementType.WhiteSpace && previousItem.LexicalElementType != LexicalElementType.EndOfLine && !previousItem.Is(TokenType.OpenParenthesis)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.OpeningCurlyBracketsMustBeSpacedCorrectly); } if (previousItem.LexicalElementType == LexicalElementType.WhiteSpace) { // If this is preceded by whitespace, make sure that the character just // before the whitespace is not an open paren. for (LexicalElement item = previousItem.FindPreviousLexicalElement(); item != null; item = item.FindPreviousLexicalElement()) { if (item.Is(TokenType.OpenParenthesis)) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.OpeningCurlyBracketsMustBeSpacedCorrectly); } else if (item.LexicalElementType != LexicalElementType.WhiteSpace) { break; } } } } // Open curly brackets should always be followed by whitespace. LexicalElement nextItem = token.FindNextLexicalElement(); if (nextItem != null && nextItem.LexicalElementType != LexicalElementType.WhiteSpace && nextItem.LexicalElementType != LexicalElementType.EndOfLine) { this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.OpeningCurlyBracketsMustBeSpacedCorrectly); } }
/// <summary> /// Determines whether the given bracket is the only thing on its line or whether it shares the line. /// </summary> /// <param name="bracketNode">The bracket to check.</param> /// <param name="allowTrailingCharacters">Indicates whether a semicolon, comma or closing parenthesis after the /// bracket is allowed.</param> /// <returns>Returns true if the bracket shares the line with something else.</returns> private static bool BracketSharesLine(Token bracketNode, bool allowTrailingCharacters) { Param.AssertNotNull(bracketNode, "bracketNode"); Param.Ignore(allowTrailingCharacters); // Look forward. bool sharesLine = false; // Find the next non-whitespace or comment item. LexicalElement nextItem = null; for (LexicalElement item = bracketNode.FindNextLexicalElement(); item != null; item = item.FindNextLexicalElement()) { if (item.LexicalElementType == LexicalElementType.EndOfLine) { break; } else if (item.LexicalElementType != LexicalElementType.WhiteSpace && item.LexicalElementType != LexicalElementType.Comment) { nextItem = item; break; } } if (nextItem != null) { if (!allowTrailingCharacters || (!nextItem.Is(TokenType.Semicolon) && !nextItem.Is(TokenType.Comma) && !nextItem.Is(TokenType.CloseParenthesis) && !nextItem.Is(TokenType.CloseSquareBracket))) { sharesLine = true; } } if (!sharesLine) { // Look backwards. for (LexicalElement item = bracketNode.FindPreviousLexicalElement(); item != null; item = item.FindPreviousLexicalElement()) { if (item.LexicalElementType == LexicalElementType.EndOfLine) { break; } else if (item.LexicalElementType != LexicalElementType.WhiteSpace && !item.Is(CommentType.SingleLineComment)) { sharesLine = true; break; } } } return sharesLine; }