C++: fix 'using' in separate block of scope

Task-number: QTCREATORBUG-12357
Change-Id: I7397b0e66783d3249daa5a8ee422bfd5f5bc7bea
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent 6a700ff0
......@@ -242,26 +242,32 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
return n;
}
QList<LookupItem> LookupContext::lookupByUsing(const Name *name, Scope *scope) const
QList<LookupItem> LookupContext::lookupByUsing(const Name *name,
ClassOrNamespace *bindingScope) const
{
QList<LookupItem> candidates;
// if it is a nameId there can be a using declaration for it
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->identifier() && name->identifier()
&& q->name()->identifier()->match(name->identifier())) {
candidates = bindings()->globalNamespace()->find(q);
// if it is not a global scope(scope of scope is not equal 0)
// then add current using declaration as a candidate
if (scope->enclosingScope()) {
LookupItem item;
item.setDeclaration(u);
item.setScope(scope);
candidates.append(item);
foreach (Symbol *s, bindingScope->symbols()) {
if (Scope *scope = s->asScope()) {
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->identifier() && name->identifier()
&& q->name()->identifier()->match(name->identifier())) {
candidates = bindings()->globalNamespace()->find(q);
// if it is not a global scope(scope of scope is not equal 0)
// then add current using declaration as a candidate
if (scope->enclosingScope()) {
LookupItem item;
item.setDeclaration(u);
item.setScope(scope);
candidates.append(item);
}
}
}
}
}
......@@ -269,9 +275,15 @@ 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());
foreach (Symbol *s, bindingScope->symbols()) {
if (Scope *scope = s->asScope()) {
ClassOrNamespace *base = lookupType(q->base(), scope);
if (base)
candidates = lookupByUsing(q->name(), base);
if (!candidates.isEmpty())
return candidates;
}
}
}
return candidates;
}
......@@ -400,13 +412,13 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
}
}
candidates = lookupByUsing(name, scope);
if (! candidates.isEmpty())
return candidates;
if (ClassOrNamespace *bindingScope = bindings()->lookupType(scope)) {
if (ClassOrNamespace *bindingBlock = bindingScope->findBlock(scope->asBlock())) {
candidates = lookupByUsing(name, bindingBlock);
if (! candidates.isEmpty())
return candidates;
if (ClassOrNamespace *binding = bindings()->lookupType(scope)) {
if (ClassOrNamespace *block = binding->findBlock(scope->asBlock())) {
candidates = block->find(name);
candidates = bindingBlock->find(name);
if (! candidates.isEmpty())
return candidates;
......@@ -461,15 +473,17 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
} else if (scope->asNamespace()
|| scope->asClass()
|| (scope->asEnum() && scope->asEnum()->isScoped())) {
if (ClassOrNamespace *binding = bindings()->lookupType(scope))
candidates = binding->find(name);
if (! candidates.isEmpty())
return candidates;
if (ClassOrNamespace *bindingScope = bindings()->lookupType(scope)) {
candidates = bindingScope->find(name);
candidates = lookupByUsing(name, scope);
if (! candidates.isEmpty())
return candidates;
if (! candidates.isEmpty())
return candidates;
candidates = lookupByUsing(name, bindingScope);
if (!candidates.isEmpty())
return candidates;
}
// the scope can be defined inside a block, try to find it
if (Block *block = scope->enclosingBlock()) {
......
......@@ -328,7 +328,7 @@ public:
}
private:
QList<LookupItem> lookupByUsing(const Name *name, Scope *scope) const;
QList<LookupItem> lookupByUsing(const Name *name, ClassOrNamespace *bindingScope) const;
// The current expression.
Document::Ptr _expressionDocument;
......
......@@ -1596,6 +1596,51 @@ void tst_CheckSymbols::test_checksymbols_data()
<< Use(12, 20, 1, Highlighting::TypeUse)
<< Use(12, 23, 1, Highlighting::LocalUse));
QTest::newRow("using_inside_different_block_of_scope_unnamed_namespace_QTCREATORBUG12357")
<< _("namespace \n"
"{\n"
" namespace Ns { struct Foo {}; }\n"
" using Ns::Foo;\n"
"}\n"
"void fun()\n"
"{\n"
" Foo foo;\n"
"}\n")
<< (QList<Use>()
<< Use(3, 15, 2, CppHighlightingSupport::TypeUse)
<< Use(3, 27, 3, CppHighlightingSupport::TypeUse)
<< Use(4, 11, 2, CppHighlightingSupport::TypeUse)
<< Use(4, 15, 3, CppHighlightingSupport::TypeUse)
<< Use(6, 6, 3, CppHighlightingSupport::FunctionUse)
<< Use(8, 5, 3, CppHighlightingSupport::TypeUse)
<< Use(8, 9, 3, CppHighlightingSupport::LocalUse)
);
QTest::newRow("using_inside_different_block_of_scope_named_namespace_QTCREATORBUG12357")
<< _("namespace NS1\n"
"{\n"
" namespace Ns { struct Foo {}; }\n"
" using Ns::Foo;\n"
"}\n"
"namespace NS1\n"
"{\n"
" void fun()\n"
" {\n"
" Foo foo;\n"
" }\n"
"}\n"
)
<< (QList<Use>()
<< Use(1, 11, 3, CppHighlightingSupport::TypeUse)
<< Use(3, 15, 2, CppHighlightingSupport::TypeUse)
<< Use(3, 27, 3, CppHighlightingSupport::TypeUse)
<< Use(4, 11, 2, CppHighlightingSupport::TypeUse)
<< Use(4, 15, 3, CppHighlightingSupport::TypeUse)
<< Use(6, 11, 3, CppHighlightingSupport::TypeUse)
<< Use(8, 10, 3, CppHighlightingSupport::FunctionUse)
<< Use(10, 13, 3, CppHighlightingSupport::LocalUse)
);
QTest::newRow("using_inside_different_namespace_QTCREATORBUG7978")
<< _("class My" TEST_UNICODE_IDENTIFIER "Type { int " TEST_UNICODE_IDENTIFIER "Member; };\n"
"void f(My" TEST_UNICODE_IDENTIFIER "Type var" TEST_UNICODE_IDENTIFIER ")\n"
......
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