Files
qt-creator/src/libs/cplusplus/LookupContext.cpp

886 lines
25 KiB
C++
Raw Normal View History

2010-05-05 10:28:32 +02:00
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "LookupContext.h"
#include "ResolveExpression.h"
#include "Overview.h"
#include "DeprecatedGenTemplateInstance.h"
2010-05-05 10:28:32 +02:00
#include <CoreTypes.h>
#include <Symbols.h>
#include <Literals.h>
#include <Names.h>
#include <Scope.h>
#include <Control.h>
#include <QtDebug>
2010-05-14 14:00:56 +02:00
namespace {
const bool debug = ! qgetenv("CPLUSPLUS_LOOKUPCONTEXT_DEBUG").isEmpty();
}
2010-05-05 10:28:32 +02:00
using namespace CPlusPlus;
static void fullyQualifiedName_helper(Symbol *symbol, QList<const Name *> *names)
{
if (! symbol)
return;
fullyQualifiedName_helper(symbol->enclosingSymbol(), names);
if (symbol->name()) {
if (symbol->isClass() || symbol->isNamespace()) {
if (const QualifiedNameId *q = symbol->name()->asQualifiedNameId()) {
for (unsigned i = 0; i < q->nameCount(); ++i)
names->append(q->nameAt(i));
} else if (symbol->name()->isNameId() || symbol->name()->isTemplateNameId()) {
names->append(symbol->name());
}
} else if (symbol->isObjCClass() || symbol->isObjCBaseClass() || symbol->isObjCProtocol()
|| symbol->isObjCForwardClassDeclaration() || symbol->isObjCForwardProtocolDeclaration()) {
if (symbol->name())
names->append(symbol->name());
} else if (symbol->isFunction()) {
if (const QualifiedNameId *q = symbol->name()->asQualifiedNameId()) {
for (unsigned i = 0; i < q->nameCount() - 1; ++i)
names->append(q->nameAt(i));
}
}
}
}
bool ClassOrNamespace::CompareName::operator()(const Name *name, const Name *other) const
{
Q_ASSERT(name != 0);
Q_ASSERT(other != 0);
const Identifier *id = name->identifier();
const Identifier *otherId = other->identifier();
return strcmp(id->chars(), otherId->chars()) < 0;
}
2010-05-05 10:28:32 +02:00
/////////////////////////////////////////////////////////////////////
// LookupContext
/////////////////////////////////////////////////////////////////////
LookupContext::LookupContext()
{ }
LookupContext::LookupContext(Document::Ptr thisDocument,
const Snapshot &snapshot)
: _expressionDocument(Document::create("<LookupContext>")),
_thisDocument(thisDocument),
_snapshot(snapshot)
{
}
LookupContext::LookupContext(Document::Ptr expressionDocument,
Document::Ptr thisDocument,
const Snapshot &snapshot)
: _expressionDocument(expressionDocument),
_thisDocument(thisDocument),
_snapshot(snapshot)
{
}
LookupContext::LookupContext(const LookupContext &other)
: _expressionDocument(other._expressionDocument),
2010-05-05 10:28:32 +02:00
_thisDocument(other._thisDocument),
_snapshot(other._snapshot),
_bindings(other._bindings)
{ }
LookupContext &LookupContext::operator = (const LookupContext &other)
{
_expressionDocument = other._expressionDocument;
_thisDocument = other._thisDocument;
_snapshot = other._snapshot;
_bindings = other._bindings;
return *this;
}
QList<const Name *> LookupContext::fullyQualifiedName(Symbol *symbol)
{
QList<const Name *> names;
fullyQualifiedName_helper(symbol, &names);
return names;
}
2010-05-05 10:28:32 +02:00
QSharedPointer<CreateBindings> LookupContext::bindings() const
{
if (! _bindings)
_bindings = QSharedPointer<CreateBindings>(new CreateBindings(_thisDocument, _snapshot));
return _bindings;
}
void LookupContext::setBindings(QSharedPointer<CreateBindings> bindings)
{
_bindings = bindings;
}
Control *LookupContext::control() const
{ return bindings()->control(); }
2010-05-05 10:28:32 +02:00
Document::Ptr LookupContext::expressionDocument() const
{ return _expressionDocument; }
Document::Ptr LookupContext::thisDocument() const
{ return _thisDocument; }
Document::Ptr LookupContext::document(const QString &fileName) const
{ return _snapshot.document(fileName); }
Snapshot LookupContext::snapshot() const
{ return _snapshot; }
ClassOrNamespace *LookupContext::globalNamespace() const
{
return bindings()->globalNamespace();
}
ClassOrNamespace *LookupContext::lookupType(const Name *name, Scope *scope) const
2010-05-05 10:28:32 +02:00
{
2010-05-14 14:00:56 +02:00
if (ClassOrNamespace *b = bindings()->lookupType(scope->owner()))
return b->lookupType(name);
2010-05-05 10:28:32 +02:00
return 0;
}
ClassOrNamespace *LookupContext::lookupType(Symbol *symbol) const
2010-05-05 10:28:32 +02:00
{
2010-05-14 14:00:56 +02:00
return bindings()->lookupType(symbol);
2010-05-05 10:28:32 +02:00
}
QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
{
QList<Symbol *> candidates;
if (! name)
return candidates;
for (; scope; scope = scope->enclosingScope()) {
2010-05-25 15:55:12 +02:00
if ((name->isNameId() || name->isTemplateNameId()) && scope->isBlockScope()) {
2010-05-11 10:01:10 +02:00
bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ 0);
2010-05-05 10:28:32 +02:00
if (! candidates.isEmpty())
break; // it's a local.
for (unsigned index = 0; index < scope->symbolCount(); ++index) {
Symbol *member = scope->symbolAt(index);
if (UsingNamespaceDirective *u = member->asUsingNamespaceDirective()) {
2010-05-05 12:06:38 +02:00
if (Namespace *enclosingNamespace = u->enclosingNamespaceScope()->owner()->asNamespace()) {
2010-05-14 14:00:56 +02:00
if (ClassOrNamespace *b = bindings()->lookupType(enclosingNamespace)) {
if (ClassOrNamespace *uu = b->lookupType(u->name())) {
2010-05-05 12:06:38 +02:00
candidates = uu->lookup(name);
if (! candidates.isEmpty())
return candidates;
}
}
2010-05-05 10:28:32 +02:00
}
}
}
} else if (scope->isFunctionScope()) {
Function *fun = scope->owner()->asFunction();
2010-05-11 10:01:10 +02:00
bindings()->lookupInScope(name, fun->arguments(), &candidates, /*templateId = */ 0);
2010-05-21 15:44:04 +02:00
for (TemplateParameters *it = fun->templateParameters(); it && candidates.isEmpty(); it = it->previous())
bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0);
2010-05-05 10:28:32 +02:00
if (! candidates.isEmpty())
2010-05-21 15:44:04 +02:00
break; // it's an argument or a template parameter.
2010-05-05 10:28:32 +02:00
if (fun->name() && fun->name()->isQualifiedNameId()) {
2010-05-21 15:44:04 +02:00
if (ClassOrNamespace *binding = bindings()->lookupType(fun)) {
candidates = binding->lookup(name);
if (! candidates.isEmpty())
return candidates;
}
2010-05-05 10:28:32 +02:00
}
2010-05-21 15:44:04 +02:00
// contunue, and look at the enclosing scope.
2010-05-05 10:28:32 +02:00
} else if (scope->isObjCMethodScope()) {
ObjCMethod *method = scope->owner()->asObjCMethod();
2010-05-11 10:01:10 +02:00
bindings()->lookupInScope(name, method->arguments(), &candidates, /*templateId = */ 0);
2010-05-21 15:44:04 +02:00
2010-05-05 10:28:32 +02:00
if (! candidates.isEmpty())
break; // it's a formal argument.
2010-05-21 15:44:04 +02:00
} else if (scope->isClassScope()) {
Class *klass = scope->owner()->asClass();
for (TemplateParameters *it = klass->templateParameters(); it && candidates.isEmpty(); it = it->previous())
bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0);
if (! candidates.isEmpty())
break; // it's an argument or a template parameter.
if (ClassOrNamespace *binding = bindings()->lookupType(klass)) {
candidates = binding->lookup(name);
if (! candidates.isEmpty())
return candidates;
}
} else if (scope->isNamespaceScope() || scope->isObjCClassScope() || scope->isObjCProtocolScope()) {
2010-05-14 14:00:56 +02:00
if (ClassOrNamespace *binding = bindings()->lookupType(scope->owner()))
2010-05-05 10:28:32 +02:00
return binding->lookup(name);
break;
}
}
return candidates;
}
ClassOrNamespace::ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent)
: _factory(factory), _parent(parent), _templateId(0)
2010-05-05 10:28:32 +02:00
{
}
2010-05-12 16:04:43 +02:00
const TemplateNameId *ClassOrNamespace::templateId() const
{
return _templateId;
}
ClassOrNamespace *ClassOrNamespace::parent() const
{
return _parent;
}
2010-05-05 10:28:32 +02:00
QList<ClassOrNamespace *> ClassOrNamespace::usings() const
{
const_cast<ClassOrNamespace *>(this)->flush();
return _usings;
}
QList<Enum *> ClassOrNamespace::enums() const
{
const_cast<ClassOrNamespace *>(this)->flush();
return _enums;
}
QList<Symbol *> ClassOrNamespace::symbols() const
{
if (_templateId && ! _usings.isEmpty())
return _usings.first()->symbols(); // ask to the base implementation
2010-05-05 10:28:32 +02:00
const_cast<ClassOrNamespace *>(this)->flush();
return _symbols;
}
ClassOrNamespace *ClassOrNamespace::globalNamespace() const
{
ClassOrNamespace *e = const_cast<ClassOrNamespace *>(this);
do {
if (! e->_parent)
break;
e = e->_parent;
} while (e);
return e;
}
QList<Symbol *> ClassOrNamespace::find(const Name *name)
{
return lookup_helper(name, false);
}
2010-05-05 10:28:32 +02:00
QList<Symbol *> ClassOrNamespace::lookup(const Name *name)
{
return lookup_helper(name, true);
}
QList<Symbol *> ClassOrNamespace::lookup_helper(const Name *name, bool searchInEnclosingScope)
2010-05-05 10:28:32 +02:00
{
QList<Symbol *> result;
2010-05-12 16:04:43 +02:00
if (name) {
if (const QualifiedNameId *q = name->asQualifiedNameId()) {
ClassOrNamespace *binding = this;
2010-05-05 10:28:32 +02:00
2010-05-12 16:04:43 +02:00
if (q->isGlobal())
binding = globalNamespace();
2010-05-05 10:28:32 +02:00
2010-05-12 16:04:43 +02:00
if (q->nameCount() == 1)
return binding->find(q->unqualifiedNameId());
2010-05-10 10:38:49 +02:00
binding = binding->lookupType(q->nameAt(0));
2010-05-05 10:28:32 +02:00
2010-05-12 16:04:43 +02:00
for (unsigned index = 1; binding && index < q->nameCount() - 1; ++index)
binding = binding->findType(q->nameAt(index));
2010-05-05 10:28:32 +02:00
2010-05-12 16:04:43 +02:00
if (binding)
result = binding->find(q->unqualifiedNameId());
2010-05-05 10:28:32 +02:00
2010-05-12 16:04:43 +02:00
return result;
}
2010-05-05 10:28:32 +02:00
2010-05-12 16:04:43 +02:00
QSet<ClassOrNamespace *> processed;
ClassOrNamespace *binding = this;
do {
lookup_helper(name, binding, &result, &processed, /*templateId = */ 0);
binding = binding->_parent;
} while (searchInEnclosingScope && binding);
}
2010-05-05 10:28:32 +02:00
return result;
}
void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding,
QList<Symbol *> *result,
QSet<ClassOrNamespace *> *processed,
const TemplateNameId *templateId)
2010-05-05 10:28:32 +02:00
{
2010-05-14 14:37:17 +02:00
if (binding && ! processed->contains(binding)) {
2010-05-05 10:28:32 +02:00
processed->insert(binding);
foreach (Symbol *s, binding->symbols()) {
if (ScopedSymbol *scoped = s->asScopedSymbol())
2010-05-11 10:01:10 +02:00
_factory->lookupInScope(name, scoped->members(), result, templateId);
2010-05-05 10:28:32 +02:00
}
foreach (Enum *e, binding->enums())
2010-05-11 10:01:10 +02:00
_factory->lookupInScope(name, e->members(), result, templateId);
2010-05-05 10:28:32 +02:00
foreach (ClassOrNamespace *u, binding->usings())
lookup_helper(name, u, result, processed, binding->_templateId);
2010-05-05 10:28:32 +02:00
}
}
2010-05-11 10:01:10 +02:00
void CreateBindings::lookupInScope(const Name *name, Scope *scope,
QList<Symbol *> *result,
const TemplateNameId *templateId)
2010-05-05 10:28:32 +02:00
{
Q_UNUSED(templateId);
2010-05-05 10:28:32 +02:00
if (! name) {
return;
} else if (const OperatorNameId *op = name->asOperatorNameId()) {
for (Symbol *s = scope->lookat(op->kind()); s; s = s->next()) {
if (! s->name())
continue;
else if (! s->name()->isEqualTo(op))
continue;
2010-05-05 10:28:32 +02:00
result->append(s);
}
} else if (const Identifier *id = name->identifier()) {
for (Symbol *s = scope->lookat(id); s; s = s->next()) {
2010-05-12 11:16:54 +02:00
if (! id->isEqualTo(s->identifier()))
2010-05-05 10:28:32 +02:00
continue;
2010-05-12 11:16:54 +02:00
else if (s->name()->isQualifiedNameId())
continue; // skip qualified ids.
#if 0
2010-05-17 15:08:10 +02:00
if (templateId && (s->isDeclaration() || s->isFunction())) {
2010-05-10 09:44:18 +02:00
2010-05-17 15:08:10 +02:00
FullySpecifiedType ty = GenTemplateInstance::instantiate(templateId, s, _control);
2010-05-10 09:44:18 +02:00
2010-05-17 15:08:10 +02:00
if (debug) {
2010-05-14 15:34:39 +02:00
Overview oo;
oo.setShowFunctionSignatures(true);
oo.setShowReturnTypes(true);
2010-05-17 15:08:10 +02:00
qDebug() << "instantiate:" << oo(s->type(), s->name()) << "using:" << oo(templateId) << oo(ty);
}
2010-05-10 09:44:18 +02:00
2010-05-17 15:08:10 +02:00
if (Declaration *decl = s->asDeclaration()) {
Declaration *d = _control->newDeclaration(0, 0);
d->copy(decl);
d->setType(ty);
result->append(d);
continue;
} else if (Function *fun = s->asFunction()) {
Function *d = ty->asFunctionType();
d->copy(fun);
result->append(d);
continue;
2010-05-14 15:34:39 +02:00
}
2010-05-10 09:44:18 +02:00
}
#endif
2010-05-10 09:44:18 +02:00
2010-05-05 10:28:32 +02:00
result->append(s);
}
}
}
ClassOrNamespace *ClassOrNamespace::lookupType(const Name *name)
2010-05-05 10:28:32 +02:00
{
if (! name)
return 0;
QSet<ClassOrNamespace *> processed;
return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ true);
2010-05-05 10:28:32 +02:00
}
ClassOrNamespace *ClassOrNamespace::findType(const Name *name)
2010-05-05 10:28:32 +02:00
{
QSet<ClassOrNamespace *> processed;
return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ false);
2010-05-05 10:28:32 +02:00
}
2010-05-14 13:49:16 +02:00
ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
QSet<ClassOrNamespace *> *processed,
bool searchInEnclosingScope)
2010-05-05 10:28:32 +02:00
{
if (const QualifiedNameId *q = name->asQualifiedNameId()) {
ClassOrNamespace *e = this;
2010-05-05 10:28:32 +02:00
if (q->isGlobal())
e = globalNamespace();
2010-05-05 10:28:32 +02:00
e = e->lookupType(q->nameAt(0));
2010-05-05 10:28:32 +02:00
for (unsigned index = 1; e && index < q->nameCount(); ++index)
e = e->findType(q->nameAt(index));
2010-05-05 10:28:32 +02:00
return e;
2010-05-05 10:28:32 +02:00
} else if (! processed->contains(this)) {
processed->insert(this);
2010-05-05 10:28:32 +02:00
if (name->isNameId() || name->isTemplateNameId()) {
flush();
2010-05-05 10:28:32 +02:00
2010-05-14 13:49:16 +02:00
if (ClassOrNamespace *e = nestedType(name))
2010-05-05 10:28:32 +02:00
return e;
2010-05-21 15:44:04 +02:00
else if (_templateId) {
Q_ASSERT(_usings.size() == 1);
ClassOrNamespace *delegate = _usings.first();
if (ClassOrNamespace *r = delegate->lookupType_helper(name, processed, /*searchInEnclosingScope = */ true))
return r;
}
2010-05-05 10:28:32 +02:00
foreach (ClassOrNamespace *u, usings()) {
if (ClassOrNamespace *r = u->lookupType_helper(name, processed, /*searchInEnclosingScope =*/ false))
2010-05-05 10:28:32 +02:00
return r;
}
}
if (_parent && searchInEnclosingScope)
return _parent->lookupType_helper(name, processed, searchInEnclosingScope);
2010-05-05 10:28:32 +02:00
}
return 0;
}
2010-05-14 13:49:16 +02:00
ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name) const
2010-05-05 10:28:32 +02:00
{
Q_ASSERT(name != 0);
Q_ASSERT(name->isNameId() || name->isTemplateNameId());
2010-05-05 10:28:32 +02:00
const_cast<ClassOrNamespace *>(this)->flush();
2010-05-05 10:28:32 +02:00
Table::const_iterator it = _classOrNamespaces.find(name);
2010-05-05 10:28:32 +02:00
if (it == _classOrNamespaces.end())
return 0;
2010-05-05 10:28:32 +02:00
ClassOrNamespace *c = it->second;
if (const TemplateNameId *templId = name->asTemplateNameId()) {
foreach (ClassOrNamespace *i, c->_instantiations) {
2010-05-10 09:44:18 +02:00
if (templId->isEqualTo(i->_templateId))
return i;
}
ClassOrNamespace *i = _factory->allocClassOrNamespace(c);
i->_templateId = templId;
i->_usings.append(c);
c->_instantiations.append(i);
return i;
}
return c;
2010-05-05 10:28:32 +02:00
}
void ClassOrNamespace::flush()
{
2010-05-05 14:07:10 +02:00
if (! _todo.isEmpty()) {
const QList<Symbol *> todo = _todo;
_todo.clear();
2010-05-05 10:28:32 +02:00
2010-05-05 14:07:10 +02:00
foreach (Symbol *member, todo)
2010-05-05 10:28:32 +02:00
_factory->process(member, this);
}
}
void ClassOrNamespace::addSymbol(Symbol *symbol)
{
_symbols.append(symbol);
}
void ClassOrNamespace::addTodo(Symbol *symbol)
{
_todo.append(symbol);
}
void ClassOrNamespace::addEnum(Enum *e)
{
_enums.append(e);
}
void ClassOrNamespace::addUsing(ClassOrNamespace *u)
{
_usings.append(u);
}
2010-05-14 13:49:16 +02:00
void ClassOrNamespace::addNestedType(const Name *alias, ClassOrNamespace *e)
2010-05-05 10:28:32 +02:00
{
_classOrNamespaces[alias] = e;
2010-05-05 10:28:32 +02:00
}
ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name)
2010-05-05 10:28:32 +02:00
{
if (! name)
return this;
if (const QualifiedNameId *q = name->asQualifiedNameId()) {
ClassOrNamespace *e = this;
for (unsigned i = 0; e && i < q->nameCount(); ++i)
e = e->findOrCreateType(q->nameAt(i));
2010-05-05 10:28:32 +02:00
return e;
} else if (name->isNameId() || name->isTemplateNameId()) {
2010-05-14 13:49:16 +02:00
ClassOrNamespace *e = nestedType(name);
2010-05-05 10:28:32 +02:00
if (! e) {
e = _factory->allocClassOrNamespace(this);
_classOrNamespaces[name] = e;
2010-05-05 10:28:32 +02:00
}
return e;
}
return 0;
}
CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot)
: _snapshot(snapshot)
{
_control = new Control();
2010-05-05 10:28:32 +02:00
_globalNamespace = allocClassOrNamespace(/*parent = */ 0);
_currentClassOrNamespace = _globalNamespace;
process(thisDocument);
}
CreateBindings::~CreateBindings()
{
qDeleteAll(_entities);
delete _control;
2010-05-05 10:28:32 +02:00
}
2010-05-11 10:03:30 +02:00
ClassOrNamespace *CreateBindings::switchCurrentClassOrNamespace(ClassOrNamespace *classOrNamespace)
2010-05-05 10:28:32 +02:00
{
ClassOrNamespace *previous = _currentClassOrNamespace;
_currentClassOrNamespace = classOrNamespace;
return previous;
}
ClassOrNamespace *CreateBindings::globalNamespace() const
{
return _globalNamespace;
}
2010-05-14 14:00:56 +02:00
ClassOrNamespace *CreateBindings::lookupType(Symbol *symbol)
2010-05-05 10:28:32 +02:00
{
const QList<const Name *> names = LookupContext::fullyQualifiedName(symbol);
2010-05-05 10:28:32 +02:00
if (names.isEmpty())
return _globalNamespace;
2010-05-05 10:28:32 +02:00
ClassOrNamespace *b = _globalNamespace->lookupType(names.at(0));
for (int i = 1; b && i < names.size(); ++i)
b = b->findType(names.at(i));
return b;
2010-05-05 10:28:32 +02:00
}
void CreateBindings::process(Symbol *s, ClassOrNamespace *classOrNamespace)
{
2010-05-11 10:03:30 +02:00
ClassOrNamespace *previous = switchCurrentClassOrNamespace(classOrNamespace);
2010-05-05 10:28:32 +02:00
accept(s);
2010-05-11 10:03:30 +02:00
(void) switchCurrentClassOrNamespace(previous);
2010-05-05 10:28:32 +02:00
}
void CreateBindings::process(Symbol *symbol)
{
_currentClassOrNamespace->addTodo(symbol);
}
Control *CreateBindings::control() const
{
return _control;
}
2010-05-05 10:28:32 +02:00
ClassOrNamespace *CreateBindings::allocClassOrNamespace(ClassOrNamespace *parent)
{
ClassOrNamespace *e = new ClassOrNamespace(this, parent);
_entities.append(e);
return e;
}
void CreateBindings::process(Document::Ptr doc)
{
if (! doc)
return;
else if (Namespace *globalNamespace = doc->globalNamespace()) {
if (! _processed.contains(globalNamespace)) {
_processed.insert(globalNamespace);
foreach (const Document::Include &i, doc->includes()) {
if (Document::Ptr incl = _snapshot.document(i.fileName()))
process(incl);
}
accept(globalNamespace);
}
}
}
2010-05-11 10:12:49 +02:00
ClassOrNamespace *CreateBindings::enterClassOrNamespaceBinding(Symbol *symbol)
2010-05-05 10:28:32 +02:00
{
ClassOrNamespace *entity = _currentClassOrNamespace->findOrCreateType(symbol->name());
2010-05-05 10:28:32 +02:00
entity->addSymbol(symbol);
2010-05-11 10:03:30 +02:00
return switchCurrentClassOrNamespace(entity);
2010-05-05 10:28:32 +02:00
}
2010-05-11 10:12:49 +02:00
ClassOrNamespace *CreateBindings::enterGlobalClassOrNamespace(Symbol *symbol)
2010-05-05 10:28:32 +02:00
{
ClassOrNamespace *entity = _globalNamespace->findOrCreateType(symbol->name());
2010-05-05 10:28:32 +02:00
entity->addSymbol(symbol);
2010-05-11 10:03:30 +02:00
return switchCurrentClassOrNamespace(entity);
2010-05-05 10:28:32 +02:00
}
bool CreateBindings::visit(Namespace *ns)
{
2010-05-11 10:12:49 +02:00
ClassOrNamespace *previous = enterClassOrNamespaceBinding(ns);
2010-05-05 10:28:32 +02:00
for (unsigned i = 0; i < ns->memberCount(); ++i)
process(ns->memberAt(i));
_currentClassOrNamespace = previous;
return false;
}
bool CreateBindings::visit(Class *klass)
{
ClassOrNamespace *previous = _currentClassOrNamespace;
ClassOrNamespace *binding = 0;
if (klass->name() && klass->name()->isQualifiedNameId())
binding = _currentClassOrNamespace->lookupType(klass->name());
if (! binding)
binding = _currentClassOrNamespace->findOrCreateType(klass->name());
_currentClassOrNamespace = binding;
_currentClassOrNamespace->addSymbol(klass);
2010-05-05 10:28:32 +02:00
for (unsigned i = 0; i < klass->baseClassCount(); ++i)
process(klass->baseClassAt(i));
for (unsigned i = 0; i < klass->memberCount(); ++i)
process(klass->memberAt(i));
_currentClassOrNamespace = previous;
return false;
}
bool CreateBindings::visit(ForwardClassDeclaration *klass)
{
2010-05-10 09:47:46 +02:00
if (! klass->isFriend()) {
2010-05-11 10:12:49 +02:00
ClassOrNamespace *previous = enterClassOrNamespaceBinding(klass);
2010-05-10 09:47:46 +02:00
_currentClassOrNamespace = previous;
}
2010-05-05 10:28:32 +02:00
return false;
}
bool CreateBindings::visit(Enum *e)
{
_currentClassOrNamespace->addEnum(e);
return false;
}
bool CreateBindings::visit(Declaration *decl)
{
if (decl->isTypedef()) {
const FullySpecifiedType ty = decl->type();
const Identifier *typedefId = decl->identifier();
if (typedefId && ! (ty.isConst() || ty.isVolatile())) {
if (const NamedType *namedTy = ty->asNamedType()) {
if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(namedTy->name())) {
2010-05-14 13:49:16 +02:00
_currentClassOrNamespace->addNestedType(decl->name(), e);
2010-05-05 10:28:32 +02:00
} else if (false) {
Overview oo;
qDebug() << "found entity not found for" << oo(namedTy->name());
}
}
}
}
return false;
}
bool CreateBindings::visit(Function *)
{
return false;
}
bool CreateBindings::visit(BaseClass *b)
{
if (ClassOrNamespace *base = _currentClassOrNamespace->lookupType(b->name())) {
2010-05-05 10:28:32 +02:00
_currentClassOrNamespace->addUsing(base);
} else if (false) {
Overview oo;
qDebug() << "no entity for:" << oo(b->name());
}
return false;
}
bool CreateBindings::visit(UsingNamespaceDirective *u)
{
if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(u->name())) {
2010-05-05 10:28:32 +02:00
_currentClassOrNamespace->addUsing(e);
} else if (false) {
Overview oo;
qDebug() << "no entity for namespace:" << oo(u->name());
}
return false;
}
bool CreateBindings::visit(NamespaceAlias *a)
{
if (! a->identifier()) {
return false;
} else if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(a->namespaceName())) {
if (a->name()->isNameId() || a->name()->isTemplateNameId())
2010-05-14 13:49:16 +02:00
_currentClassOrNamespace->addNestedType(a->name(), e);
2010-05-05 10:28:32 +02:00
} else if (false) {
Overview oo;
qDebug() << "no entity for namespace:" << oo(a->namespaceName());
}
return false;
}
bool CreateBindings::visit(ObjCClass *klass)
{
2010-05-11 10:12:49 +02:00
ClassOrNamespace *previous = enterGlobalClassOrNamespace(klass);
2010-05-05 10:28:32 +02:00
process(klass->baseClass());
for (unsigned i = 0; i < klass->protocolCount(); ++i)
process(klass->protocolAt(i));
for (unsigned i = 0; i < klass->memberCount(); ++i)
process(klass->memberAt(i));
_currentClassOrNamespace = previous;
return false;
}
bool CreateBindings::visit(ObjCBaseClass *b)
{
if (ClassOrNamespace *base = _globalNamespace->lookupType(b->name())) {
2010-05-05 10:28:32 +02:00
_currentClassOrNamespace->addUsing(base);
} else if (false) {
Overview oo;
qDebug() << "no entity for:" << oo(b->name());
}
return false;
}
bool CreateBindings::visit(ObjCForwardClassDeclaration *klass)
{
2010-05-11 10:12:49 +02:00
ClassOrNamespace *previous = enterGlobalClassOrNamespace(klass);
2010-05-05 10:28:32 +02:00
_currentClassOrNamespace = previous;
return false;
}
bool CreateBindings::visit(ObjCProtocol *proto)
{
2010-05-11 10:12:49 +02:00
ClassOrNamespace *previous = enterGlobalClassOrNamespace(proto);
2010-05-05 10:28:32 +02:00
for (unsigned i = 0; i < proto->protocolCount(); ++i)
process(proto->protocolAt(i));
for (unsigned i = 0; i < proto->memberCount(); ++i)
process(proto->memberAt(i));
_currentClassOrNamespace = previous;
return false;
}
bool CreateBindings::visit(ObjCBaseProtocol *b)
{
if (ClassOrNamespace *base = _globalNamespace->lookupType(b->name())) {
2010-05-05 10:28:32 +02:00
_currentClassOrNamespace->addUsing(base);
} else if (false) {
Overview oo;
qDebug() << "no entity for:" << oo(b->name());
}
return false;
}
bool CreateBindings::visit(ObjCForwardProtocolDeclaration *proto)
{
2010-05-11 10:12:49 +02:00
ClassOrNamespace *previous = enterGlobalClassOrNamespace(proto);
2010-05-05 10:28:32 +02:00
_currentClassOrNamespace = previous;
return false;
}
bool CreateBindings::visit(ObjCMethod *)
{
return false;
}