CplusPlus: Fix minimal name construction

... when using declarations are involved.
Second attempt.
I have a suspicion that this is not the "correct" approach, however:
    a) It appears to fix the problem.
    b) It does not break any tests.
    c) It's rather high in the call tree, so there's a low likelihood
       of breaking something else.
    d) Considering the hacky-looking pre-existing code dealing with
       using declarations (e.g. LookupContext::lookupByUsing()),
       it seems quite possible that there is no "correct" way with
       the current infrastructure.

Fixes: QTCREATORBUG-14524
Change-Id: I28c6e53137c21ce158bbd03b92b3db39146116d5
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Christian Kandeler
2021-01-29 10:18:31 +01:00
parent fa260e00ed
commit aae3ce15aa
3 changed files with 49 additions and 15 deletions

View File

@@ -270,6 +270,27 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
{ {
const Name *n = nullptr; const Name *n = nullptr;
QList<const Name *> names = LookupContext::fullyQualifiedName(symbol); QList<const Name *> names = LookupContext::fullyQualifiedName(symbol);
ClassOrNamespace *current = target;
const auto getNameFromItems = [symbol, target, control](const QList<LookupItem> &items,
const QList<const Name *> &names, bool checkSymbols) -> const Name * {
for (const LookupItem &item : items) {
if (checkSymbols && !symbolIdentical(item.declaration(), symbol))
continue;
// eliminate inline namespaces
QList<const Name *> minimal = names;
for (int i = minimal.size() - 2; i >= 0; --i) {
const Name *candidate = toName(minimal.mid(0, i + 1), control);
if (isInlineNamespace(target, candidate))
minimal.removeAt(i);
}
return toName(minimal, control);
}
return nullptr;
};
for (int i = names.size() - 1; i >= 0; --i) { for (int i = names.size() - 1; i >= 0; --i) {
if (! n) if (! n)
@@ -279,20 +300,24 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
// once we're qualified enough to get the same symbol, break // once we're qualified enough to get the same symbol, break
if (target) { if (target) {
const QList<LookupItem> tresults = target->lookup(n); const Name * const minimal = getNameFromItems(target->lookup(n), names.mid(i), true);
foreach (const LookupItem &tr, tresults) { if (minimal)
if (symbolIdentical(tr.declaration(), symbol)) { return minimal;
// eliminate inline namespaces
QList<const Name *> minimal = names.mid(i);
for (int i = minimal.size() - 2; i >= 0; --i) {
const Name *candidate = toName(minimal.mid(0, i + 1), control);
if (isInlineNamespace(target, candidate))
minimal.removeAt(i);
} }
if (current) {
return toName(minimal, control); const ClassOrNamespace * const nested = current->getNested(names.last());
if (nested) {
const QList<const Name *> nameList
= names.mid(0, names.size() - i - 1) << names.last();
const QList<ClassOrNamespace *> usings = nested->usings();
for (ClassOrNamespace * const u : usings) {
const Name * const minimal = getNameFromItems(u->lookup(symbol->name()),
nameList, false);
if (minimal)
return minimal;
} }
} }
current = current->getNested(names.at(names.size() - i - 1));
} }
} }
@@ -923,6 +948,15 @@ ClassOrNamespace *ClassOrNamespace::findBlock(Block *block)
return findBlock_helper(block, &processed, true); return findBlock_helper(block, &processed, true);
} }
ClassOrNamespace *ClassOrNamespace::getNested(const Name *name)
{
flush();
const auto it = _classOrNamespaces.find(name);
if (it != _classOrNamespaces.cend())
return it->second;
return nullptr;
}
Symbol *ClassOrNamespace::lookupInScope(const QList<const Name *> &fullName) Symbol *ClassOrNamespace::lookupInScope(const QList<const Name *> &fullName)
{ {
if (!_scopeLookupCache) { if (!_scopeLookupCache) {

View File

@@ -83,6 +83,7 @@ public:
ClassOrNamespace *lookupType(const Name *name, Block *block); ClassOrNamespace *lookupType(const Name *name, Block *block);
ClassOrNamespace *findType(const Name *name); ClassOrNamespace *findType(const Name *name);
ClassOrNamespace *findBlock(Block *block); ClassOrNamespace *findBlock(Block *block);
ClassOrNamespace *getNested(const Name *name);
Symbol *lookupInScope(const QList<const Name *> &fullName); Symbol *lookupInScope(const QList<const Name *> &fullName);

View File

@@ -4322,7 +4322,6 @@ void Foo::otherFunc()
QuickFixOperationTest(testDocuments, &factory); QuickFixOperationTest(testDocuments, &factory);
} }
// FIXME: QTCREATORBUG-14524.
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_usingDecl() void CppEditorPlugin::test_quickfix_InsertDefFromDecl_usingDecl()
{ {
QList<QuickFixTestDocument::Ptr> testDocuments; QList<QuickFixTestDocument::Ptr> testDocuments;
@@ -4347,7 +4346,7 @@ void @func(const S &s);
expected = R"( expected = R"(
#include "file.h" #include "file.h"
void func(const N::S &s) void func(const S &s)
{ {
} }
@@ -4376,7 +4375,7 @@ void @func(const N1::S &s);
expected = R"( expected = R"(
#include "file.h" #include "file.h"
void func(const N1::N2::S &s) void func(const N1::S &s)
{ {
} }