tools/icheck/parser/src/libs/cplusplus/CppBindings.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "CppBindings.h"
       
    43 #include "CppDocument.h"
       
    44 #include "Overview.h"
       
    45 
       
    46 #include <CoreTypes.h>
       
    47 #include <Symbols.h>
       
    48 #include <Literals.h>
       
    49 #include <Names.h>
       
    50 #include <Scope.h>
       
    51 #include <Control.h>
       
    52 #include <SymbolVisitor.h>
       
    53 
       
    54 #include <QtDebug>
       
    55 
       
    56 using namespace CPlusPlus;
       
    57 
       
    58 
       
    59 ////////////////////////////////////////////////////////////////////////////////
       
    60 // Location
       
    61 ////////////////////////////////////////////////////////////////////////////////
       
    62 Location::Location()
       
    63     : _fileId(0),
       
    64       _sourceLocation(0)
       
    65 { }
       
    66 
       
    67 Location::Location(Symbol *symbol)
       
    68     : _fileId(symbol->fileId()),
       
    69       _sourceLocation(symbol->sourceLocation())
       
    70 { }
       
    71 
       
    72 Location::Location(const StringLiteral *fileId, unsigned sourceLocation)
       
    73     : _fileId(fileId), _sourceLocation(sourceLocation)
       
    74 { }
       
    75 
       
    76 ////////////////////////////////////////////////////////////////////////////////
       
    77 // NamespaceBinding
       
    78 ////////////////////////////////////////////////////////////////////////////////
       
    79 
       
    80 NamespaceBinding::NamespaceBinding(NamespaceBinding *parent)
       
    81     : parent(parent),
       
    82       anonymousNamespaceBinding(0)
       
    83 {
       
    84     if (parent)
       
    85         parent->children.append(this);
       
    86 }
       
    87 
       
    88 NamespaceBinding::~NamespaceBinding()
       
    89 {
       
    90     qDeleteAll(children);
       
    91     qDeleteAll(classBindings);
       
    92 }
       
    93 
       
    94 const NameId *NamespaceBinding::name() const
       
    95 {
       
    96     if (symbols.size()) {
       
    97         if (const Name *name = symbols.first()->name()) {
       
    98             const NameId *nameId = name->asNameId();
       
    99             Q_ASSERT(nameId != 0);
       
   100 
       
   101             return nameId;
       
   102         }
       
   103     }
       
   104 
       
   105     return 0;
       
   106 }
       
   107 
       
   108 const Identifier *NamespaceBinding::identifier() const
       
   109 {
       
   110     if (const NameId *nameId = name())
       
   111         return nameId->identifier();
       
   112 
       
   113     return 0;
       
   114 }
       
   115 
       
   116 NamespaceBinding *NamespaceBinding::globalNamespaceBinding()
       
   117 {
       
   118     NamespaceBinding *it = this;
       
   119 
       
   120     for (; it; it = it->parent) {
       
   121         if (! it->parent)
       
   122             break;
       
   123     }
       
   124 
       
   125     return it;
       
   126 }
       
   127 
       
   128 Binding *NamespaceBinding::findClassOrNamespaceBinding(const Identifier *id, QSet<Binding *> *processed)
       
   129 {
       
   130     if (processed->contains(this))
       
   131         return 0;
       
   132 
       
   133     processed->insert(this);
       
   134 
       
   135     if (id->isEqualTo(identifier()))
       
   136         return const_cast<NamespaceBinding *>(this);
       
   137 
       
   138     foreach (NamespaceBinding *nestedNamespaceBinding, children) {
       
   139         if (id->isEqualTo(nestedNamespaceBinding->identifier()))
       
   140             return nestedNamespaceBinding;
       
   141     }
       
   142 
       
   143     foreach (ClassBinding *classBinding, classBindings) {
       
   144         if (id->isEqualTo(classBinding->identifier()))
       
   145             return classBinding;
       
   146     }
       
   147 
       
   148     foreach (NamespaceBinding *u, usings) {
       
   149         if (Binding *b = u->findClassOrNamespaceBinding(id, processed))
       
   150             return b;
       
   151     }
       
   152 
       
   153     if (parent)
       
   154         return parent->findClassOrNamespaceBinding(id, processed);
       
   155 
       
   156     return 0;
       
   157 }
       
   158 
       
   159 ClassBinding *NamespaceBinding::findClassBinding(const Name *name, QSet<Binding *> *processed)
       
   160 {
       
   161     if (! name)
       
   162         return 0;
       
   163 
       
   164     if (processed->contains(this))
       
   165         return 0;
       
   166 
       
   167     if (const QualifiedNameId *q = name->asQualifiedNameId()) {
       
   168         Binding *current = this;
       
   169 
       
   170         for (unsigned i = 0; i < q->nameCount(); ++i) {
       
   171             const Identifier *nameId = q->nameAt(i)->identifier();
       
   172             if (! nameId)
       
   173                 return 0;
       
   174 
       
   175             QSet<Binding *> visited;
       
   176             Binding *binding = current->findClassOrNamespaceBinding(nameId, &visited); // ### TODO: check recursion.
       
   177             if (! binding)
       
   178                 return 0;
       
   179 
       
   180             current = binding;
       
   181         }
       
   182 
       
   183         return current->asClassBinding();
       
   184     }
       
   185 
       
   186     processed->insert(this);
       
   187 
       
   188     const Identifier *id = name->identifier();
       
   189 
       
   190     foreach (ClassBinding *classBinding, classBindings) {
       
   191         if (id->isEqualTo(classBinding->identifier()))
       
   192             return classBinding;
       
   193     }
       
   194 
       
   195     if (parent)
       
   196         return parent->findClassBinding(name, processed);
       
   197 
       
   198     foreach (NamespaceBinding *u, usings) {
       
   199         if (ClassBinding *classBinding = u->findClassBinding(name, processed))
       
   200             return classBinding;
       
   201     }
       
   202 
       
   203     return 0;
       
   204 }
       
   205 
       
   206 NamespaceBinding *NamespaceBinding::findNamespaceBinding(const Name *name)
       
   207 {
       
   208     if (! name)
       
   209         return anonymousNamespaceBinding;
       
   210 
       
   211     else if (const NameId *nameId = name->asNameId())
       
   212         return findNamespaceBindingForNameId(nameId, /*lookAtParent = */ true);
       
   213 
       
   214     else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
       
   215         NamespaceBinding *current = this;
       
   216 
       
   217         for (unsigned i = 0; i < q->nameCount(); ++i) {
       
   218             const NameId *namespaceName = q->nameAt(i)->asNameId();
       
   219             if (! namespaceName)
       
   220                 return 0;
       
   221 
       
   222             bool lookAtParent = false;
       
   223             if (i == 0)
       
   224                 lookAtParent = true;
       
   225 
       
   226             NamespaceBinding *binding = current->findNamespaceBindingForNameId(namespaceName, lookAtParent);
       
   227             if (! binding)
       
   228                 return 0;
       
   229 
       
   230             current = binding;
       
   231         }
       
   232 
       
   233         return current;
       
   234     }
       
   235 
       
   236     // invalid binding
       
   237     return 0;
       
   238 }
       
   239 
       
   240 NamespaceBinding *NamespaceBinding::findNamespaceBindingForNameId(const NameId *name,
       
   241                                                                   bool lookAtParentNamespace)
       
   242 {
       
   243     QSet<NamespaceBinding *> processed;
       
   244     return findNamespaceBindingForNameId_helper(name, lookAtParentNamespace, &processed);
       
   245 }
       
   246 
       
   247 NamespaceBinding *NamespaceBinding::findNamespaceBindingForNameId_helper(const NameId *name,
       
   248                                                                          bool lookAtParentNamespace,
       
   249                                                                          QSet<NamespaceBinding *> *processed)
       
   250 {
       
   251     if (processed->contains(this))
       
   252         return 0;
       
   253 
       
   254     processed->insert(this);
       
   255 
       
   256     foreach (NamespaceBinding *binding, children) {
       
   257         const Name *bindingName = binding->name();
       
   258 
       
   259         if (! bindingName)
       
   260             continue;
       
   261 
       
   262         if (const NameId *bindingNameId = bindingName->asNameId()) {
       
   263             if (name->isEqualTo(bindingNameId))
       
   264                 return binding;
       
   265         }
       
   266     }
       
   267 
       
   268     foreach (NamespaceBinding *u, usings) {
       
   269         if (NamespaceBinding *b = u->findNamespaceBindingForNameId_helper(name, lookAtParentNamespace, processed)) {
       
   270             return b;
       
   271         }
       
   272     }
       
   273 
       
   274     if (lookAtParentNamespace && parent)
       
   275         return parent->findNamespaceBindingForNameId_helper(name, lookAtParentNamespace, processed);
       
   276 
       
   277     return 0;
       
   278 }
       
   279 
       
   280 NamespaceBinding *NamespaceBinding::findOrCreateNamespaceBinding(Namespace *symbol)
       
   281 {
       
   282     if (NamespaceBinding *binding = findNamespaceBinding(symbol->name())) {
       
   283         int index = 0;
       
   284 
       
   285         for (; index < binding->symbols.size(); ++index) {
       
   286             Namespace *ns = binding->symbols.at(index);
       
   287 
       
   288             if (ns == symbol)
       
   289                 break;
       
   290         }
       
   291 
       
   292         if (index == binding->symbols.size())
       
   293             binding->symbols.append(symbol);
       
   294 
       
   295         return binding;
       
   296     }
       
   297 
       
   298     NamespaceBinding *binding = new NamespaceBinding(this);
       
   299     binding->symbols.append(symbol);
       
   300 
       
   301     if (! symbol->name()) {
       
   302         Q_ASSERT(! anonymousNamespaceBinding);
       
   303 
       
   304         anonymousNamespaceBinding = binding;
       
   305     }
       
   306 
       
   307     return binding;
       
   308 }
       
   309 
       
   310 static void closure(const Location &loc,
       
   311                     NamespaceBinding *binding, const Name *name,
       
   312                     QList<NamespaceBinding *> *bindings)
       
   313 {
       
   314     if (bindings->contains(binding))
       
   315         return;
       
   316 
       
   317     bindings->append(binding);
       
   318 
       
   319     Q_ASSERT(name->isNameId());
       
   320 
       
   321     const Identifier *id = name->asNameId()->identifier();
       
   322     bool ignoreUsingDirectives = false;
       
   323 
       
   324     foreach (Namespace *symbol, binding->symbols) {
       
   325         Scope *scope = symbol->members();
       
   326 
       
   327         for (Symbol *symbol = scope->lookat(id); symbol; symbol = symbol->next()) {
       
   328             if (symbol->name() != name || ! symbol->isNamespace())
       
   329                 continue;
       
   330 
       
   331             const Location l(symbol);
       
   332 
       
   333             if (l.fileId() == loc.fileId() && l.sourceLocation() < loc.sourceLocation()) {
       
   334                 ignoreUsingDirectives = true;
       
   335                 break;
       
   336             }
       
   337         }
       
   338     }
       
   339 
       
   340     if (ignoreUsingDirectives)
       
   341         return;
       
   342 
       
   343     foreach (NamespaceBinding *u, binding->usings)
       
   344         closure(loc, u, name, bindings);
       
   345 }
       
   346 
       
   347 
       
   348 NamespaceBinding *NamespaceBinding::resolveNamespace(const Location &loc,
       
   349                                                      const Name *name,
       
   350                                                      bool lookAtParent)
       
   351 {
       
   352     if (! name)
       
   353         return 0;
       
   354 
       
   355     else if (const NameId *nameId = name->asNameId()) {
       
   356         QList<NamespaceBinding *> bindings;
       
   357         closure(loc, this, nameId, &bindings);
       
   358 
       
   359         QList<NamespaceBinding *> results;
       
   360 
       
   361         foreach (NamespaceBinding *binding, bindings) {
       
   362             if (NamespaceBinding *b = binding->findNamespaceBinding(nameId))
       
   363                 results.append(b);
       
   364         }
       
   365 
       
   366         if (results.size() == 1)
       
   367             return results.at(0);
       
   368 
       
   369         else if (results.size() > 1) {
       
   370             // ### FIXME: return 0;
       
   371             return results.at(0);
       
   372         }
       
   373 
       
   374         else if (parent && lookAtParent)
       
   375             return parent->resolveNamespace(loc, name);
       
   376 
       
   377     } else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
       
   378         if (q->nameCount() == 1) {
       
   379             Q_ASSERT(q->isGlobal());
       
   380 
       
   381             return globalNamespaceBinding()->resolveNamespace(loc, q->nameAt(0));
       
   382         }
       
   383 
       
   384         NamespaceBinding *current = this;
       
   385         if (q->isGlobal())
       
   386             current = globalNamespaceBinding();
       
   387 
       
   388         current = current->resolveNamespace(loc, q->nameAt(0));
       
   389         for (unsigned i = 1; current && i < q->nameCount(); ++i)
       
   390             current = current->resolveNamespace(loc, q->nameAt(i), false);
       
   391 
       
   392         return current;
       
   393     }
       
   394 
       
   395     return 0;
       
   396 }
       
   397 
       
   398 // ### rewrite me
       
   399 QByteArray NamespaceBinding::qualifiedId() const
       
   400 {
       
   401     if (! parent)
       
   402         return "<root>";
       
   403 
       
   404     QByteArray s;
       
   405 
       
   406     s.append(parent->qualifiedId());
       
   407     s.append("::");
       
   408 
       
   409     if (const Identifier *id = identifier())
       
   410         s.append(id->chars(), id->size());
       
   411 
       
   412     else
       
   413         s.append("<anonymous>");
       
   414 
       
   415     return s;
       
   416 }
       
   417 
       
   418 // ### rewrite me
       
   419 QByteArray ClassBinding::qualifiedId() const
       
   420 {
       
   421     QByteArray s = parent->qualifiedId();
       
   422     s += "::";
       
   423 
       
   424     if (const Identifier *id = identifier())
       
   425         s.append(id->chars(), id->size());
       
   426 
       
   427     else
       
   428         s.append("<anonymous>");
       
   429 
       
   430     return s;
       
   431 }
       
   432 
       
   433 Binding *ClassBinding::findClassOrNamespaceBinding(const Identifier *id, QSet<Binding *> *processed)
       
   434 {
       
   435     if (id->isEqualTo(identifier()))
       
   436         return this;
       
   437 
       
   438     if (processed->contains(this))
       
   439         return 0;
       
   440 
       
   441     processed->insert(this);
       
   442 
       
   443     foreach (ClassBinding *nestedClassBinding, children) {
       
   444         if (id->isEqualTo(nestedClassBinding->identifier()))
       
   445             return nestedClassBinding;
       
   446     }
       
   447 
       
   448     foreach (ClassBinding *baseClassBinding, baseClassBindings) {
       
   449         if (! baseClassBinding)
       
   450             continue;
       
   451 
       
   452         else if (Binding *b = baseClassBinding->findClassOrNamespaceBinding(id, processed))
       
   453             return b;
       
   454     }
       
   455 
       
   456     if (parent)
       
   457         return parent->findClassOrNamespaceBinding(id, processed);
       
   458 
       
   459     return 0;
       
   460 }
       
   461 
       
   462 ClassBinding *ClassBinding::findClassBinding(const Name *name, QSet<Binding *> *processed)
       
   463 {
       
   464     if (! name)
       
   465         return 0;
       
   466 
       
   467     if (processed->contains(this))
       
   468         return 0;
       
   469 
       
   470     processed->insert(this);
       
   471 
       
   472     if (const QualifiedNameId *q = name->asQualifiedNameId()) {
       
   473         Binding *currentBinding = this;
       
   474 
       
   475         for (unsigned i = 0; i < q->nameCount() - 1; ++i) {
       
   476             const Identifier *id = q->nameAt(i)->identifier();
       
   477             if (! id)
       
   478                 return 0;
       
   479 
       
   480             Binding *classOrNamespaceBinding = currentBinding->findClassOrNamespaceBinding(id, processed);
       
   481 
       
   482             if (! classOrNamespaceBinding)
       
   483                 return 0;
       
   484 
       
   485             currentBinding = classOrNamespaceBinding;
       
   486         }
       
   487 
       
   488         if (currentBinding)
       
   489             return currentBinding->findClassBinding(q->unqualifiedNameId(), processed);
       
   490 
       
   491         return 0;
       
   492     }
       
   493 
       
   494     if (const Identifier *id = name->identifier()) {
       
   495         if (id->isEqualTo(identifier()))
       
   496             return this;
       
   497 
       
   498         foreach (ClassBinding *nestedClassBinding, children) {
       
   499             if (const Identifier *nestedClassId = nestedClassBinding->identifier()) {
       
   500                 if (nestedClassId->isEqualTo(id))
       
   501                     return nestedClassBinding;
       
   502             }
       
   503         }
       
   504 
       
   505         if (parent)
       
   506             return parent->findClassBinding(name, processed);
       
   507     }
       
   508 
       
   509     return 0;
       
   510 }
       
   511 
       
   512 static int depth;
       
   513 
       
   514 void NamespaceBinding::dump()
       
   515 {
       
   516     qDebug() << QByteArray(depth, ' ').constData() << "namespace" << qualifiedId().constData()
       
   517               << " # " << symbols.size();
       
   518 
       
   519     ++depth;
       
   520 
       
   521     foreach (ClassBinding *classBinding, classBindings) {
       
   522         classBinding->dump();
       
   523     }
       
   524 
       
   525     foreach (NamespaceBinding *child, children) {
       
   526         child->dump();
       
   527     }
       
   528 
       
   529     --depth;
       
   530 }
       
   531 
       
   532 void ClassBinding::dump()
       
   533 {
       
   534     qDebug() << QByteArray(depth, ' ').constData() << "class" << qualifiedId().constData()
       
   535               << " # " << symbols.size();
       
   536 
       
   537     ++depth;
       
   538 
       
   539     foreach (ClassBinding *classBinding, children) {
       
   540         classBinding->dump();
       
   541     }
       
   542 
       
   543     --depth;
       
   544 }
       
   545 
       
   546 ////////////////////////////////////////////////////////////////////////////////
       
   547 // ClassBinding
       
   548 ////////////////////////////////////////////////////////////////////////////////
       
   549 ClassBinding::ClassBinding(NamespaceBinding *parent)
       
   550     : parent(parent)
       
   551 {
       
   552     parent->classBindings.append(this);
       
   553 }
       
   554 
       
   555 ClassBinding::ClassBinding(ClassBinding *parentClass)
       
   556     : parent(parentClass)
       
   557 {
       
   558     parentClass->children.append(this);
       
   559 }
       
   560 
       
   561 ClassBinding::~ClassBinding()
       
   562 { qDeleteAll(children); }
       
   563 
       
   564 const Name *ClassBinding::name() const
       
   565 {
       
   566     if (symbols.isEmpty())
       
   567         return 0;
       
   568 
       
   569     return symbols.first()->name();
       
   570 }
       
   571 
       
   572 const Identifier *ClassBinding::identifier() const
       
   573 {
       
   574     if (const Name *n = name())
       
   575         return n->identifier();
       
   576 
       
   577     return 0;
       
   578 }
       
   579 
       
   580 namespace {
       
   581 
       
   582 ////////////////////////////////////////////////////////////////////////////////
       
   583 // Binder
       
   584 ////////////////////////////////////////////////////////////////////////////////
       
   585 
       
   586 class Binder: protected SymbolVisitor
       
   587 {
       
   588 public:
       
   589     Binder(NamespaceBinding *globals);
       
   590     virtual ~Binder();
       
   591 
       
   592     NamespaceBinding *operator()(Document::Ptr doc, const Snapshot &snapshot)
       
   593     {
       
   594         namespaceBinding = _globals;
       
   595         const Snapshot previousSnapshot = _snapshot;
       
   596 
       
   597         _snapshot = snapshot;
       
   598         (void) bind(doc);
       
   599         _snapshot = previousSnapshot;
       
   600 
       
   601         return _globals;
       
   602     }
       
   603 
       
   604     Snapshot _snapshot;
       
   605 
       
   606 protected:
       
   607     NamespaceBinding *bind(Document::Ptr doc)
       
   608     {
       
   609         QSet<QString> processed;
       
   610         return bind(doc, &processed);
       
   611     }
       
   612 
       
   613     NamespaceBinding *bind(Document::Ptr doc, QSet<QString> *processed)
       
   614     {
       
   615         if (processed->contains(doc->fileName()))
       
   616             return 0;
       
   617 
       
   618         processed->insert(doc->fileName());
       
   619 
       
   620         foreach (const Document::Include &i, doc->includes()) {
       
   621             if (Document::Ptr includedDoc = _snapshot.document(i.fileName())) {
       
   622                 /*NamepaceBinding *binding = */ bind(includedDoc, processed);
       
   623             }
       
   624         }
       
   625 
       
   626         Namespace *ns = doc->globalNamespace();
       
   627         _globals->symbols.append(ns);
       
   628 
       
   629         for (unsigned i = 0; i < ns->memberCount(); ++i) {
       
   630             (void) bind(ns->memberAt(i), _globals);
       
   631         }
       
   632 
       
   633         return _globals;
       
   634     }
       
   635 
       
   636     NamespaceBinding *bind(Symbol *symbol, NamespaceBinding *binding);
       
   637     NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol);
       
   638     NamespaceBinding *resolveNamespace(const Location &loc, const Name *name);
       
   639 
       
   640     NamespaceBinding *switchNamespaceBinding(NamespaceBinding *binding);
       
   641 
       
   642     ClassBinding *findOrCreateClassBinding(Class *classSymbol);
       
   643     ClassBinding *findClassBinding(const Name *name);
       
   644 
       
   645     ClassBinding *switchClassBinding(ClassBinding *binding);
       
   646 
       
   647     using SymbolVisitor::visit;
       
   648 
       
   649     virtual bool visit(Namespace *);
       
   650     virtual bool visit(UsingNamespaceDirective *);
       
   651     virtual bool visit(Class *);
       
   652     virtual bool visit(Function *);
       
   653     virtual bool visit(Block *);
       
   654 
       
   655 private:
       
   656     NamespaceBinding *_globals;
       
   657     NamespaceBinding *namespaceBinding;
       
   658     ClassBinding *classBinding;
       
   659 };
       
   660 
       
   661 Binder::Binder(NamespaceBinding *globals)
       
   662     : _globals(globals),
       
   663       namespaceBinding(0),
       
   664       classBinding(0)
       
   665 { }
       
   666 
       
   667 Binder::~Binder()
       
   668 { }
       
   669 
       
   670 NamespaceBinding *Binder::bind(Symbol *symbol, NamespaceBinding *binding)
       
   671 {
       
   672     NamespaceBinding *previousBinding = switchNamespaceBinding(binding);
       
   673     accept(symbol);
       
   674     return switchNamespaceBinding(previousBinding);
       
   675 }
       
   676 
       
   677 NamespaceBinding *Binder::findOrCreateNamespaceBinding(Namespace *symbol)
       
   678 { return namespaceBinding->findOrCreateNamespaceBinding(symbol); }
       
   679 
       
   680 NamespaceBinding *Binder::resolveNamespace(const Location &loc, const Name *name)
       
   681 {
       
   682     if (! namespaceBinding)
       
   683         return 0;
       
   684 
       
   685     return namespaceBinding->resolveNamespace(loc, name);
       
   686 }
       
   687 
       
   688 NamespaceBinding *Binder::switchNamespaceBinding(NamespaceBinding *binding)
       
   689 {
       
   690     NamespaceBinding *previousBinding = namespaceBinding;
       
   691     namespaceBinding = binding;
       
   692     return previousBinding;
       
   693 }
       
   694 
       
   695 ClassBinding *Binder::findOrCreateClassBinding(Class *classSymbol)
       
   696 {
       
   697     // ### FINISH ME
       
   698     ClassBinding *binding = 0;
       
   699 
       
   700     if (classBinding)
       
   701         binding = new ClassBinding(classBinding);
       
   702     else
       
   703         binding = new ClassBinding(namespaceBinding);
       
   704 
       
   705     binding->symbols.append(classSymbol);
       
   706     return binding;
       
   707 }
       
   708 
       
   709 ClassBinding *Binder::findClassBinding(const Name *name)
       
   710 {
       
   711     QSet<Binding *> processed;
       
   712 
       
   713     if (classBinding) {
       
   714         if (ClassBinding *k = classBinding->findClassBinding(name, &processed))
       
   715             return k;
       
   716 
       
   717         processed.clear();
       
   718     }
       
   719 
       
   720     if (namespaceBinding)
       
   721         return namespaceBinding->findClassBinding(name, &processed);
       
   722 
       
   723     return 0;
       
   724 }
       
   725 
       
   726 ClassBinding *Binder::switchClassBinding(ClassBinding *binding)
       
   727 {
       
   728     ClassBinding *previousClassBinding = classBinding;
       
   729     classBinding = binding;
       
   730     return previousClassBinding;
       
   731 }
       
   732 
       
   733 bool Binder::visit(Namespace *symbol)
       
   734 {
       
   735     NamespaceBinding *binding = findOrCreateNamespaceBinding(symbol);
       
   736 
       
   737     for (unsigned i = 0; i < symbol->memberCount(); ++i) {
       
   738         Symbol *member = symbol->memberAt(i);
       
   739 
       
   740         bind(member, binding);
       
   741     }
       
   742 
       
   743     return false;
       
   744 }
       
   745 
       
   746 bool Binder::visit(UsingNamespaceDirective *u)
       
   747 {
       
   748     NamespaceBinding *resolved = resolveNamespace(Location(u), u->name());
       
   749 
       
   750     if (! resolved)
       
   751         return false;
       
   752 
       
   753     namespaceBinding->usings.append(resolved);
       
   754 
       
   755     return false;
       
   756 }
       
   757 
       
   758 bool Binder::visit(Class *classSymbol)
       
   759 {
       
   760     ClassBinding *binding = findOrCreateClassBinding(classSymbol);
       
   761     ClassBinding *previousClassBinding = switchClassBinding(binding);
       
   762 
       
   763     for (unsigned i = 0; i < classSymbol->baseClassCount(); ++i) {
       
   764         BaseClass *baseClass = classSymbol->baseClassAt(i);
       
   765         ClassBinding *baseClassBinding = findClassBinding(baseClass->name());
       
   766         binding->baseClassBindings.append(baseClassBinding);
       
   767     }
       
   768 
       
   769     for (unsigned i = 0; i < classSymbol->memberCount(); ++i)
       
   770         accept(classSymbol->memberAt(i));
       
   771 
       
   772     (void) switchClassBinding(previousClassBinding);
       
   773 
       
   774     return false;
       
   775 }
       
   776 
       
   777 bool Binder::visit(Function *)
       
   778 { return false; }
       
   779 
       
   780 bool Binder::visit(Block *)
       
   781 { return false; }
       
   782 
       
   783 } // end of anonymous namespace
       
   784 
       
   785 static NamespaceBinding *find_helper(Namespace *symbol, NamespaceBinding *binding,
       
   786                                      QSet<NamespaceBinding *> *processed)
       
   787 {
       
   788     if (binding && ! processed->contains(binding)) {
       
   789         processed->insert(binding);
       
   790 
       
   791         if (binding->symbols.contains(symbol))
       
   792             return binding;
       
   793 
       
   794         foreach (NamespaceBinding *nestedBinding, binding->children) {
       
   795             if (NamespaceBinding *ns = find_helper(symbol, nestedBinding, processed))
       
   796                 return ns;
       
   797         }
       
   798 
       
   799         if (NamespaceBinding *a = find_helper(symbol, binding->anonymousNamespaceBinding, processed))
       
   800             return a;
       
   801     }
       
   802 
       
   803     return 0;
       
   804 }
       
   805 
       
   806 static ClassBinding *find_helper(Class *symbol, Binding *binding,
       
   807                                  QSet<Binding *> *processed)
       
   808 {
       
   809     if (binding && ! processed->contains(binding)) {
       
   810         processed->insert(binding);
       
   811 
       
   812         if (NamespaceBinding *namespaceBinding = binding->asNamespaceBinding()) {
       
   813             foreach (ClassBinding *classBinding, namespaceBinding->classBindings) {
       
   814                 if (ClassBinding *c = find_helper(symbol, classBinding, processed))
       
   815                     return c;
       
   816             }
       
   817 
       
   818             foreach (NamespaceBinding *nestedBinding, namespaceBinding->children) {
       
   819                 if (ClassBinding *c = find_helper(symbol, nestedBinding, processed))
       
   820                     return c;
       
   821             }
       
   822 
       
   823             if (ClassBinding *a = find_helper(symbol, namespaceBinding->anonymousNamespaceBinding, processed))
       
   824                 return a;
       
   825 
       
   826         } else if (ClassBinding *classBinding = binding->asClassBinding()) {
       
   827             foreach (Class *klass, classBinding->symbols) {
       
   828                 if (klass == symbol)
       
   829                     return classBinding;
       
   830             }
       
   831 
       
   832             foreach (ClassBinding *nestedClassBinding, classBinding->children) {
       
   833                 if (ClassBinding *c = find_helper(symbol, nestedClassBinding, processed))
       
   834                     return c;
       
   835             }
       
   836 
       
   837 #if 0 // ### FIXME
       
   838             if (ClassBinding *a = find_helper(symbol, classBinding->anonymousClassBinding, processed))
       
   839                 return a;
       
   840 #endif
       
   841         }
       
   842     }
       
   843 
       
   844     return 0;
       
   845 }
       
   846 
       
   847 NamespaceBinding *NamespaceBinding::find(Namespace *symbol, NamespaceBinding *binding)
       
   848 {
       
   849     QSet<NamespaceBinding *> processed;
       
   850     return find_helper(symbol, binding, &processed);
       
   851 }
       
   852 
       
   853 ClassBinding *NamespaceBinding::find(Class *symbol, NamespaceBinding *binding)
       
   854 {
       
   855     QSet<Binding *> processed;
       
   856     return find_helper(symbol, binding, &processed);
       
   857 }
       
   858 
       
   859 NamespaceBindingPtr CPlusPlus::bind(Document::Ptr doc, Snapshot snapshot)
       
   860 {
       
   861     NamespaceBindingPtr global(new NamespaceBinding());
       
   862 
       
   863     Binder bind(global.data());
       
   864     bind(doc, snapshot);
       
   865     return global;
       
   866 }
       
   867