From 70c4bb54b4af33bf117e321c760e317a6eeed0ac Mon Sep 17 00:00:00 2001 From: Reijo Tomperi Date: Thu, 22 Dec 2011 23:13:45 +0200 Subject: [PATCH] Refactoring: Split long function in tokenizer. simplifyTemplatesInstantiate() --- lib/tokenize.cpp | 241 ++++++++++++++++++++++++----------------------- lib/tokenize.h | 7 ++ 2 files changed, 132 insertions(+), 116 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 0525ab293..c896d0030 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -3117,6 +3117,126 @@ int Tokenizer::simplifyTemplatesGetTemplateNamePosition(const Token *tok) return namepos; } +void Tokenizer::simplifyTemplatesExpandTemplate(const Token *tok, + const std::string &name, + std::vector &type, + const std::string &newName, + std::vector &types2, + std::list &used) +{ + int _indentlevel = 0; + int _parlevel = 0; + for (const Token *tok3 = _tokens; tok3; tok3 = tok3->next()) { + if (tok3->str() == "{") + ++_indentlevel; + else if (tok3->str() == "}") + --_indentlevel; + else if (tok3->str() == "(") + ++_parlevel; + else if (tok3->str() == ")") + --_parlevel; + + // Start of template.. + if (tok3 == tok) { + tok3 = tok3->next(); + } + + // member function implemented outside class definition + else if (_indentlevel == 0 && + _parlevel == 0 && + simplifyTemplatesInstantiateMatch(tok3, name, type.size(), ":: ~| %var% (")) { + addtoken(newName.c_str(), tok3->linenr(), tok3->fileIndex()); + while (tok3->str() != "::") + tok3 = tok3->next(); + } + + // not part of template.. go on to next token + else + continue; + + int indentlevel = 0; + std::stack braces; // holds "{" tokens + std::stack brackets; // holds "(" tokens + std::stack brackets2; // holds "[" tokens + + for (; tok3; tok3 = tok3->next()) { + if (tok3->str() == "{") + ++indentlevel; + + else if (tok3->str() == "}") { + if (indentlevel <= 1 && brackets.empty() && brackets2.empty()) { + // there is a bug if indentlevel is 0 + // the "}" token should only be added if indentlevel is 1 but I add it always intentionally + // if indentlevel ever becomes 0, cppcheck will write: + // ### Error: Invalid number of character { + addtoken("}", tok3->linenr(), tok3->fileIndex()); + Token::createMutualLinks(braces.top(), _tokensBack); + braces.pop(); + break; + } + --indentlevel; + } + + + if (tok3->isName()) { + // search for this token in the type vector + unsigned int itype = 0; + while (itype < type.size() && type[itype]->str() != tok3->str()) + ++itype; + + // replace type with given type.. + if (itype < type.size()) { + for (const Token *typetok = types2[itype]; + typetok && !Token::Match(typetok, "[,>]"); + typetok = typetok->next()) { + addtoken(typetok, tok3->linenr(), tok3->fileIndex()); + } + continue; + } + } + + // replace name.. + if (Token::Match(tok3, (name + " !!<").c_str())) { + addtoken(newName.c_str(), tok3->linenr(), tok3->fileIndex()); + continue; + } + + // copy + addtoken(tok3, tok3->linenr(), tok3->fileIndex()); + if (Token::Match(tok3, "%type% <")) { + //if (!Token::simpleMatch(tok3, (name + " <").c_str())) + //done = false; + used.push_back(_tokensBack); + } + + // link() newly tokens manually + if (tok3->str() == "{") { + braces.push(_tokensBack); + } else if (tok3->str() == "}") { + assert(braces.empty() == false); + Token::createMutualLinks(braces.top(), _tokensBack); + braces.pop(); + } else if (tok3->str() == "(") { + brackets.push(_tokensBack); + } else if (tok3->str() == "[") { + brackets2.push(_tokensBack); + } else if (tok3->str() == ")") { + assert(brackets.empty() == false); + Token::createMutualLinks(brackets.top(), _tokensBack); + brackets.pop(); + } else if (tok3->str() == "]") { + assert(brackets2.empty() == false); + Token::createMutualLinks(brackets2.top(), _tokensBack); + brackets2.pop(); + } + + } + + assert(braces.empty()); + assert(brackets.empty()); + } +} + void Tokenizer::simplifyTemplatesInstantiate(const Token *tok, std::list &used, std::set &expandedtemplates) @@ -3231,122 +3351,11 @@ void Tokenizer::simplifyTemplatesInstantiate(const Token *tok, } // New classname/funcname.. - const std::string name2(name + "<" + type2 + ">"); + const std::string newName(name + "<" + type2 + ">"); - if (expandedtemplates.find(name2) == expandedtemplates.end()) { - expandedtemplates.insert(name2); - // Copy template.. - int _indentlevel = 0; - int _parlevel = 0; - for (const Token *tok3 = _tokens; tok3; tok3 = tok3->next()) { - if (tok3->str() == "{") - ++_indentlevel; - else if (tok3->str() == "}") - --_indentlevel; - else if (tok3->str() == "(") - ++_parlevel; - else if (tok3->str() == ")") - --_parlevel; - - // Start of template.. - if (tok3 == tok) { - tok3 = tok3->next(); - } - - // member function implemented outside class definition - else if (_indentlevel == 0 && - _parlevel == 0 && - simplifyTemplatesInstantiateMatch(tok3, name, type.size(), ":: ~| %var% (")) { - addtoken(name2.c_str(), tok3->linenr(), tok3->fileIndex()); - while (tok3->str() != "::") - tok3 = tok3->next(); - } - - // not part of template.. go on to next token - else - continue; - - int indentlevel = 0; - std::stack braces; // holds "{" tokens - std::stack brackets; // holds "(" tokens - std::stack brackets2; // holds "[" tokens - - for (; tok3; tok3 = tok3->next()) { - if (tok3->str() == "{") - ++indentlevel; - - else if (tok3->str() == "}") { - if (indentlevel <= 1 && brackets.empty() && brackets2.empty()) { - // there is a bug if indentlevel is 0 - // the "}" token should only be added if indentlevel is 1 but I add it always intentionally - // if indentlevel ever becomes 0, cppcheck will write: - // ### Error: Invalid number of character { - addtoken("}", tok3->linenr(), tok3->fileIndex()); - Token::createMutualLinks(braces.top(), _tokensBack); - braces.pop(); - break; - } - --indentlevel; - } - - - if (tok3->isName()) { - // search for this token in the type vector - unsigned int itype = 0; - while (itype < type.size() && type[itype]->str() != tok3->str()) - ++itype; - - // replace type with given type.. - if (itype < type.size()) { - for (const Token *typetok = types2[itype]; - typetok && !Token::Match(typetok, "[,>]"); - typetok = typetok->next()) { - addtoken(typetok, tok3->linenr(), tok3->fileIndex()); - } - continue; - } - } - - // replace name.. - if (Token::Match(tok3, (name + " !!<").c_str())) { - addtoken(name2.c_str(), tok3->linenr(), tok3->fileIndex()); - continue; - } - - // copy - addtoken(tok3, tok3->linenr(), tok3->fileIndex()); - if (Token::Match(tok3, "%type% <")) { - //if (!Token::simpleMatch(tok3, (name + " <").c_str())) - //done = false; - used.push_back(_tokensBack); - } - - // link() newly tokens manually - if (tok3->str() == "{") { - braces.push(_tokensBack); - } else if (tok3->str() == "}") { - assert(braces.empty() == false); - Token::createMutualLinks(braces.top(), _tokensBack); - braces.pop(); - } else if (tok3->str() == "(") { - brackets.push(_tokensBack); - } else if (tok3->str() == "[") { - brackets2.push(_tokensBack); - } else if (tok3->str() == ")") { - assert(brackets.empty() == false); - Token::createMutualLinks(brackets.top(), _tokensBack); - brackets.pop(); - } else if (tok3->str() == "]") { - assert(brackets2.empty() == false); - Token::createMutualLinks(brackets2.top(), _tokensBack); - brackets2.pop(); - } - - } - - assert(braces.empty()); - assert(brackets.empty()); - } + if (expandedtemplates.find(newName) == expandedtemplates.end()) { + expandedtemplates.insert(newName); + simplifyTemplatesExpandTemplate(tok,name,type,newName,types2,used); } // Replace all these template usages.. @@ -3376,7 +3385,7 @@ void Tokenizer::simplifyTemplatesInstantiate(const Token *tok, // matching template usage => replace tokens.. // Foo < int > => Foo if (tok5 && tok5->str() == ">" && count + 1U == types2.size()) { - tok4->str(name2); + tok4->str(newName); for (Token *tok6 = tok4->next(); tok6 != tok5; tok6 = tok6->next()) { if (tok6->isName()) used.remove(tok6); diff --git a/lib/tokenize.h b/lib/tokenize.h index 9e68028fe..18c6675dd 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -489,6 +489,13 @@ public: std::list &used, std::set &expandedtemplates); + void simplifyTemplatesExpandTemplate(const Token *tok, + const std::string &name, + std::vector &type, + const std::string &newName, + std::vector &types2, + std::list &used); + /** * Match template declaration/instantiation * @param tok The ">" token e.g. before "class"