forked from qt-creator/qt-creator
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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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)
|
||||||
|
Reference in New Issue
Block a user