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))
|
if (isVariableDeclaration(tok, vartok, typetok))
|
||||||
{
|
{
|
||||||
isClass = (!typetok->isStandardType() && typetok->next()->str() != "*");
|
isClass = (!typetok->isStandardType() && vartok->previous()->str() != "*");
|
||||||
tok = vartok->next();
|
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 the vartok was set in the if-blocks above, create a entry for this variable..
|
||||||
if (vartok && vartok->str() != "operator")
|
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
|
bool SymbolDatabase::SpaceInfo::isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const
|
||||||
{
|
{
|
||||||
tok = skipScopeIdentifiers(tok);
|
const Token* localTypeTok = skipScopeIdentifiers(tok);
|
||||||
if (Token::Match(tok, "%type%"))
|
|
||||||
|
if (Token::Match(localTypeTok, "%type% < "))
|
||||||
{
|
{
|
||||||
const Token* potentialTypetok = tok;
|
const Token* closetok = NULL;
|
||||||
|
bool found = findClosingBracket(localTypeTok->next(), closetok);
|
||||||
tok = skipPointers(tok->next());
|
if (found)
|
||||||
|
|
||||||
if (isSimpleVariable(tok) || isArrayVariable(tok))
|
|
||||||
{
|
{
|
||||||
vartok = tok;
|
if (Token::Match(closetok, "> %var% ;"))
|
||||||
typetok = potentialTypetok;
|
{
|
||||||
|
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";
|
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
|
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 isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const;
|
||||||
bool isSimpleVariable(const Token* tok) const;
|
bool isSimpleVariable(const Token* tok) const;
|
||||||
bool isArrayVariable(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 */
|
/** @brief Information about all namespaces/classes/structrues */
|
||||||
|
|
|
@ -35,11 +35,15 @@ private:
|
||||||
const SymbolDatabase::SpaceInfo si;
|
const SymbolDatabase::SpaceInfo si;
|
||||||
const Token* vartok;
|
const Token* vartok;
|
||||||
const Token* typetok;
|
const Token* typetok;
|
||||||
|
const Token* t;
|
||||||
|
bool found;
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
vartok = NULL;
|
vartok = NULL;
|
||||||
typetok = NULL;
|
typetok = NULL;
|
||||||
|
t = NULL;
|
||||||
|
found = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
|
@ -58,6 +62,16 @@ private:
|
||||||
TEST_CASE(test_isVariableDeclarationIdentifiesDeclarationWithMultipleIndirection);
|
TEST_CASE(test_isVariableDeclarationIdentifiesDeclarationWithMultipleIndirection);
|
||||||
TEST_CASE(test_isVariableDeclarationIdentifiesArray);
|
TEST_CASE(test_isVariableDeclarationIdentifiesArray);
|
||||||
TEST_CASE(test_isVariableDeclarationIdentifiesOfArrayPointers);
|
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()
|
void test_isVariableDeclarationCanHandleNull()
|
||||||
|
@ -198,6 +212,107 @@ private:
|
||||||
ASSERT_EQUALS("a", vartok->str());
|
ASSERT_EQUALS("a", vartok->str());
|
||||||
ASSERT_EQUALS("A", typetok->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)
|
REGISTER_TEST(TestSymbolDatabase)
|
||||||
|
|
Loading…
Reference in New Issue