forked from qt-creator/qt-creator
C++: Improve lookup - collect more valid items
There was a fix for QTCREATORBUG-7730 in the case of nested
forward declarations in commit 74a458bca0
.
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: Christian Kamm <christian.d.kamm@nokia.com>
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
@@ -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
|
||||
|
Reference in New Issue
Block a user