diff --git a/src/libs/cplusplus/CppBindings.cpp b/src/libs/cplusplus/CppBindings.cpp index 488f8b97cc6048126a20762cd2906a2e5d8ab021..ba5c37754ee68cfa88b630d7793333bc6f939f02 100644 --- a/src/libs/cplusplus/CppBindings.cpp +++ b/src/libs/cplusplus/CppBindings.cpp @@ -82,7 +82,7 @@ NamespaceBinding::~NamespaceBinding() NameId *NamespaceBinding::name() const { if (symbols.size()) { - if (Name *name = symbols.at(0)->name()) { + if (Name *name = symbols.first()->name()) { NameId *nameId = name->asNameId(); Q_ASSERT(nameId != 0); @@ -113,20 +113,100 @@ NamespaceBinding *NamespaceBinding::globalNamespaceBinding() return it; } +Binding *NamespaceBinding::findClassOrNamespaceBinding(Identifier *id) +{ + if (id->isEqualTo(identifier())) + return const_cast<NamespaceBinding *>(this); + + foreach (NamespaceBinding *nestedNamespaceBinding, children) { + if (id->isEqualTo(nestedNamespaceBinding->identifier())) + return nestedNamespaceBinding; + } + + foreach (ClassBinding *classBinding, classBindings) { + if (id->isEqualTo(classBinding->identifier())) + return classBinding; + } + + foreach (NamespaceBinding *u, usings) { + if (Binding *b = u->findClassOrNamespaceBinding(id)) + return b; + } + + if (parent) + return parent->findClassOrNamespaceBinding(id); + + return 0; +} + +ClassBinding *NamespaceBinding::findClassBinding(Name *name) +{ + if (! name) + return 0; + + Identifier *id = name->identifier(); + + foreach (ClassBinding *classBinding, classBindings) { + if (id->isEqualTo(classBinding->identifier())) + return classBinding; + } + + if (parent) + return parent->findClassBinding(name); + + return 0; +} + NamespaceBinding *NamespaceBinding::findNamespaceBinding(Name *name) { if (! name) return anonymousNamespaceBinding; else if (NameId *nameId = name->asNameId()) - return findNamespaceBindingForNameId(nameId); + return findNamespaceBindingForNameId(nameId, /*lookAtParent = */ true); + + else if (const QualifiedNameId *q = name->asQualifiedNameId()) { + NamespaceBinding *current = this; + + for (unsigned i = 0; i < q->nameCount(); ++i) { + NameId *namespaceName = q->nameAt(i)->asNameId(); + if (! namespaceName) + return 0; + + bool lookAtParent = false; + if (i == 0) + lookAtParent = true; + + NamespaceBinding *binding = current->findNamespaceBindingForNameId(namespaceName, lookAtParent); + if (! binding) + return 0; + + current = binding; + } + + return current; + } // invalid binding return 0; } -NamespaceBinding *NamespaceBinding::findNamespaceBindingForNameId(NameId *name) +NamespaceBinding *NamespaceBinding::findNamespaceBindingForNameId(NameId *name, + bool lookAtParentNamespace) { + QSet<NamespaceBinding *> processed; + return findNamespaceBindingForNameId_helper(name, lookAtParentNamespace, &processed); +} + +NamespaceBinding *NamespaceBinding::findNamespaceBindingForNameId_helper(NameId *name, + bool lookAtParentNamespace, + QSet<NamespaceBinding *> *processed) +{ + if (processed->contains(this)) + return 0; + + processed->insert(this); + foreach (NamespaceBinding *binding, children) { Name *bindingName = binding->name(); @@ -139,6 +219,15 @@ NamespaceBinding *NamespaceBinding::findNamespaceBindingForNameId(NameId *name) } } + foreach (NamespaceBinding *u, usings) { + if (NamespaceBinding *b = u->findNamespaceBindingForNameId_helper(name, lookAtParentNamespace, processed)) { + return b; + } + } + + if (lookAtParentNamespace && parent) + return parent->findNamespaceBindingForNameId_helper(name, lookAtParentNamespace, processed); + return 0; } @@ -239,7 +328,7 @@ NamespaceBinding *NamespaceBinding::resolveNamespace(const Location &loc, else if (parent && lookAtParent) return parent->resolveNamespace(loc, name); - } else if (QualifiedNameId *q = name->asQualifiedNameId()) { + } else if (const QualifiedNameId *q = name->asQualifiedNameId()) { if (q->nameCount() == 1) { Q_ASSERT(q->isGlobal()); @@ -295,6 +384,74 @@ QByteArray ClassBinding::qualifiedId() const return s; } +Binding *ClassBinding::findClassOrNamespaceBinding(Identifier *id) +{ + if (id->isEqualTo(identifier())) + return this; + + foreach (ClassBinding *nestedClassBinding, children) { + if (id->isEqualTo(nestedClassBinding->identifier())) + return nestedClassBinding; + } + + foreach (ClassBinding *baseClassBinding, baseClassBindings) { + if (! baseClassBinding) + continue; + else if (Binding *b = baseClassBinding->findClassOrNamespaceBinding(id)) + return b; + } + + if (parent) + return parent->findClassOrNamespaceBinding(id); + + return 0; +} + +ClassBinding *ClassBinding::findClassBinding(Name *name) +{ + if (! name) + return 0; + + if (const QualifiedNameId *q = name->asQualifiedNameId()) { + Binding *currentBinding = this; + + for (unsigned i = 0; i < q->nameCount() - 1; ++i) { + Identifier *id = q->nameAt(i)->identifier(); + if (! id) + return 0; + + Binding *classOrNamespaceBinding = currentBinding->findClassOrNamespaceBinding(id); + + if (! classOrNamespaceBinding) + return 0; + + currentBinding = classOrNamespaceBinding; + } + + if (currentBinding) + return currentBinding->findClassBinding(q->unqualifiedNameId()); + + return 0; + } + + if (Identifier *id = name->identifier()) { + if (id->isEqualTo(identifier())) + return this; + + foreach (ClassBinding *nestedClassBinding, children) { + if (Identifier *nestedClassId = nestedClassBinding->identifier()) { + if (nestedClassId->isEqualTo(id)) + return nestedClassBinding; + } + } + + if (parent) + return parent->findClassBinding(name); + } + + return 0; +} + static int depth; void NamespaceBinding::dump() @@ -339,30 +496,26 @@ ClassBinding::ClassBinding(NamespaceBinding *parent) } ClassBinding::ClassBinding(ClassBinding *parentClass) + : parent(parentClass) { - parent = parentClass->parent; parentClass->children.append(this); } ClassBinding::~ClassBinding() { qDeleteAll(children); } -NameId *ClassBinding::name() const +Name *ClassBinding::name() const { - if (symbols.size()) { - if (Name *name = symbols.at(0)->name()) { - NameId *nameId = name->asNameId(); - return nameId; - } - } + if (symbols.isEmpty()) + return 0; - return 0; + return symbols.first()->name(); } Identifier *ClassBinding::identifier() const { - if (NameId *nameId = name()) - return nameId->identifier(); + if (Name *n = name()) + return n->identifier(); return 0; } @@ -497,7 +650,14 @@ ClassBinding *Binder::findOrCreateClassBinding(Class *classSymbol) ClassBinding *Binder::findClassBinding(Name *name) { - qDebug() << Q_FUNC_INFO; + if (classBinding) { + if (ClassBinding *k = classBinding->findClassBinding(name)) + return k; + } + + if (namespaceBinding) + return namespaceBinding->findClassBinding(name); + return 0; } @@ -540,16 +700,11 @@ bool Binder::visit(Class *classSymbol) ClassBinding *binding = findOrCreateClassBinding(classSymbol); ClassBinding *previousClassBinding = switchClassBinding(binding); -#if 0 for (unsigned i = 0; i < classSymbol->baseClassCount(); ++i) { BaseClass *baseClass = classSymbol->baseClassAt(i); - ClassBinding *baseClassBinding = findClassBinding(baseClass->name()); - - // ### wrong binding->baseClassBindings.append(baseClassBinding); } -#endif for (unsigned i = 0; i < classSymbol->memberCount(); ++i) accept(classSymbol->memberAt(i)); @@ -568,12 +723,10 @@ bool Binder::visit(Block *) } // end of anonymous namespace static NamespaceBinding *find_helper(Namespace *symbol, NamespaceBinding *binding, - QSet<QByteArray> *processed) + QSet<NamespaceBinding *> *processed) { - const QByteArray id = binding->qualifiedId(); - - if (! processed->contains(id)) { - processed->insert(id); + if (binding && ! processed->contains(binding)) { + processed->insert(binding); if (binding->symbols.contains(symbol)) return binding; @@ -582,6 +735,50 @@ static NamespaceBinding *find_helper(Namespace *symbol, NamespaceBinding *bindin if (NamespaceBinding *ns = find_helper(symbol, nestedBinding, processed)) return ns; } + + if (NamespaceBinding *a = find_helper(symbol, binding->anonymousNamespaceBinding, processed)) + return a; + } + + return 0; +} + +static ClassBinding *find_helper(Class *symbol, Binding *binding, + QSet<Binding *> *processed) +{ + if (binding && ! processed->contains(binding)) { + processed->insert(binding); + + if (NamespaceBinding *namespaceBinding = binding->asNamespaceBinding()) { + foreach (ClassBinding *classBinding, namespaceBinding->classBindings) { + if (ClassBinding *c = find_helper(symbol, classBinding, processed)) + return c; + } + + foreach (NamespaceBinding *nestedBinding, namespaceBinding->children) { + if (ClassBinding *c = find_helper(symbol, nestedBinding, processed)) + return c; + } + + if (ClassBinding *a = find_helper(symbol, namespaceBinding->anonymousNamespaceBinding, processed)) + return a; + + } else if (ClassBinding *classBinding = binding->asClassBinding()) { + foreach (Class *klass, classBinding->symbols) { + if (klass == symbol) + return classBinding; + } + + foreach (ClassBinding *nestedClassBinding, classBinding->children) { + if (ClassBinding *c = find_helper(symbol, nestedClassBinding, processed)) + return c; + } + +#if 0 // ### FIXME + if (ClassBinding *a = find_helper(symbol, classBinding->anonymousClassBinding, processed)) + return a; +#endif + } } return 0; @@ -589,7 +786,13 @@ static NamespaceBinding *find_helper(Namespace *symbol, NamespaceBinding *bindin NamespaceBinding *NamespaceBinding::find(Namespace *symbol, NamespaceBinding *binding) { - QSet<QByteArray> processed; + QSet<NamespaceBinding *> processed; + return find_helper(symbol, binding, &processed); +} + +ClassBinding *NamespaceBinding::find(Class *symbol, NamespaceBinding *binding) +{ + QSet<Binding *> processed; return find_helper(symbol, binding, &processed); } diff --git a/src/libs/cplusplus/CppBindings.h b/src/libs/cplusplus/CppBindings.h index 86029e105ba4b34509134f716ce9b2502f489262..be5933e2c204f9c494b4f669563f1ae95b1bbeb3 100644 --- a/src/libs/cplusplus/CppBindings.h +++ b/src/libs/cplusplus/CppBindings.h @@ -80,8 +80,12 @@ public: Binding() {} virtual ~Binding() {} + virtual QByteArray qualifiedId() const = 0; virtual NamespaceBinding *asNamespaceBinding() { return 0; } virtual ClassBinding *asClassBinding() { return 0; } + + virtual ClassBinding *findClassBinding(Name *name) = 0; + virtual Binding *findClassOrNamespaceBinding(Identifier *id) = 0; }; class CPLUSPLUS_EXPORT NamespaceBinding: public Binding @@ -112,16 +116,25 @@ public: Name *name, bool lookAtParent = true); + virtual ClassBinding *findClassBinding(Name *name); + virtual Binding *findClassOrNamespaceBinding(Identifier *id); + /// Helpers. - QByteArray qualifiedId() const; + virtual QByteArray qualifiedId() const; void dump(); virtual NamespaceBinding *asNamespaceBinding() { return this; } static NamespaceBinding *find(Namespace *symbol, NamespaceBinding *binding); + static ClassBinding *find(Class *symbol, NamespaceBinding *binding); private: - NamespaceBinding *findNamespaceBindingForNameId(NameId *name); + NamespaceBinding *findNamespaceBindingForNameId(NameId *name, + bool lookAtParentNamespace); + + NamespaceBinding *findNamespaceBindingForNameId_helper(NameId *name, + bool lookAtParentNamespace, + QSet<NamespaceBinding *> *processed); public: // attributes /// This binding's parent. @@ -152,17 +165,19 @@ public: virtual ClassBinding *asClassBinding() { return this; } /// Returns this binding's name. - NameId *name() const; + Name *name() const; /// Returns this binding's identifier. Identifier *identifier() const; + virtual QByteArray qualifiedId() const; - QByteArray qualifiedId() const; + virtual ClassBinding *findClassBinding(Name *name); + virtual Binding *findClassOrNamespaceBinding(Identifier *id); void dump(); public: // attributes - NamespaceBinding *parent; + Binding *parent; QList<ClassBinding *> children;