C++: Fix completion for typedefs for templates in namespaces.

Change-Id: Ib96551388c94731d97eb8f9728613b120b0b86a9
Reviewed-on: http://codereview.qt.nokia.com/3262
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
This commit is contained in:
Christian Kamm
2011-08-19 13:10:36 +02:00
parent f51511a81d
commit d8c053b525
3 changed files with 46 additions and 21 deletions

View File

@@ -361,7 +361,7 @@ ClassOrNamespace *LookupContext::lookupParent(Symbol *symbol) const
} }
ClassOrNamespace::ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent) ClassOrNamespace::ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent)
: _factory(factory), _parent(parent), _templateId(0) : _factory(factory), _parent(parent), _templateId(0), _instantiationOrigin(0)
{ {
} }
@@ -370,6 +370,11 @@ const TemplateNameId *ClassOrNamespace::templateId() const
return _templateId; return _templateId;
} }
ClassOrNamespace *ClassOrNamespace::instantiationOrigin() const
{
return _instantiationOrigin;
}
ClassOrNamespace *ClassOrNamespace::parent() const ClassOrNamespace *ClassOrNamespace::parent() const
{ {
return _parent; return _parent;
@@ -541,26 +546,30 @@ ClassOrNamespace *ClassOrNamespace::lookupType(const Name *name)
return 0; return 0;
QSet<ClassOrNamespace *> processed; QSet<ClassOrNamespace *> processed;
return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ true); return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ true, this);
} }
ClassOrNamespace *ClassOrNamespace::findType(const Name *name) ClassOrNamespace *ClassOrNamespace::findType(const Name *name)
{ {
QSet<ClassOrNamespace *> processed; QSet<ClassOrNamespace *> processed;
return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ false); return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ false, this);
} }
ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name, ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
QSet<ClassOrNamespace *> *processed, QSet<ClassOrNamespace *> *processed,
bool searchInEnclosingScope) bool searchInEnclosingScope,
ClassOrNamespace *origin)
{ {
if (const QualifiedNameId *q = name->asQualifiedNameId()) { if (const QualifiedNameId *q = name->asQualifiedNameId()) {
if (! q->base()) QSet<ClassOrNamespace *> innerProcessed;
return globalNamespace()->findType(q->name()); if (! q->base()) {
return globalNamespace()->lookupType_helper(q->name(), &innerProcessed, true, origin);
}
else if (ClassOrNamespace *binding = lookupType(q->base())) if (ClassOrNamespace *binding = lookupType_helper(q->base(), processed, true, origin)) {
return binding->findType(q->name()); return binding->lookupType_helper(q->name(), &innerProcessed, false, origin);
}
return 0; return 0;
@@ -577,14 +586,14 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
} }
} }
if (ClassOrNamespace *e = nestedType(name)) if (ClassOrNamespace *e = nestedType(name, origin))
return e; return e;
else if (_templateId) { else if (_templateId) {
if (_usings.size() == 1) { if (_usings.size() == 1) {
ClassOrNamespace *delegate = _usings.first(); ClassOrNamespace *delegate = _usings.first();
if (ClassOrNamespace *r = delegate->lookupType_helper(name, processed, /*searchInEnclosingScope = */ true)) if (ClassOrNamespace *r = delegate->lookupType_helper(name, processed, /*searchInEnclosingScope = */ true, origin))
return r; return r;
} else { } else {
if (debug) if (debug)
@@ -593,19 +602,19 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
} }
foreach (ClassOrNamespace *u, usings()) { foreach (ClassOrNamespace *u, usings()) {
if (ClassOrNamespace *r = u->lookupType_helper(name, processed, /*searchInEnclosingScope =*/ false)) if (ClassOrNamespace *r = u->lookupType_helper(name, processed, /*searchInEnclosingScope =*/ false, origin))
return r; return r;
} }
} }
if (_parent && searchInEnclosingScope) if (_parent && searchInEnclosingScope)
return _parent->lookupType_helper(name, processed, searchInEnclosingScope); return _parent->lookupType_helper(name, processed, searchInEnclosingScope, origin);
} }
return 0; return 0;
} }
ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name) const ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespace *origin) const
{ {
Q_ASSERT(name != 0); Q_ASSERT(name != 0);
Q_ASSERT(name->isNameId() || name->isTemplateNameId()); Q_ASSERT(name->isNameId() || name->isTemplateNameId());
@@ -622,6 +631,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name) const
if (const TemplateNameId *templId = name->asTemplateNameId()) { if (const TemplateNameId *templId = name->asTemplateNameId()) {
ClassOrNamespace *i = _factory->allocClassOrNamespace(c); ClassOrNamespace *i = _factory->allocClassOrNamespace(c);
i->_templateId = templId; i->_templateId = templId;
i->_instantiationOrigin = origin;
i->_usings.append(c); i->_usings.append(c);
return i; return i;
} }
@@ -665,19 +675,21 @@ void ClassOrNamespace::addNestedType(const Name *alias, ClassOrNamespace *e)
_classOrNamespaces[alias] = e; _classOrNamespaces[alias] = e;
} }
ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name) ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name, ClassOrNamespace *origin)
{ {
if (! name) if (! name)
return this; return this;
if (! origin)
origin = this;
if (const QualifiedNameId *q = name->asQualifiedNameId()) { if (const QualifiedNameId *q = name->asQualifiedNameId()) {
if (! q->base()) if (! q->base())
return globalNamespace()->findOrCreateType(q->name()); return globalNamespace()->findOrCreateType(q->name(), origin);
return findOrCreateType(q->base())->findOrCreateType(q->name()); return findOrCreateType(q->base(), origin)->findOrCreateType(q->name(), origin);
} else if (name->isNameId() || name->isTemplateNameId()) { } else if (name->isNameId() || name->isTemplateNameId()) {
ClassOrNamespace *e = nestedType(name); ClassOrNamespace *e = nestedType(name, origin);
if (! e) { if (! e) {
e = _factory->allocClassOrNamespace(this); e = _factory->allocClassOrNamespace(this);

View File

@@ -54,6 +54,8 @@ public:
ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent); ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent);
const TemplateNameId *templateId() const; const TemplateNameId *templateId() const;
ClassOrNamespace *instantiationOrigin() const;
ClassOrNamespace *parent() const; ClassOrNamespace *parent() const;
QList<ClassOrNamespace *> usings() const; QList<ClassOrNamespace *> usings() const;
QList<Enum *> enums() const; QList<Enum *> enums() const;
@@ -72,7 +74,7 @@ private:
void flush(); void flush();
/// \internal /// \internal
ClassOrNamespace *findOrCreateType(const Name *name); ClassOrNamespace *findOrCreateType(const Name *name, ClassOrNamespace *origin = 0);
void addTodo(Symbol *symbol); void addTodo(Symbol *symbol);
void addSymbol(Symbol *symbol); void addSymbol(Symbol *symbol);
@@ -88,9 +90,9 @@ private:
const TemplateNameId *templateId); const TemplateNameId *templateId);
ClassOrNamespace *lookupType_helper(const Name *name, QSet<ClassOrNamespace *> *processed, ClassOrNamespace *lookupType_helper(const Name *name, QSet<ClassOrNamespace *> *processed,
bool searchInEnclosingScope); bool searchInEnclosingScope, ClassOrNamespace *origin);
ClassOrNamespace *nestedType(const Name *name) const; ClassOrNamespace *nestedType(const Name *name, ClassOrNamespace *origin) const;
private: private:
struct CompareName: std::binary_function<const Name *, const Name *, bool> { struct CompareName: std::binary_function<const Name *, const Name *, bool> {
@@ -109,6 +111,7 @@ private:
// it's an instantiation. // it's an instantiation.
const TemplateNameId *_templateId; const TemplateNameId *_templateId;
ClassOrNamespace *_instantiationOrigin;
friend class CreateBindings; friend class CreateBindings;
}; };

View File

@@ -712,10 +712,20 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), overload->enclosingScope())) if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), overload->enclosingScope()))
return retBinding; return retBinding;
else if (scope != overload->enclosingScope()) { if (scope != overload->enclosingScope()) {
if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), scope)) if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), scope))
return retBinding; return retBinding;
} }
if (ClassOrNamespace *origin = binding->instantiationOrigin()) {
foreach (Symbol *originSymbol, origin->symbols()) {
Scope *originScope = originSymbol->asScope();
if (originScope && originScope != scope && originScope != overload->enclosingScope()) {
if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), originScope))
return retBinding;
}
}
}
} }
} }
} }