CppEditor: Another name minimalization fix

... involving using declarations.
See also aae3ce15aa.

Fixes: QTCREATORBUG-28386
Change-Id: I4171dce7b4e34b41c4a894e3bb34b3f62f82ac0f
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Christian Kandeler
2022-11-30 16:47:48 +01:00
parent 5f4a5802cc
commit 4e7adc2462
2 changed files with 76 additions and 30 deletions

View File

@@ -229,11 +229,11 @@ static bool isInlineNamespace(ClassOrNamespace *con, const Name *name)
const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target, Control *control) const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target, Control *control)
{ {
const Name *n = nullptr; const Name *n = nullptr;
std::optional<QList<const Name *>> minimal;
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 auto getNameFromItems = [symbol, target, control](const QList<LookupItem> &items,
const QList<const Name *> &names) -> const Name * { const QList<const Name *> &names) -> std::optional<QList<const Name *>> {
for (const LookupItem &item : items) { for (const LookupItem &item : items) {
if (!symbol->asUsingDeclaration() && !symbolIdentical(item.declaration(), symbol)) if (!symbol->asUsingDeclaration() && !symbolIdentical(item.declaration(), symbol))
continue; continue;
@@ -246,41 +246,54 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
minimal.removeAt(i); minimal.removeAt(i);
} }
return control->toName(minimal); return minimal;
} }
return {};
return nullptr;
}; };
for (int i = names.size() - 1; i >= 0; --i) { do {
if (! n) ClassOrNamespace *current = target;
n = names.at(i); n = nullptr;
else
n = control->qualifiedNameId(names.at(i), n);
// once we're qualified enough to get the same symbol, break for (int i = names.size() - 1; i >= 0; --i) {
if (target) { if (! n)
const Name * const minimal = getNameFromItems(target->lookup(n), names.mid(i)); n = names.at(i);
if (minimal) else
return minimal; n = control->qualifiedNameId(names.at(i), n);
}
if (current) { if (target) {
const ClassOrNamespace * const nested = current->getNested(names.last()); const auto candidate = getNameFromItems(target->lookup(n), names.mid(i));
if (nested) { if (candidate && (!minimal || minimal->size() > candidate->size())) {
const QList<const Name *> nameList minimal = candidate;
= names.mid(0, names.size() - i - 1) << names.last(); if (minimal && minimal->size() == 1)
const QList<ClassOrNamespace *> usings = nested->usings(); return control->toName(*minimal);
for (ClassOrNamespace * const u : usings) {
const Name * const minimal = getNameFromItems(u->lookup(symbol->name()),
nameList);
if (minimal)
return minimal;
} }
} }
current = current->getNested(names.at(names.size() - i - 1));
}
}
if (current) {
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 auto candidate = getNameFromItems(u->lookup(symbol->name()), nameList);
if (candidate && (!minimal || minimal->size() > candidate->size())) {
minimal = candidate;
if (minimal && minimal->size() == 1)
return control->toName(*minimal);
}
}
}
current = current->getNested(names.at(names.size() - i - 1));
}
}
if (target)
target = target->parent();
} while (target);
if (minimal)
return control->toName(*minimal);
return n; return n;
} }

View File

@@ -4555,6 +4555,39 @@ D::D()
)"; )";
testDocuments << CppTestDocument::create("file.cpp", original, expected); testDocuments << CppTestDocument::create("file.cpp", original, expected);
QuickFixOperationTest(testDocuments, &factory); QuickFixOperationTest(testDocuments, &factory);
testDocuments.clear();
original = R"(
namespace ns1 { template<typename T> class span {}; }
namespace ns {
using ns1::span;
class foo
{
void @bar(ns::span<int>);
};
}
)";
expected = R"(
namespace ns1 { template<typename T> class span {}; }
namespace ns {
using ns1::span;
class foo
{
void bar(ns::span<int>);
};
void foo::bar(ns::span<int>)
{
}
}
)";
// TODO: Unneeded namespace gets inserted in RewriteName::visit(const QualifiedNameId *)
testDocuments << CppTestDocument::create("file.cpp", original, expected);
QuickFixOperationTest(testDocuments, &factory);
} }
/// Find right implementation file. (QTCREATORBUG-10728) /// Find right implementation file. (QTCREATORBUG-10728)