Commit 903c3caf authored by Leandro Melo's avatar Leandro Melo
Browse files

C++: Improve lookup - collect more valid items

There was a fix for QTCREATORBUG-7730 in the case of nested
forward declarations in commit 74a458bc

.
However, it introduced regressions and actually didn't solve
the issue, since the behavior was hidden by another error fixed later.

The patch should properly fix the issue and the regression pointed
in QTCREATORBUG-7777.

Task-number: QTCREATORBUG-7730
Task-number: QTCREATORBUG-7777
Change-Id: I27397fefdc7cc9a60111761df1f76a01407886f7
Reviewed-by: default avatarChristian Kamm <christian.d.kamm@nokia.com>
Reviewed-by: Orgad Shaneh's avatarOrgad Shaneh <orgads@gmail.com>
parent 41a7d1c6
......@@ -212,35 +212,6 @@ void FindUsages::reportResult(unsigned tokenIndex)
_references.append(tokenIndex);
}
bool FindUsages::compareFullyQualifiedName(const QList<const Name *> &path, const QList<const Name *> &other)
{
if (path.length() != other.length())
return false;
for (int i = 0; i < path.length(); ++i) {
if (! compareName(path.at(i), other.at(i)))
return false;
}
return true;
}
bool FindUsages::compareName(const Name *name, const Name *other)
{
if (name == other)
return true;
else if (name && other) {
const Identifier *id = name->identifier();
const Identifier *otherId = other->identifier();
if (id == otherId || (id && id->isEqualTo(otherId)))
return true;
}
return false;
}
bool FindUsages::isLocalScope(Scope *scope)
{
if (scope) {
......
......@@ -82,8 +82,6 @@ protected:
bool checkCandidates(const QList<LookupItem> &candidates) const;
void checkExpression(unsigned startToken, unsigned endToken, Scope *scope = 0);
static bool compareFullyQualifiedName(const QList<const Name *> &path, const QList<const Name *> &other);
static bool compareName(const Name *name, const Name *other);
static bool isLocalScope(Scope *scope);
void statement(StatementAST *ast);
......
......@@ -88,6 +88,39 @@ static void path_helper(Symbol *symbol, QList<const Name *> *names)
}
}
static bool compareName(const Name *name, const Name *other)
{
if (name == other)
return true;
else if (name && other) {
const Identifier *id = name->identifier();
const Identifier *otherId = other->identifier();
if (id == otherId || (id && id->isEqualTo(otherId)))
return true;
}
return false;
}
namespace CPlusPlus {
bool compareFullyQualifiedName(const QList<const Name *> &path, const QList<const Name *> &other)
{
if (path.length() != other.length())
return false;
for (int i = 0; i < path.length(); ++i) {
if (! compareName(path.at(i), other.at(i)))
return false;
}
return true;
}
}
bool ClassOrNamespace::CompareName::operator()(const Name *name, const Name *other) const
{
Q_ASSERT(name != 0);
......@@ -416,20 +449,51 @@ QList<LookupItem> ClassOrNamespace::lookup_helper(const Name *name, bool searchI
QList<LookupItem> result;
if (name) {
QSet<ClassOrNamespace *> processed;
if (const QualifiedNameId *q = name->asQualifiedNameId()) {
if (! q->base())
result = globalNamespace()->find(q->name());
else if (ClassOrNamespace *binding = lookupType(q->base()))
else if (ClassOrNamespace *binding = lookupType(q->base())) {
result = binding->find(q->name());
lookup_helper(name, this, &result, &processed, /*templateId = */ 0);
QList<const Name *> fullName;
addNames(name, &fullName);
// It's also possible that there are matches in the parent binding through
// a qualified name. For instance, a nested class which is forward declared
// in the class but defined outside it - we should capture both.
Symbol *match = 0;
ClassOrNamespace *parentBinding = binding->parent();
while (parentBinding && !match) {
for (int j = 0; j < parentBinding->symbols().size() && !match; ++j) {
if (Scope *scope = parentBinding->symbols().at(j)->asScope()) {
for (unsigned i = 0; i < scope->memberCount(); ++i) {
Symbol *candidate = scope->memberAt(i);
if (compareFullyQualifiedName(
fullName,
LookupContext::fullyQualifiedName(candidate))) {
match = candidate;
break;
}
}
}
}
parentBinding = parentBinding->parent();
}
if (match) {
LookupItem item;
item.setDeclaration(match);
item.setBinding(binding);
result.append(item);
}
}
return result;
}
QSet<ClassOrNamespace *> processed;
ClassOrNamespace *binding = this;
do {
lookup_helper(name, binding, &result, &processed, /*templateId = */ 0);
......@@ -456,6 +520,7 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding
else if (s->isUsingNamespaceDirective())
continue;
if (Scope *scope = s->asScope()) {
if (Class *klass = scope->asClass()) {
if (const Identifier *id = klass->identifier()) {
......
......@@ -252,6 +252,10 @@ private:
QSharedPointer<Control> _control;
};
bool CPLUSPLUS_EXPORT compareFullyQualifiedName(const QList<const Name *> &path,
const QList<const Name *> &other);
} // namespace CPlusPlus
#endif // CPLUSPLUS_LOOKUPCONTEXT_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment