forked from qt-creator/qt-creator
C++: fix 'using' in separate block of scope
Task-number: QTCREATORBUG-12357 Change-Id: I7397b0e66783d3249daa5a8ee422bfd5f5bc7bea Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
@@ -242,15 +242,19 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
|
|||||||
return n;
|
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;
|
QList<LookupItem> candidates;
|
||||||
// if it is a nameId there can be a using declaration for it
|
// if it is a nameId there can be a using declaration for it
|
||||||
if (name->isNameId() || name->isTemplateNameId()) {
|
if (name->isNameId() || name->isTemplateNameId()) {
|
||||||
|
foreach (Symbol *s, bindingScope->symbols()) {
|
||||||
|
if (Scope *scope = s->asScope()) {
|
||||||
for (unsigned i = 0, count = scope->memberCount(); i < count; ++i) {
|
for (unsigned i = 0, count = scope->memberCount(); i < count; ++i) {
|
||||||
if (UsingDeclaration *u = scope->memberAt(i)->asUsingDeclaration()) {
|
if (UsingDeclaration *u = scope->memberAt(i)->asUsingDeclaration()) {
|
||||||
if (const Name *usingDeclarationName = u->name()) {
|
if (const Name *usingDeclarationName = u->name()) {
|
||||||
if (const QualifiedNameId *q = usingDeclarationName->asQualifiedNameId()) {
|
if (const QualifiedNameId *q
|
||||||
|
= usingDeclarationName->asQualifiedNameId()) {
|
||||||
if (q->name() && q->identifier() && name->identifier()
|
if (q->name() && q->identifier() && name->identifier()
|
||||||
&& q->name()->identifier()->match(name->identifier())) {
|
&& q->name()->identifier()->match(name->identifier())) {
|
||||||
candidates = bindings()->globalNamespace()->find(q);
|
candidates = bindings()->globalNamespace()->find(q);
|
||||||
@@ -268,10 +272,18 @@ QList<LookupItem> LookupContext::lookupByUsing(const Name *name, Scope *scope) c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
|
} else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
|
||||||
|
foreach (Symbol *s, bindingScope->symbols()) {
|
||||||
|
if (Scope *scope = s->asScope()) {
|
||||||
ClassOrNamespace *base = lookupType(q->base(), scope);
|
ClassOrNamespace *base = lookupType(q->base(), scope);
|
||||||
if (base && base->symbols().size() > 0 && base->symbols().first()->asScope())
|
if (base)
|
||||||
return lookupByUsing(q->name(), base->symbols().first()->asScope());
|
candidates = lookupByUsing(q->name(), base);
|
||||||
|
if (!candidates.isEmpty())
|
||||||
|
return candidates;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return candidates;
|
return candidates;
|
||||||
}
|
}
|
||||||
@@ -400,13 +412,13 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
candidates = lookupByUsing(name, scope);
|
if (ClassOrNamespace *bindingScope = bindings()->lookupType(scope)) {
|
||||||
|
if (ClassOrNamespace *bindingBlock = bindingScope->findBlock(scope->asBlock())) {
|
||||||
|
candidates = lookupByUsing(name, bindingBlock);
|
||||||
if (! candidates.isEmpty())
|
if (! candidates.isEmpty())
|
||||||
return candidates;
|
return candidates;
|
||||||
|
|
||||||
if (ClassOrNamespace *binding = bindings()->lookupType(scope)) {
|
candidates = bindingBlock->find(name);
|
||||||
if (ClassOrNamespace *block = binding->findBlock(scope->asBlock())) {
|
|
||||||
candidates = block->find(name);
|
|
||||||
|
|
||||||
if (! candidates.isEmpty())
|
if (! candidates.isEmpty())
|
||||||
return candidates;
|
return candidates;
|
||||||
@@ -461,15 +473,17 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
|
|||||||
} else if (scope->asNamespace()
|
} else if (scope->asNamespace()
|
||||||
|| scope->asClass()
|
|| scope->asClass()
|
||||||
|| (scope->asEnum() && scope->asEnum()->isScoped())) {
|
|| (scope->asEnum() && scope->asEnum()->isScoped())) {
|
||||||
if (ClassOrNamespace *binding = bindings()->lookupType(scope))
|
|
||||||
candidates = binding->find(name);
|
if (ClassOrNamespace *bindingScope = bindings()->lookupType(scope)) {
|
||||||
|
candidates = bindingScope->find(name);
|
||||||
|
|
||||||
if (! candidates.isEmpty())
|
if (! candidates.isEmpty())
|
||||||
return candidates;
|
return candidates;
|
||||||
|
|
||||||
candidates = lookupByUsing(name, scope);
|
candidates = lookupByUsing(name, bindingScope);
|
||||||
if (!candidates.isEmpty())
|
if (!candidates.isEmpty())
|
||||||
return candidates;
|
return candidates;
|
||||||
|
}
|
||||||
|
|
||||||
// the scope can be defined inside a block, try to find it
|
// the scope can be defined inside a block, try to find it
|
||||||
if (Block *block = scope->enclosingBlock()) {
|
if (Block *block = scope->enclosingBlock()) {
|
||||||
|
@@ -328,7 +328,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<LookupItem> lookupByUsing(const Name *name, Scope *scope) const;
|
QList<LookupItem> lookupByUsing(const Name *name, ClassOrNamespace *bindingScope) const;
|
||||||
|
|
||||||
// The current expression.
|
// The current expression.
|
||||||
Document::Ptr _expressionDocument;
|
Document::Ptr _expressionDocument;
|
||||||
|
@@ -1596,6 +1596,51 @@ void tst_CheckSymbols::test_checksymbols_data()
|
|||||||
<< Use(12, 20, 1, Highlighting::TypeUse)
|
<< Use(12, 20, 1, Highlighting::TypeUse)
|
||||||
<< Use(12, 23, 1, Highlighting::LocalUse));
|
<< 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")
|
QTest::newRow("using_inside_different_namespace_QTCREATORBUG7978")
|
||||||
<< _("class My" TEST_UNICODE_IDENTIFIER "Type { int " TEST_UNICODE_IDENTIFIER "Member; };\n"
|
<< _("class My" TEST_UNICODE_IDENTIFIER "Type { int " TEST_UNICODE_IDENTIFIER "Member; };\n"
|
||||||
"void f(My" TEST_UNICODE_IDENTIFIER "Type var" TEST_UNICODE_IDENTIFIER ")\n"
|
"void f(My" TEST_UNICODE_IDENTIFIER "Type var" TEST_UNICODE_IDENTIFIER ")\n"
|
||||||
|
Reference in New Issue
Block a user