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,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);
|
||||
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);
|
||||
// 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"
|
||||
|
Reference in New Issue
Block a user