Commit 3256b7b2 authored by Przemyslaw Gorszkowski's avatar Przemyslaw Gorszkowski Committed by Erik Verbruggen
Browse files

C++: fix matching type with using from other namespace



example code:
struct S { int s; };

namespace std
{
    template <typename T>
    struct shared_ptr
    {
        T* operator->();
    };
}

namespace NS
{
    using std::shared_ptr;
}

int main()
{
    NS::shared_ptr<S> p;// for this shared_ptr
    return 0;
}

Fixes:
* find usages
* follow symbol
* highlighting
* marking

Task-number: QTCREATORBUG-7978
Change-Id: I28994c960b87ddd400e1d7b860fca6c6683bbb5a
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent 9de44134
......@@ -246,12 +246,13 @@ QList<LookupItem> LookupContext::lookupByUsing(const Name *name, Scope *scope) c
{
QList<LookupItem> 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<LookupItem> 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;
}
......
......@@ -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<LookupItem> 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())
......
......@@ -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 <typename T> struct shared_ptr{};\n"
"}\n"
"namespace NS\n"
"{\n"
" using std::shared_ptr;\n"
"}\n"
"void fun()\n"
"{\n"
" NS::shared_ptr<S> p;\n"
"}\n"
;
const QList<Use> expectedUses = QList<Use>()
<< 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"
......@@ -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<Usage> &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 <typename T> struct shared_ptr{};\n"
"}\n"
"namespace NS\n"
"{\n"
" using std::shared_ptr;\n"
"}\n"
"void fun()\n"
"{\n"
" NS::shared_ptr<S> 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"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment