New internal check: Catch extra whitespace in match patterns

Inspired by a recent commit from PKEuS.
This commit is contained in:
Thomas Jarosch 2014-12-30 14:21:18 +01:00
parent 208761f0c3
commit 17b47f1ce0
3 changed files with 84 additions and 0 deletions

View File

@ -283,6 +283,32 @@ void CheckInternal::checkRedundantNextPrevious()
}
}
void CheckInternal::checkExtraWhitespace()
{
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
if (!Token::simpleMatch(tok, "Token :: simpleMatch (") &&
!Token::simpleMatch(tok, "Token :: findsimplematch (") &&
!Token::simpleMatch(tok, "Token :: Match (") &&
!Token::simpleMatch(tok, "Token :: findmatch ("))
continue;
const std::string& funcname = tok->strAt(2);
// Get pattern string
const Token *pattern_tok = tok->tokAt(4)->nextArgument();
if (!pattern_tok || pattern_tok->type() != Token::eString)
continue;
const std::string pattern = pattern_tok->strValue();
if (!pattern.empty() && (pattern[0] == ' ' || *pattern.rbegin() == ' '))
extraWhitespaceError(tok, pattern, funcname);
// two whitespaces or more
if (pattern.find(" ") != std::string::npos)
extraWhitespaceError(tok, pattern, funcname);
}
}
void CheckInternal::multiComparePatternError(const Token* tok, const std::string& pattern, const std::string &funcname)
{
reportError(tok, Severity::error, "multiComparePatternError",
@ -329,4 +355,11 @@ void CheckInternal::orInComplexPattern(const Token* tok, const std::string& patt
"Token::" + funcname + "() pattern \"" + pattern + "\" contains \"||\" or \"|\". Replace it by \"%oror%\" or \"%or%\".");
}
void CheckInternal::extraWhitespaceError(const Token* tok, const std::string& pattern, const std::string &funcname)
{
reportError(tok, Severity::warning, "extraWhitespaceError",
"Found extra whitespace inside Token::" + funcname + "() call: \"" + pattern + "\""
);
}
#endif // #ifdef CHECK_INTERNAL

View File

@ -53,6 +53,7 @@ public:
checkInternal.checkMissingPercentCharacter();
checkInternal.checkUnknownPattern();
checkInternal.checkRedundantNextPrevious();
checkInternal.checkExtraWhitespace();
}
/** @brief %Check if a simple pattern is used inside Token::Match or Token::findmatch */
@ -70,6 +71,9 @@ public:
/** @brief %Check for inefficient usage of Token::next(), Token::previous() and Token::tokAt() */
void checkRedundantNextPrevious();
/** @brief %Check if there is whitespace at the beginning or at the end of a pattern */
void checkExtraWhitespace();
private:
void multiComparePatternError(const Token *tok, const std::string &pattern, const std::string &funcname);
void simplePatternError(const Token *tok, const std::string &pattern, const std::string &funcname);
@ -78,6 +82,7 @@ private:
void unknownPatternError(const Token* tok, const std::string& pattern);
void redundantNextPreviousError(const Token* tok, const std::string& func1, const std::string& func2);
void orInComplexPattern(const Token *tok, const std::string &pattern, const std::string &funcname);
void extraWhitespaceError(const Token *tok, const std::string &pattern, const std::string &funcname);
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
CheckInternal c(0, settings, errorLogger);
@ -88,6 +93,7 @@ private:
c.unknownPatternError(0, "%typ");
c.redundantNextPreviousError(0, "previous", "next");
c.orInComplexPattern(0, "||", "Match");
c.extraWhitespaceError(0, "%str% ", "Match");
}
static std::string myName() {

View File

@ -42,6 +42,7 @@ private:
TEST_CASE(internalError)
TEST_CASE(invalidMultiCompare);
TEST_CASE(orInComplexPattern);
TEST_CASE(extraWhitespace);
}
void check(const char code[]) {
@ -375,6 +376,50 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
}
void extraWhitespace() {
// whitespace at the end
check("void f() {\n"
" const Token *tok;\n"
" Token::Match(tok, \"%str% \");\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) Found extra whitespace inside Token::Match() call: \"%str% \"\n", errout.str());
// whitespace at the begin
check("void f() {\n"
" const Token *tok;\n"
" Token::Match(tok, \" %str%\");\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) Found extra whitespace inside Token::Match() call: \" %str%\"\n", errout.str());
// two whitespaces or more
check("void f() {\n"
" const Token *tok;\n"
" Token::Match(tok, \"%str% bar\");\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) Found extra whitespace inside Token::Match() call: \"%str% bar\"\n", errout.str());
// test simpleMatch
check("void f() {\n"
" const Token *tok;\n"
" Token::simpleMatch(tok, \"foobar \");\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) Found extra whitespace inside Token::simpleMatch() call: \"foobar \"\n", errout.str());
// test findmatch
check("void f() {\n"
" const Token *tok;\n"
" Token::findmatch(tok, \"%str% \");\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) Found extra whitespace inside Token::findmatch() call: \"%str% \"\n", errout.str());
// test findsimplematch
check("void f() {\n"
" const Token *tok;\n"
" Token::findsimplematch(tok, \"foobar \");\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) Found extra whitespace inside Token::findsimplematch() call: \"foobar \"\n", errout.str());
}
};
REGISTER_TEST(TestInternal)