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