isVariableDeclaration() now detects template variables.
This commit is contained in:
parent
38c37ad2d8
commit
7918c4b804
|
@ -1167,72 +1167,9 @@ void SymbolDatabase::SpaceInfo::getVarList()
|
|||
|
||||
if (isVariableDeclaration(tok, vartok, typetok))
|
||||
{
|
||||
isClass = (!typetok->isStandardType() && typetok->next()->str() != "*");
|
||||
isClass = (!typetok->isStandardType() && vartok->previous()->str() != "*");
|
||||
tok = vartok->next();
|
||||
}
|
||||
// Container..
|
||||
else if (Token::Match(tok, ":: %type% :: %type% :: %type% <") ||
|
||||
Token::Match(tok, "%type% :: %type% :: %type% <") ||
|
||||
Token::Match(tok, ":: %type% :: %type% <") ||
|
||||
Token::Match(tok, "%type% :: %type% <") ||
|
||||
Token::Match(tok, ":: %type% <") ||
|
||||
Token::Match(tok, "%type% <"))
|
||||
{
|
||||
// got an unhandled template?
|
||||
if (tok->str() == "template")
|
||||
continue;
|
||||
|
||||
// find matching ">"
|
||||
int level = 0;
|
||||
const Token *tok1 = NULL;
|
||||
for (; tok; tok = tok->next())
|
||||
{
|
||||
if (tok->str() == "<")
|
||||
{
|
||||
if (level == 0)
|
||||
tok1 = tok->previous();
|
||||
level++;
|
||||
}
|
||||
else if (tok->str() == ">")
|
||||
{
|
||||
level--;
|
||||
if (level == 0)
|
||||
break;
|
||||
}
|
||||
else if (tok->str() == ">>")
|
||||
{
|
||||
level-=2;
|
||||
if (level <= 0)
|
||||
break;
|
||||
}
|
||||
else if (tok->str() == "(")
|
||||
tok = tok->link();
|
||||
|
||||
// don't crash on unhandled templates
|
||||
if (tok->next() == NULL)
|
||||
break;
|
||||
}
|
||||
if (tok && (Token::Match(tok, "> %var% ;") || Token::Match(tok, ">> %var% ;")))
|
||||
{
|
||||
isClass = true;
|
||||
vartok = tok->next();
|
||||
typetok = tok1;
|
||||
tok = vartok->next();
|
||||
}
|
||||
else if (tok && (Token::Match(tok, "> :: %type% %var% ;") || Token::Match(tok, ">> :: %type% %var% ;")))
|
||||
{
|
||||
isClass = true;
|
||||
vartok = tok->tokAt(3);
|
||||
typetok = vartok->previous();
|
||||
tok = vartok->next();
|
||||
}
|
||||
else if (tok && (Token::Match(tok, "> * %var% ;") || Token::Match(tok, ">> * %var% ;")))
|
||||
{
|
||||
vartok = tok->tokAt(2);
|
||||
tok = vartok->next();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If the vartok was set in the if-blocks above, create a entry for this variable..
|
||||
if (vartok && vartok->str() != "operator")
|
||||
|
@ -1295,17 +1232,39 @@ const Token* skipPointers(const Token* tok)
|
|||
|
||||
bool SymbolDatabase::SpaceInfo::isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const
|
||||
{
|
||||
tok = skipScopeIdentifiers(tok);
|
||||
if (Token::Match(tok, "%type%"))
|
||||
const Token* localTypeTok = skipScopeIdentifiers(tok);
|
||||
|
||||
if (Token::Match(localTypeTok, "%type% < "))
|
||||
{
|
||||
const Token* potentialTypetok = tok;
|
||||
|
||||
tok = skipPointers(tok->next());
|
||||
|
||||
if (isSimpleVariable(tok) || isArrayVariable(tok))
|
||||
const Token* closetok = NULL;
|
||||
bool found = findClosingBracket(localTypeTok->next(), closetok);
|
||||
if (found)
|
||||
{
|
||||
vartok = tok;
|
||||
typetok = potentialTypetok;
|
||||
if (Token::Match(closetok, "> %var% ;"))
|
||||
{
|
||||
vartok = closetok->next();
|
||||
typetok = localTypeTok;
|
||||
}
|
||||
else if (Token::Match(closetok, "> * %var% ;"))
|
||||
{
|
||||
vartok = closetok->tokAt(2);
|
||||
typetok = localTypeTok;
|
||||
}
|
||||
else if (Token::Match(closetok, "> :: %type% %var% ;"))
|
||||
{
|
||||
vartok = closetok->tokAt(3);
|
||||
typetok = closetok->tokAt(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Token::Match(localTypeTok, "%type%"))
|
||||
{
|
||||
const Token* localVarTok = skipPointers(localTypeTok->next());
|
||||
|
||||
if (isSimpleVariable(localVarTok) || isArrayVariable(localVarTok))
|
||||
{
|
||||
vartok = localVarTok;
|
||||
typetok = localTypeTok;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1322,6 +1281,33 @@ bool SymbolDatabase::SpaceInfo::isArrayVariable(const Token* tok) const
|
|||
return Token::Match(tok, "%var% [") && tok->next()->str() != "operator";
|
||||
}
|
||||
|
||||
bool SymbolDatabase::SpaceInfo::findClosingBracket(const Token* tok, const Token*& close) const
|
||||
{
|
||||
bool found = false;
|
||||
if (NULL != tok && tok->str() == "<")
|
||||
{
|
||||
unsigned int depth = 0;
|
||||
for (close = tok; (close != NULL) && (close->str() != ";"); close = close->next())
|
||||
{
|
||||
if (close->str() == "<")
|
||||
{
|
||||
++depth;
|
||||
}
|
||||
else if (close->str() == ">")
|
||||
{
|
||||
if (--depth == 0)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
const SymbolDatabase::SpaceInfo *SymbolDatabase::findVarType(const SpaceInfo *start, const Token *type) const
|
||||
|
|
|
@ -211,6 +211,7 @@ public:
|
|||
bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const;
|
||||
bool isSimpleVariable(const Token* tok) const;
|
||||
bool isArrayVariable(const Token* tok) const;
|
||||
bool findClosingBracket(const Token* tok, const Token*& close) const;
|
||||
};
|
||||
|
||||
/** @brief Information about all namespaces/classes/structrues */
|
||||
|
|
|
@ -35,11 +35,15 @@ private:
|
|||
const SymbolDatabase::SpaceInfo si;
|
||||
const Token* vartok;
|
||||
const Token* typetok;
|
||||
const Token* t;
|
||||
bool found;
|
||||
|
||||
void reset()
|
||||
{
|
||||
vartok = NULL;
|
||||
typetok = NULL;
|
||||
t = NULL;
|
||||
found = false;
|
||||
}
|
||||
|
||||
void run()
|
||||
|
@ -58,6 +62,16 @@ private:
|
|||
TEST_CASE(test_isVariableDeclarationIdentifiesDeclarationWithMultipleIndirection);
|
||||
TEST_CASE(test_isVariableDeclarationIdentifiesArray);
|
||||
TEST_CASE(test_isVariableDeclarationIdentifiesOfArrayPointers);
|
||||
TEST_CASE(isVariableDeclarationIdentifiesTemplatedPointerVariable);
|
||||
TEST_CASE(isVariableDeclarationIdentifiesTemplatedVariable);
|
||||
TEST_CASE(isVariableDeclarationIdentifiesTemplatedVariableIterator);
|
||||
TEST_CASE(isVariableDeclarationIdentifiesNestedTemplateVariable);
|
||||
TEST_CASE(isVariableDeclarationDoesNotIdentifyTemplateClass);
|
||||
TEST_CASE(canFindMatchingBracketsNeedsOpen);
|
||||
TEST_CASE(canFindMatchingBracketsInnerPair);
|
||||
TEST_CASE(canFindMatchingBracketsOuterPair);
|
||||
TEST_CASE(canFindMatchingBracketsWithTooManyClosing);
|
||||
TEST_CASE(canFindMatchingBracketsWithTooManyOpening);
|
||||
}
|
||||
|
||||
void test_isVariableDeclarationCanHandleNull()
|
||||
|
@ -198,6 +212,107 @@ private:
|
|||
ASSERT_EQUALS("a", vartok->str());
|
||||
ASSERT_EQUALS("A", typetok->str());
|
||||
}
|
||||
|
||||
void isVariableDeclarationIdentifiesTemplatedPointerVariable()
|
||||
{
|
||||
reset();
|
||||
givenACodeSampleToTokenize var("std::set<char>* chars;");
|
||||
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok);
|
||||
ASSERT_EQUALS(true, result);
|
||||
ASSERT_EQUALS("chars", vartok->str());
|
||||
ASSERT_EQUALS("set", typetok->str());
|
||||
}
|
||||
|
||||
void isVariableDeclarationIdentifiesTemplatedVariable()
|
||||
{
|
||||
reset();
|
||||
givenACodeSampleToTokenize var("std::vector<int> ints;");
|
||||
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok);
|
||||
ASSERT_EQUALS(true, result);
|
||||
ASSERT_EQUALS("ints", vartok->str());
|
||||
ASSERT_EQUALS("vector", typetok->str());
|
||||
}
|
||||
|
||||
void isVariableDeclarationIdentifiesTemplatedVariableIterator()
|
||||
{
|
||||
reset();
|
||||
givenACodeSampleToTokenize var("std::list<int>::const_iterator floats;");
|
||||
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok);
|
||||
ASSERT_EQUALS(true, result);
|
||||
ASSERT_EQUALS("floats", vartok->str());
|
||||
ASSERT_EQUALS("const_iterator", typetok->str());
|
||||
}
|
||||
|
||||
void isVariableDeclarationIdentifiesNestedTemplateVariable()
|
||||
{
|
||||
reset();
|
||||
givenACodeSampleToTokenize var("std::deque<std::set<int> > intsets;");
|
||||
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok);
|
||||
ASSERT_EQUALS(true, result);
|
||||
ASSERT_EQUALS("intsets", vartok->str());
|
||||
ASSERT_EQUALS("deque", typetok->str());
|
||||
}
|
||||
|
||||
void isVariableDeclarationDoesNotIdentifyTemplateClass()
|
||||
{
|
||||
reset();
|
||||
givenACodeSampleToTokenize var("template <class T> class SomeClass{};");
|
||||
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok);
|
||||
ASSERT_EQUALS(false, result);
|
||||
}
|
||||
|
||||
void canFindMatchingBracketsNeedsOpen()
|
||||
{
|
||||
reset();
|
||||
givenACodeSampleToTokenize var("std::deque<std::set<int> > intsets;");
|
||||
|
||||
found = si.findClosingBracket(var.tokens(), t);
|
||||
ASSERT(! found);
|
||||
ASSERT(! t);
|
||||
}
|
||||
|
||||
void canFindMatchingBracketsInnerPair()
|
||||
{
|
||||
reset();
|
||||
givenACodeSampleToTokenize var("std::deque<std::set<int> > intsets;");
|
||||
|
||||
found = si.findClosingBracket(var.tokens()->tokAt(7), t);
|
||||
ASSERT(found);
|
||||
ASSERT_EQUALS(">", t->str());
|
||||
ASSERT_EQUALS(var.tokens()->strAt(9), t->str());
|
||||
}
|
||||
|
||||
void canFindMatchingBracketsOuterPair()
|
||||
{
|
||||
reset();
|
||||
givenACodeSampleToTokenize var("std::deque<std::set<int> > intsets;");
|
||||
|
||||
found = si.findClosingBracket(var.tokens()->tokAt(3), t);
|
||||
ASSERT(found);
|
||||
ASSERT_EQUALS(">", t->str());
|
||||
ASSERT_EQUALS(var.tokens()->strAt(10), t->str());
|
||||
|
||||
}
|
||||
|
||||
void canFindMatchingBracketsWithTooManyClosing()
|
||||
{
|
||||
reset();
|
||||
givenACodeSampleToTokenize var("X< 1>2 > x1;\n");
|
||||
|
||||
found = si.findClosingBracket(var.tokens()->tokAt(1), t);
|
||||
ASSERT(found);
|
||||
ASSERT_EQUALS(">", t->str());
|
||||
ASSERT_EQUALS(var.tokens()->strAt(3), t->str());
|
||||
}
|
||||
|
||||
void canFindMatchingBracketsWithTooManyOpening()
|
||||
{
|
||||
reset();
|
||||
givenACodeSampleToTokenize var("X < (2 < 1) > x1;\n");
|
||||
|
||||
found = si.findClosingBracket(var.tokens()->tokAt(1), t);
|
||||
ASSERT(!found);
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestSymbolDatabase)
|
||||
|
|
Loading…
Reference in New Issue