diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 3df90dc93..f7e37ef8f 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1156,7 +1156,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s bool isClassVar = startTok == endTok && !startTok->isStandardType(); - argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, false, false, isConstVar, isClassVar, argType, scope)); + argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, false, false, isConstVar, isClassVar, argType, scope, false)); if (tok->str() == ")") break; @@ -1418,7 +1418,9 @@ void Scope::getVariableList() tok = tok->next(); } - if (isVariableDeclaration(tok, vartok, typetok)) + bool isArray = false; + + if (isVariableDeclaration(tok, vartok, typetok, isArray)) { isClass = (!typetok->isStandardType() && vartok->previous()->str() != "*"); tok = vartok->next(); @@ -1450,7 +1452,7 @@ void Scope::getVariableList() if (typetok) scope = check->findVariableType(this, typetok); - addVariable(vartok, typestart, vartok->previous(), varaccess, isMutable, isStatic, isConst, isClass, scope, this); + addVariable(vartok, typestart, vartok->previous(), varaccess, isMutable, isStatic, isConst, isClass, scope, this, isArray); } } } @@ -1483,7 +1485,7 @@ const Token* skipPointers(const Token* tok) return ret; } -bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const +bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray) const { const Token* localTypeTok = skipScopeIdentifiers(tok); const Token* localVarTok = NULL; @@ -1508,10 +1510,17 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const localVarTok = skipPointers(localTypeTok->next()); } - if (isSimpleVariable(localVarTok) || isArrayVariable(localVarTok)) + if (isSimpleVariable(localVarTok)) { vartok = localVarTok; typetok = localTypeTok; + isArray = false; + } + else if (isArrayVariable(localVarTok)) + { + vartok = localVarTok; + typetok = localTypeTok; + isArray = true; } return NULL != vartok; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index e55d018de..3e11805b3 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -49,7 +49,8 @@ class Variable fIsMutable = (1 << 0), /** @brief mutable variable */ fIsStatic = (1 << 1), /** @brief static variable */ fIsConst = (1 << 2), /** @brief const variable */ - fIsClass = (1 << 3) /** @brief user defined type */ + fIsClass = (1 << 3), /** @brief user defined type */ + fIsArray = (1 << 4) /** @brief array variable */ }; /** @@ -76,7 +77,7 @@ public: Variable(const Token *name_, const Token *start_, const Token *end_, std::size_t index_, AccessControl access_, bool mutable_, bool static_, bool const_, bool class_, const Scope *type_, - const Scope *scope_) + const Scope *scope_, bool array_) : _name(name_), _start(start_), _end(end_), @@ -90,6 +91,7 @@ public: setFlag(fIsStatic, static_); setFlag(fIsConst, const_); setFlag(fIsClass, class_); + setFlag(fIsArray, array_); } /** @@ -255,6 +257,15 @@ public: return getFlag(fIsClass); } + /** + * Is variable an array. + * @return true if array, false if not + */ + bool isArray() const + { + return getFlag(fIsArray); + } + /** * Get Scope pointer of known type. * @return pointer to type if known, NULL if not known @@ -417,11 +428,11 @@ public: void addVariable(const Token *token_, const Token *start_, const Token *end_, AccessControl access_, bool mutable_, bool static_, bool const_, bool class_, const Scope *type_, - const Scope *scope_) + const Scope *scope_, bool array_) { varlist.push_back(Variable(token_, start_, end_, varlist.size(), access_, mutable_, static_, const_, class_, - type_, scope_)); + type_, scope_, array_)); } /** @brief initialize varlist */ @@ -447,9 +458,10 @@ private: * @param tok pointer to token to check * @param vartok populated with pointer to the variable token, if found * @param typetok populated with pointer to the type token, if found + * @param isArray reference to variable to set if array is found * @return true if tok points to a variable declaration, false otherwise */ - bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const; + bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray) const; bool isSimpleVariable(const Token* tok) const; bool isArrayVariable(const Token* tok) const; bool findClosingBracket(const Token* tok, const Token*& close) const; diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index d3ba32467..241929c74 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -38,6 +38,7 @@ public: ,typetok(NULL) ,t(NULL) ,found(false) + ,isArray(false) {} private: @@ -46,6 +47,7 @@ private: const Token* typetok; const Token* t; bool found; + bool isArray; void reset() { @@ -53,6 +55,7 @@ private: typetok = NULL; t = NULL; found = false; + isArray = false; } void run() @@ -102,208 +105,229 @@ private: void test_isVariableDeclarationCanHandleNull() { reset(); - bool result = si.isVariableDeclaration(NULL, vartok, typetok); + bool result = si.isVariableDeclaration(NULL, vartok, typetok, isArray); ASSERT_EQUALS(false, result); ASSERT(NULL == vartok); ASSERT(NULL == typetok); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesSimpleDeclaration() { reset(); givenACodeSampleToTokenize simpleDeclaration("int x;"); - bool result = si.isVariableDeclaration(simpleDeclaration.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(simpleDeclaration.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("x", vartok->str()); ASSERT_EQUALS("int", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesScopedDeclaration() { reset(); givenACodeSampleToTokenize ScopedDeclaration("::int x;"); - bool result = si.isVariableDeclaration(ScopedDeclaration.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(ScopedDeclaration.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("x", vartok->str()); ASSERT_EQUALS("int", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesStdDeclaration() { reset(); givenACodeSampleToTokenize StdDeclaration("std::string x;"); - bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("x", vartok->str()); ASSERT_EQUALS("string", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesScopedStdDeclaration() { reset(); givenACodeSampleToTokenize StdDeclaration("::std::string x;"); - bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("x", vartok->str()); ASSERT_EQUALS("string", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesManyScopes() { reset(); givenACodeSampleToTokenize manyScopes("AA::BB::CC::DD::EE x;"); - bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("x", vartok->str()); ASSERT_EQUALS("EE", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesPointers() { reset(); givenACodeSampleToTokenize pointer("int* p;"); - bool result = si.isVariableDeclaration(pointer.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(pointer.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("p", vartok->str()); ASSERT_EQUALS("int", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationDoesNotIdentifyConstness() { reset(); givenACodeSampleToTokenize constness("const int* cp;"); - bool result = si.isVariableDeclaration(constness.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(constness.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(false, result); ASSERT(NULL == vartok); ASSERT(NULL == typetok); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesFirstOfManyVariables() { reset(); givenACodeSampleToTokenize multipleDeclaration("int first, second;"); - bool result = si.isVariableDeclaration(multipleDeclaration.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(multipleDeclaration.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("first", vartok->str()); ASSERT_EQUALS("int", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesScopedPointerDeclaration() { reset(); givenACodeSampleToTokenize manyScopes("AA::BB::CC::DD::EE* p;"); - bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("p", vartok->str()); ASSERT_EQUALS("EE", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesDeclarationWithIndirection() { reset(); givenACodeSampleToTokenize pointerToPointer("int** pp;"); - bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("pp", vartok->str()); ASSERT_EQUALS("int", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesDeclarationWithMultipleIndirection() { reset(); givenACodeSampleToTokenize pointerToPointer("int***** p;"); - bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("p", vartok->str()); ASSERT_EQUALS("int", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesArray() { reset(); givenACodeSampleToTokenize array("::std::string v[3];"); - bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("v", vartok->str()); ASSERT_EQUALS("string", typetok->str()); + ASSERT(true == isArray); } void test_isVariableDeclarationIdentifiesOfArrayPointers() { reset(); givenACodeSampleToTokenize array("A *a[5];"); - bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("a", vartok->str()); ASSERT_EQUALS("A", typetok->str()); + ASSERT(true == isArray); } void isVariableDeclarationIdentifiesTemplatedPointerVariable() { reset(); givenACodeSampleToTokenize var("std::set* chars;"); - bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("chars", vartok->str()); ASSERT_EQUALS("set", typetok->str()); + ASSERT(false == isArray); } void isVariableDeclarationIdentifiesTemplatedPointerToPointerVariable() { reset(); givenACodeSampleToTokenize var("std::deque*** ints;"); - bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("ints", vartok->str()); ASSERT_EQUALS("deque", typetok->str()); + ASSERT(false == isArray); } void isVariableDeclarationIdentifiesTemplatedArrayVariable() { reset(); givenACodeSampleToTokenize var("std::deque ints[3];"); - bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("ints", vartok->str()); ASSERT_EQUALS("deque", typetok->str()); + ASSERT(true == isArray); } void isVariableDeclarationIdentifiesTemplatedVariable() { reset(); givenACodeSampleToTokenize var("std::vector ints;"); - bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("ints", vartok->str()); ASSERT_EQUALS("vector", typetok->str()); + ASSERT(false == isArray); } void isVariableDeclarationIdentifiesTemplatedVariableIterator() { reset(); givenACodeSampleToTokenize var("std::list::const_iterator floats;"); - bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("floats", vartok->str()); ASSERT_EQUALS("const_iterator", typetok->str()); + ASSERT(false == isArray); } void isVariableDeclarationIdentifiesNestedTemplateVariable() { reset(); givenACodeSampleToTokenize var("std::deque > intsets;"); - bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("intsets", vartok->str()); ASSERT_EQUALS("deque", typetok->str()); + ASSERT(false == isArray); } void isVariableDeclarationDoesNotIdentifyTemplateClass() { reset(); givenACodeSampleToTokenize var("template class SomeClass{};"); - bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(false, result); + ASSERT(false == isArray); } void canFindMatchingBracketsNeedsOpen()