diff options
-rw-r--r-- | src/libs/cplusplus/LookupContext.cpp | 30 | ||||
-rw-r--r-- | src/plugins/cpptools/cppchecksymbols.cpp | 14 | ||||
-rw-r--r-- | src/plugins/cpptools/cppchecksymbols.h | 2 | ||||
-rw-r--r-- | tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp | 110 |
4 files changed, 150 insertions, 6 deletions
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 12ee4933c3..0834067144 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -335,8 +335,14 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const if (name->identifier() != 0 && scope->isBlock()) { bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ 0, /*binding=*/ 0); - if (! candidates.isEmpty()) - break; // it's a local. + if (! candidates.isEmpty()) { + // it's a local. + //for qualified it can be outside of the local scope + if (name->isQualifiedNameId()) + continue; + else + break; + } for (unsigned i = 0; i < scope->memberCount(); ++i) { if (UsingNamespaceDirective *u = scope->memberAt(i)->asUsingNamespaceDirective()) { @@ -352,8 +358,14 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const } else if (Function *fun = scope->asFunction()) { bindings()->lookupInScope(name, fun, &candidates, /*templateId = */ 0, /*binding=*/ 0); - if (! candidates.isEmpty()) - break; // it's an argument or a template parameter. + if (! candidates.isEmpty()) { + // it's an argument or a template parameter. + //for qualified it can be outside of the local scope + if (name->isQualifiedNameId()) + continue; + else + break; + } if (fun->name() && fun->name()->isQualifiedNameId()) { if (ClassOrNamespace *binding = bindings()->lookupType(fun)) { @@ -379,8 +391,14 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const } else if (Template *templ = scope->asTemplate()) { bindings()->lookupInScope(name, templ, &candidates, /*templateId = */ 0, /*binding=*/ 0); - if (! candidates.isEmpty()) - return candidates; // it's a template parameter. + if (! candidates.isEmpty()) { + // it's a template parameter. + //for qualified it can be outside of the local scope + if (name->isQualifiedNameId()) + continue; + else + break; + } } else if (scope->asNamespace() || scope->asClass() diff --git a/src/plugins/cpptools/cppchecksymbols.cpp b/src/plugins/cpptools/cppchecksymbols.cpp index fbf2766606..6ac5843c11 100644 --- a/src/plugins/cpptools/cppchecksymbols.cpp +++ b/src/plugins/cpptools/cppchecksymbols.cpp @@ -1240,6 +1240,7 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST { unsigned startToken = ast->firstToken(); bool isDestructor = false; + bool isConstructor = false; if (DestructorNameAST *dtor = ast->asDestructorName()) { isDestructor = true; if (dtor->unqualified_name) @@ -1264,6 +1265,8 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST if (isDestructor != c->name()->isDestructorNameId()) continue; + isConstructor = isConstructorDeclaration(c); + Function *funTy = c->type()->asFunctionType(); if (! funTy) { //Try to find a template function @@ -1296,7 +1299,9 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST } if (matchType != Match_None) { + // decide how constructor and destructor should be highlighted if (highlightCtorDtorAsType + && (isConstructor || isDestructor) && maybeType(ast->name) && kind == SemanticInfo::FunctionUse) { return false; @@ -1399,3 +1404,12 @@ void CheckSymbols::flush() _usages.clear(); _usages.reserve(cap); } + +bool CheckSymbols::isConstructorDeclaration(Symbol *declaration) +{ + Class *clazz = declaration->enclosingClass(); + if (clazz && clazz->name()) + return declaration->name()->isEqualTo(clazz->name()); + + return false; +} diff --git a/src/plugins/cpptools/cppchecksymbols.h b/src/plugins/cpptools/cppchecksymbols.h index 2b69e00081..51c032bb9c 100644 --- a/src/plugins/cpptools/cppchecksymbols.h +++ b/src/plugins/cpptools/cppchecksymbols.h @@ -165,6 +165,8 @@ protected: void flush(); private: + bool isConstructorDeclaration(Symbol *declaration); + Document::Ptr _doc; LookupContext _context; TypeOfExpression typeOfExpression; diff --git a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp index 432fd2dad4..cbc66e2628 100644 --- a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp +++ b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp @@ -176,6 +176,10 @@ private slots: void test_checksymbols_StaticUse(); void test_checksymbols_VariableHasTheSameNameAsEnumUse(); void test_checksymbols_NestedClassOfEnclosingTemplateUse(); + void test_checksymbols_8902_staticFunctionHighlightingAsMember_localVariable(); + void test_checksymbols_8902_staticFunctionHighlightingAsMember_functionArgument(); + void test_checksymbols_8902_staticFunctionHighlightingAsMember_templateParameter(); + void test_checksymbols_8902_staticFunctionHighlightingAsMember_struct(); void test_checksymbols_QTCREATORBUG8890_danglingPointer(); void test_checksymbols_QTCREATORBUG8974_danglingPointer(); @@ -446,6 +450,112 @@ void tst_CheckSymbols::test_checksymbols_NestedClassOfEnclosingTemplateUse() TestData::check(source, expectedUses); } +void tst_CheckSymbols::test_checksymbols_8902_staticFunctionHighlightingAsMember_localVariable() +{ + const QByteArray source = + "struct Foo\n" + "{\n" + " static int foo();\n" + "};\n" + "\n" + "void bar()\n" + "{\n" + " int foo = Foo::foo();\n" + "}\n" + ; + + const QList<Use> expectedUses = QList<Use>() + << Use(1, 8, 3, SemanticInfo::TypeUse) + << Use(3, 16, 3, SemanticInfo::FunctionUse) + << Use(6, 6, 3, SemanticInfo::FunctionUse) + << Use(8, 9, 3, SemanticInfo::LocalUse) + << Use(8, 15, 3, SemanticInfo::TypeUse) + << Use(8, 20, 3, SemanticInfo::FunctionUse) + ; + + TestData::check(source, expectedUses); +} + +void tst_CheckSymbols::test_checksymbols_8902_staticFunctionHighlightingAsMember_functionArgument() +{ + const QByteArray source = + "struct Foo\n" + "{\n" + " static int foo();\n" + "};\n" + "\n" + "void bar(int foo)\n" + "{\n" + " Foo::foo();\n" + "}\n" + ; + + const QList<Use> expectedUses = QList<Use>() + << Use(1, 8, 3, SemanticInfo::TypeUse) + << Use(3, 16, 3, SemanticInfo::FunctionUse) + << Use(6, 6, 3, SemanticInfo::FunctionUse) + << Use(6, 14, 3, SemanticInfo::LocalUse) + << Use(8, 5, 3, SemanticInfo::TypeUse) + << Use(8, 10, 3, SemanticInfo::FunctionUse) + ; + + TestData::check(source, expectedUses); +} + +void tst_CheckSymbols::test_checksymbols_8902_staticFunctionHighlightingAsMember_templateParameter() +{ + const QByteArray source = + "struct Foo\n" + "{\n" + " static int foo();\n" + "};\n" + "\n" + "template <class foo>\n" + "void bar()\n" + "{\n" + " Foo::foo();\n" + "}\n" + ; + + const QList<Use> expectedUses = QList<Use>() + << Use(1, 8, 3, SemanticInfo::TypeUse) + << Use(3, 16, 3, SemanticInfo::FunctionUse) + << Use(6, 17, 3, SemanticInfo::TypeUse) + << Use(7, 6, 3, SemanticInfo::FunctionUse) + << Use(9, 5, 3, SemanticInfo::TypeUse) + << Use(9, 10, 3, SemanticInfo::FunctionUse) + ; + + TestData::check(source, expectedUses); +} + +void tst_CheckSymbols::test_checksymbols_8902_staticFunctionHighlightingAsMember_struct() +{ + const QByteArray source = + "struct Foo\n" + "{\n" + " static int foo();\n" + "};\n" + "\n" + "struct foo {};\n" + "void bar()\n" + "{\n" + " Foo::foo();\n" + "}\n" + ; + + const QList<Use> expectedUses = QList<Use>() + << Use(1, 8, 3, SemanticInfo::TypeUse) + << Use(3, 16, 3, SemanticInfo::FunctionUse) + << Use(6, 8, 3, SemanticInfo::TypeUse) + << Use(7, 6, 3, SemanticInfo::FunctionUse) + << Use(9, 5, 3, SemanticInfo::TypeUse) + << Use(9, 10, 3, SemanticInfo::FunctionUse) + ; + + TestData::check(source, expectedUses); +} + void tst_CheckSymbols::test_checksymbols_QTCREATORBUG8890_danglingPointer() { const QByteArray source = |