/// <summary> /// Checks a string to determine whether it is using an incorrect empty string notation. /// </summary> /// <param name="text">The string to check.</param> /// <param name="parentElement">The parent element.</param> private void CheckEmptyString(Token text, Element parentElement) { Param.AssertNotNull(text, "text"); Param.AssertNotNull(parentElement, "parentElement"); Debug.Assert(text.TokenType == TokenType.String, "The token must be a string."); if (string.Equals(text.Text, "\"\"", StringComparison.Ordinal) || string.Equals(text.Text, "@\"\"", StringComparison.Ordinal)) { // Look at the previous token. If it is the 'case' keyword, then do not throw this // exception. It is illegal to write case: String.Empty and instead case: "" must be written. Token previousToken = text.FindPreviousToken(); if (previousToken == null || (previousToken.TokenType != TokenType.Case && !IsConstVariableDeclaration(previousToken))) { this.Violation( Rules.UseStringEmptyForEmptyStrings, new ViolationContext(parentElement, text.LineNumber), (c, o) => { // Fix the violation. CsDocument document = text.Document; // Create a member access expression which represents "string.Empty". var stringEmpty = document.CreateMemberAccessExpression(document.CreateLiteralExpression("string"), document.CreateLiteralExpression("Empty")); // The parent of the token should be a literal expression. if (text.Parent != null && text.Parent.Is(ExpressionType.Literal)) { document.Replace(text.Parent, stringEmpty); } else { Debug.Fail("Unhandled situation"); } }); } } }
/// <summary> /// Determines whether the statement is declaring a const field or variable. /// </summary> /// <param name="assignmentOperator">The assignment operator for the variable declaration.</param> /// <returns>Returns true if the statement is declaring a const, false otherwise.</returns> private static bool IsConstVariableDeclaration(Token assignmentOperator) { Param.Ignore(assignmentOperator); if (assignmentOperator != null && assignmentOperator.Text == "=") { // Work backwards until we find the keyword const, or have moved past the beginning of the statement. Token token = assignmentOperator.FindPreviousToken(); while (token != null) { if (token.TokenType == TokenType.CloseParenthesis || token.TokenType == TokenType.OpenParenthesis || token.TokenType == TokenType.OpenCurlyBracket || token.TokenType == TokenType.CloseCurlyBracket || token.TokenType == TokenType.Semicolon) { break; } else if (token.TokenType == TokenType.Const) { return true; } token = token.FindPreviousToken(); } } return false; }