From 3256b7b2ef7073264af3197bdcd62f4f9fe92ea1 Mon Sep 17 00:00:00 2001 From: Przemyslaw Gorszkowski Date: Sun, 11 Aug 2013 22:10:26 +0200 Subject: [PATCH] C++: fix matching type with using from other namespace example code: struct S { int s; }; namespace std { template struct shared_ptr { T* operator->(); }; } namespace NS { using std::shared_ptr; } int main() { NS::shared_ptr p;// for this shared_ptr return 0; } Fixes: * find usages * follow symbol * highlighting * marking Task-number: QTCREATORBUG-7978 Change-Id: I28994c960b87ddd400e1d7b860fca6c6683bbb5a Reviewed-by: Erik Verbruggen --- src/libs/cplusplus/LookupContext.cpp | 9 +++- src/plugins/cpptools/cppchecksymbols.cpp | 5 ++- .../checksymbols/tst_checksymbols.cpp | 37 +++++++++++++++++ .../cplusplus/findusages/tst_findusages.cpp | 41 +++++++++++++++++++ 4 files changed, 89 insertions(+), 3 deletions(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 5f7b7db3128..d6a5ecb865a 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -246,12 +246,13 @@ QList LookupContext::lookupByUsing(const Name *name, Scope *scope) c { QList candidates; // if it is a nameId there can be a using declaration for it - if (name->isNameId()) { + if (name->isNameId() || name->isTemplateNameId()) { for (unsigned i = 0, count = scope->memberCount(); i < count; ++i) { if (UsingDeclaration *u = scope->memberAt(i)->asUsingDeclaration()) { if (const Name *usingDeclarationName = u->name()) { if (const QualifiedNameId *q = usingDeclarationName->asQualifiedNameId()) { - if (q->name() && q->name()->isEqualTo(name)) { + if (q->name() && q->identifier() && name->identifier() + && q->name()->identifier()->isEqualTo(name->identifier())) { candidates = bindings()->globalNamespace()->find(q); // if it is not a global scope(scope of scope is not equal 0) @@ -267,6 +268,10 @@ QList LookupContext::lookupByUsing(const Name *name, Scope *scope) c } } } + } else if (const QualifiedNameId *q = name->asQualifiedNameId()) { + ClassOrNamespace *base = lookupType(q->base(), scope); + if (base && base->symbols().size() > 0 && base->symbols().first()->asScope()) + return lookupByUsing(q->name(), base->symbols().first()->asScope()); } return candidates; } diff --git a/src/plugins/cpptools/cppchecksymbols.cpp b/src/plugins/cpptools/cppchecksymbols.cpp index a9cf95b66ee..8c7625e1e0b 100644 --- a/src/plugins/cpptools/cppchecksymbols.cpp +++ b/src/plugins/cpptools/cppchecksymbols.cpp @@ -852,7 +852,10 @@ bool CheckSymbols::visit(QualifiedNameAST *ast) addUse(ast->unqualified_name, CppHighlightingSupport::FunctionUse); } } else { - maybeAddTypeOrStatic(binding->find(ast->unqualified_name->name), ast->unqualified_name); + QList items = binding->find(ast->unqualified_name->name); + if (items.empty()) + items = _context.lookup(ast->name, enclosingScope()); + maybeAddTypeOrStatic(items, ast->unqualified_name); } if (TemplateIdAST *template_id = ast->unqualified_name->asTemplateId()) diff --git a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp index 75ae38c87de..0b00c25adf1 100644 --- a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp +++ b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp @@ -201,6 +201,7 @@ private slots: void test_alias_decl_QTCREATORBUG9386(); void test_completion_enum_inside_block_inside_function_QTCREATORBUG5456(); void test_completion_enum_inside_function_QTCREATORBUG5456(); + void test_completion_using_inside_different_namespace_QTCREATORBUG7978(); }; void tst_CheckSymbols::test_checksymbols_TypeUse() @@ -1821,5 +1822,41 @@ void tst_CheckSymbols::test_completion_enum_inside_function_QTCREATORBUG5456() TestData::check(source, expectedUses); } +void tst_CheckSymbols::test_completion_using_inside_different_namespace_QTCREATORBUG7978() +{ + const QByteArray source = + "struct S {};\n" + "namespace std\n" + "{\n" + " template struct shared_ptr{};\n" + "}\n" + "namespace NS\n" + "{\n" + " using std::shared_ptr;\n" + "}\n" + "void fun()\n" + "{\n" + " NS::shared_ptr p;\n" + "}\n" + ; + + const QList expectedUses = QList() + << Use(1, 8, 1, CppHighlightingSupport::TypeUse) + << Use(2, 11, 3, CppHighlightingSupport::TypeUse) + << Use(4, 24, 1, CppHighlightingSupport::TypeUse) + << Use(4, 34, 10, CppHighlightingSupport::TypeUse) + << Use(6, 11, 2, CppHighlightingSupport::TypeUse) + << Use(8, 11, 3, CppHighlightingSupport::TypeUse) + << Use(8, 16, 10, CppHighlightingSupport::TypeUse) + << Use(10, 6, 3, CppHighlightingSupport::FunctionUse) + << Use(12, 5, 2, CppHighlightingSupport::TypeUse) + << Use(12, 9, 10, CppHighlightingSupport::TypeUse) + << Use(12, 20, 1, CppHighlightingSupport::TypeUse) + << Use(12, 23, 1, CppHighlightingSupport::LocalUse) + ; + + TestData::check(source, expectedUses); +} + QTEST_APPLESS_MAIN(tst_CheckSymbols) #include "tst_checksymbols.moc" diff --git a/tests/auto/cplusplus/findusages/tst_findusages.cpp b/tests/auto/cplusplus/findusages/tst_findusages.cpp index 9ab9d41af84..afc8ba35bb2 100644 --- a/tests/auto/cplusplus/findusages/tst_findusages.cpp +++ b/tests/auto/cplusplus/findusages/tst_findusages.cpp @@ -108,6 +108,8 @@ private Q_SLOTS: void using_insideNamespace(); void using_insideFunction(); void templatedFunction_QTCREATORBUG9749(); + + void usingInDifferentNamespace_QTCREATORBUG7978(); }; void tst_FindUsages::dump(const QList &usages) const @@ -866,5 +868,44 @@ void tst_FindUsages::templatedFunction_QTCREATORBUG9749() QCOMPARE(findUsages.usages().size(), 2); } +void tst_FindUsages::usingInDifferentNamespace_QTCREATORBUG7978() +{ + const QByteArray src = "\n" + "struct S {};\n" + "namespace std\n" + "{\n" + " template struct shared_ptr{};\n" + "}\n" + "namespace NS\n" + "{\n" + " using std::shared_ptr;\n" + "}\n" + "void fun()\n" + "{\n" + " NS::shared_ptr p;\n" + "}\n" + ; + + Document::Ptr doc = Document::create("usingInDifferentNamespace_QTCREATORBUG7978"); + doc->setUtf8Source(src); + doc->parse(); + doc->check(); + + QVERIFY(doc->diagnosticMessages().isEmpty()); + QCOMPARE(doc->globalSymbolCount(), 4U); + + Snapshot snapshot; + snapshot.insert(doc); + + Namespace *ns = doc->globalSymbolAt(1)->asNamespace(); + QVERIFY(ns); + QCOMPARE(ns->memberCount(), 1U); + Template *templateClass = ns->memberAt(0)->asTemplate(); + + FindUsages findUsages(src, doc, snapshot); + findUsages(templateClass); + QCOMPARE(findUsages.usages().size(), 3); +} + QTEST_APPLESS_MAIN(tst_FindUsages) #include "tst_findusages.moc"