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,24 +246,30 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
minimal.removeAt(i); minimal.removeAt(i);
} }
return control->toName(minimal); return minimal;
} }
return {};
return nullptr;
}; };
do {
ClassOrNamespace *current = target;
n = nullptr;
for (int i = names.size() - 1; i >= 0; --i) { for (int i = names.size() - 1; i >= 0; --i) {
if (! n) if (! n)
n = names.at(i); n = names.at(i);
else else
n = control->qualifiedNameId(names.at(i), n); n = control->qualifiedNameId(names.at(i), n);
// once we're qualified enough to get the same symbol, break
if (target) { if (target) {
const Name * const minimal = getNameFromItems(target->lookup(n), names.mid(i)); const auto candidate = getNameFromItems(target->lookup(n), names.mid(i));
if (minimal) if (candidate && (!minimal || minimal->size() > candidate->size())) {
return minimal; minimal = candidate;
if (minimal && minimal->size() == 1)
return control->toName(*minimal);
} }
}
if (current) { if (current) {
const ClassOrNamespace * const nested = current->getNested(names.last()); const ClassOrNamespace * const nested = current->getNested(names.last());
if (nested) { if (nested) {
@@ -271,16 +277,23 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
= names.mid(0, names.size() - i - 1) << names.last(); = names.mid(0, names.size() - i - 1) << names.last();
const QList<ClassOrNamespace *> usings = nested->usings(); const QList<ClassOrNamespace *> usings = nested->usings();
for (ClassOrNamespace * const u : usings) { for (ClassOrNamespace * const u : usings) {
const Name * const minimal = getNameFromItems(u->lookup(symbol->name()), const auto candidate = getNameFromItems(u->lookup(symbol->name()), nameList);
nameList); if (candidate && (!minimal || minimal->size() > candidate->size())) {
if (minimal) minimal = candidate;
return minimal; if (minimal && minimal->size() == 1)
return control->toName(*minimal);
}
} }
} }
current = current->getNested(names.at(names.size() - i - 1)); 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)