diff --git a/src/token.cpp b/src/token.cpp index 1a89315e2..536cfeb41 100644 --- a/src/token.cpp +++ b/src/token.cpp @@ -67,6 +67,22 @@ void Token::deleteNext() _next->previous(this); } +void Token::replace(Token *replaceThis, Token *start, Token *end) +{ + // Fix the whole in the old location of start and end + start->previous()->next(end->next()); + end->next()->previous(start->previous()); + + // Move start and end to their new location + replaceThis->previous()->next(start); + replaceThis->next()->previous(end); + start->previous(replaceThis->previous()); + end->next(replaceThis->next()); + + // Delete old token, which is replaced + delete replaceThis; +} + const Token *Token::tokAt(int index) const { const Token *tok = this; diff --git a/src/token.h b/src/token.h index 01236eda7..3b0f8048a 100644 --- a/src/token.h +++ b/src/token.h @@ -176,6 +176,15 @@ public: */ void printOut(const char *title = 0) const; + /** + * Replace token replaceThis with tokens between start and end, + * including start and end. The replaceThis token is deleted. + * @param replaceThis, this token will be deleted. + * @param start This will be in the place of replaceThis + * @param end This is also in the place of replaceThis + */ + static void replace(Token *replaceThis, Token *start, Token *end); + private: void next(Token *next); void previous(Token *previous); diff --git a/src/tokenize.cpp b/src/tokenize.cpp index 1641782a0..a2d641109 100644 --- a/src/tokenize.cpp +++ b/src/tokenize.cpp @@ -897,6 +897,7 @@ void Tokenizer::simplifyTokenList() } simplifyIfAddBraces(); + simplifyFunctionParameters(); for (Token *tok = _tokens; tok; tok = tok->next()) { @@ -1278,6 +1279,90 @@ bool Tokenizer::simplifyCasts() } +bool Tokenizer::simplifyFunctionParameters() +{ + bool ret = false; + int indentlevel = 0; + for (Token *tok = _tokens; tok; tok = tok->next()) + { + if (tok->str() == "{") + ++indentlevel; + + else if (tok->str() == "}") + --indentlevel; + + // Find the function e.g. foo( x ) or foo( x, y ) + else if (indentlevel == 0 && Token::Match(tok, "%var% ( %var% [,)]")) + { + // We have found old style function, now we need to change it + + // Get list of argument names + std::map argumentNames; + bool bailOut = false; + for (tok = tok->tokAt(2); tok; tok = tok->tokAt(2)) + { + if (!Token::Match(tok, "%var% [,)]")) + { + bailOut = true; + break; + } + + argumentNames[tok->str()] = tok; + if (tok->next()->str() == ")") + { + tok = tok->tokAt(2); + break; + } + } + + if (bailOut) + { + continue; + } + + Token *start = tok; + while (tok && tok->str() != "{") + { + if (tok->str() == ";") + { + tok = tok->previous(); + // Move tokens from start to tok into the place of + // argumentNames[tok->str()] and remove the ";" + + if (argumentNames.find(tok->str()) == argumentNames.end()) + { + bailOut = true; + break; + } + + // Remove the following ";" + Token *temp = tok->tokAt(2); + tok->deleteNext(); + + // Replace "x" with "int x" or similar + Token::replace(argumentNames[tok->str()], start, tok); + ret = true; + tok = temp; + start = tok; + } + else + { + tok = tok->next(); + } + } + + if (bailOut) + { + continue; + } + + ++indentlevel; + } + } + + return ret; +} + bool Tokenizer::simplifyFunctionReturn() { diff --git a/src/tokenize.h b/src/tokenize.h index b27dc4a99..ea3517978 100644 --- a/src/tokenize.h +++ b/src/tokenize.h @@ -139,6 +139,12 @@ private: */ bool simplifyRedundantParanthesis(); + /** + * Simplify functions like "void f(x) int x; {" + * into "void f(int x) {" + */ + bool simplifyFunctionParameters(); + void InsertTokens(Token *dest, Token *src, unsigned int n); Token *_tokensBack; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 39eed0a99..849f04566 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -73,7 +73,7 @@ private: TEST_CASE(doublesharp); - // TODO TEST_CASE(simplify_function_parameters); + TEST_CASE(simplify_function_parameters); TEST_CASE(reduce_redundant_paranthesis); // Ticket #61 } @@ -749,7 +749,7 @@ private: std::ostringstream ostr; for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) ostr << " " << tok->str(); - ASSERT_EQUALS(std::string(" void f ( int x, char y ) { }"), ostr.str()); + ASSERT_EQUALS(std::string(" void f ( int x , char y ) { }"), ostr.str()); } { @@ -771,7 +771,7 @@ private: std::ostringstream ostr; for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) ostr << " " << tok->str(); - ASSERT_EQUALS(std::string(" void foo ( ) { if ( x ) int x ; { } }"), ostr.str()); + ASSERT_EQUALS(std::string(" void foo ( ) { if ( x ) { int x ; } { } }"), ostr.str()); } }