forked from qt-creator/qt-creator
More work on the binding pass.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user