diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 82ba363a0ca..db8bf190881 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -229,11 +229,11 @@ static bool isInlineNamespace(ClassOrNamespace *con, const Name *name) const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target, Control *control) { const Name *n = nullptr; + std::optional> minimal; QList names = LookupContext::fullyQualifiedName(symbol); - ClassOrNamespace *current = target; const auto getNameFromItems = [symbol, target, control](const QList &items, - const QList &names) -> const Name * { + const QList &names) -> std::optional> { for (const LookupItem &item : items) { if (!symbol->asUsingDeclaration() && !symbolIdentical(item.declaration(), symbol)) continue; @@ -246,41 +246,54 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target, minimal.removeAt(i); } - return control->toName(minimal); + return minimal; } - - return nullptr; + return {}; }; - for (int i = names.size() - 1; i >= 0; --i) { - if (! n) - n = names.at(i); - else - n = control->qualifiedNameId(names.at(i), n); + do { + ClassOrNamespace *current = target; + n = nullptr; - // once we're qualified enough to get the same symbol, break - if (target) { - const Name * const minimal = getNameFromItems(target->lookup(n), names.mid(i)); - if (minimal) - return minimal; - } - if (current) { - const ClassOrNamespace * const nested = current->getNested(names.last()); - if (nested) { - const QList nameList - = names.mid(0, names.size() - i - 1) << names.last(); - const QList usings = nested->usings(); - for (ClassOrNamespace * const u : usings) { - const Name * const minimal = getNameFromItems(u->lookup(symbol->name()), - nameList); - if (minimal) - return minimal; + for (int i = names.size() - 1; i >= 0; --i) { + if (! n) + n = names.at(i); + else + n = control->qualifiedNameId(names.at(i), n); + + if (target) { + const auto candidate = getNameFromItems(target->lookup(n), names.mid(i)); + 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 (current) { + const ClassOrNamespace * const nested = current->getNested(names.last()); + if (nested) { + const QList nameList + = names.mid(0, names.size() - i - 1) << names.last(); + const QList 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; } diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp index 1aaa4c8a5cb..a464efedc43 100644 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ b/src/plugins/cppeditor/cppquickfix_test.cpp @@ -4555,6 +4555,39 @@ D::D() )"; testDocuments << CppTestDocument::create("file.cpp", original, expected); QuickFixOperationTest(testDocuments, &factory); + + testDocuments.clear(); + original = R"( +namespace ns1 { template class span {}; } + +namespace ns { +using ns1::span; +class foo +{ + void @bar(ns::span); +}; +} +)"; + expected = R"( +namespace ns1 { template class span {}; } + +namespace ns { +using ns1::span; +class foo +{ + void bar(ns::span); +}; + +void foo::bar(ns::span) +{ + +} + +} +)"; + // 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)