| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | /**************************************************************************
 | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2010-03-05 11:25:49 +01:00
										 |  |  | ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-06-17 00:01:27 +10:00
										 |  |  | ** Contact: Nokia Corporation (qt-info@nokia.com) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | ** | 
					
						
							|  |  |  | ** 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 | 
					
						
							| 
									
										
										
										
											2009-08-14 09:30:56 +02:00
										 |  |  | ** contact the sales department at http://qt.nokia.com/contact.
 | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | ** | 
					
						
							|  |  |  | **************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "CppBindings.h"
 | 
					
						
							|  |  |  | #include "CppDocument.h"
 | 
					
						
							|  |  |  | #include "Overview.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <CoreTypes.h>
 | 
					
						
							|  |  |  | #include <Symbols.h>
 | 
					
						
							|  |  |  | #include <Literals.h>
 | 
					
						
							|  |  |  | #include <Names.h>
 | 
					
						
							|  |  |  | #include <Scope.h>
 | 
					
						
							|  |  |  | #include <Control.h>
 | 
					
						
							|  |  |  | #include <SymbolVisitor.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <QtDebug>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace CPlusPlus; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Location
 | 
					
						
							|  |  |  | ////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | Location::Location() | 
					
						
							|  |  |  |     : _fileId(0), | 
					
						
							|  |  |  |       _sourceLocation(0) | 
					
						
							|  |  |  | { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Location::Location(Symbol *symbol) | 
					
						
							|  |  |  |     : _fileId(symbol->fileId()), | 
					
						
							|  |  |  |       _sourceLocation(symbol->sourceLocation()) | 
					
						
							|  |  |  | { } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 11:33:13 +01:00
										 |  |  | Location::Location(const StringLiteral *fileId, unsigned sourceLocation) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |     : _fileId(fileId), _sourceLocation(sourceLocation) | 
					
						
							|  |  |  | { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // NamespaceBinding
 | 
					
						
							|  |  |  | ////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  | NamespaceBinding::NamespaceBinding(NamespaceBinding *parent) | 
					
						
							|  |  |  |     : parent(parent), | 
					
						
							|  |  |  |       anonymousNamespaceBinding(0) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     if (parent) | 
					
						
							|  |  |  |         parent->children.append(this); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NamespaceBinding::~NamespaceBinding() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     qDeleteAll(children); | 
					
						
							|  |  |  |     qDeleteAll(classBindings); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  | const NameId *NamespaceBinding::name() const | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     if (symbols.size()) { | 
					
						
							|  |  |  |         if (const Name *name = symbols.first()->name()) { | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  |             const NameId *nameId = name->asNameId(); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |             Q_ASSERT(nameId != 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return nameId; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 11:33:13 +01:00
										 |  |  | const Identifier *NamespaceBinding::identifier() const | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  |     if (const NameId *nameId = name()) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |         return nameId->identifier(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  | NamespaceBinding *NamespaceBinding::globalNamespaceBinding() | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     NamespaceBinding *it = this; | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     for (; it; it = it->parent) { | 
					
						
							|  |  |  |         if (! it->parent) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |             break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return it; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  | Binding *NamespaceBinding::findClassOrNamespaceBinding(const Identifier *id, QSet<Binding *> *processed) | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-07-13 18:00:22 +02:00
										 |  |  |     if (processed->contains(this)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     processed->insert(this); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |     if (id->isEqualTo(identifier())) | 
					
						
							|  |  |  |         return const_cast<NamespaceBinding *>(this); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     foreach (NamespaceBinding *nestedNamespaceBinding, children) { | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |         if (id->isEqualTo(nestedNamespaceBinding->identifier())) | 
					
						
							|  |  |  |             return nestedNamespaceBinding; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     foreach (ClassBinding *classBinding, classBindings) { | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |         if (id->isEqualTo(classBinding->identifier())) | 
					
						
							|  |  |  |             return classBinding; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     foreach (NamespaceBinding *u, usings) { | 
					
						
							| 
									
										
										
										
											2009-07-13 18:00:22 +02:00
										 |  |  |         if (Binding *b = u->findClassOrNamespaceBinding(id, processed)) | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |             return b; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     if (parent) | 
					
						
							|  |  |  |         return parent->findClassOrNamespaceBinding(id, processed); | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  | ClassBinding *NamespaceBinding::findClassBinding(const Name *name, QSet<Binding *> *processed) | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (! name) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-13 18:00:22 +02:00
										 |  |  |     if (processed->contains(this)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-04 17:38:17 +01:00
										 |  |  |     if (const QualifiedNameId *q = name->asQualifiedNameId()) { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         Binding *current = this; | 
					
						
							| 
									
										
										
										
											2009-11-04 17:38:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for (unsigned i = 0; i < q->nameCount(); ++i) { | 
					
						
							| 
									
										
										
										
											2009-12-01 11:33:13 +01:00
										 |  |  |             const Identifier *nameId = q->nameAt(i)->identifier(); | 
					
						
							| 
									
										
										
										
											2009-11-04 17:38:17 +01:00
										 |  |  |             if (! nameId) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |             QSet<Binding *> visited; | 
					
						
							|  |  |  |             Binding *binding = current->findClassOrNamespaceBinding(nameId, &visited); // ### TODO: check recursion.
 | 
					
						
							| 
									
										
										
										
											2009-11-04 17:38:17 +01:00
										 |  |  |             if (! binding) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             current = binding; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return current->asClassBinding(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-13 18:00:22 +02:00
										 |  |  |     processed->insert(this); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 11:33:13 +01:00
										 |  |  |     const Identifier *id = name->identifier(); | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     foreach (ClassBinding *classBinding, classBindings) { | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |         if (id->isEqualTo(classBinding->identifier())) | 
					
						
							|  |  |  |             return classBinding; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     if (parent) | 
					
						
							|  |  |  |         return parent->findClassBinding(name, processed); | 
					
						
							| 
									
										
										
										
											2009-07-13 18:00:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     foreach (NamespaceBinding *u, usings) { | 
					
						
							| 
									
										
										
										
											2009-07-13 18:00:22 +02:00
										 |  |  |         if (ClassBinding *classBinding = u->findClassBinding(name, processed)) | 
					
						
							|  |  |  |             return classBinding; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  | NamespaceBinding *NamespaceBinding::findNamespaceBinding(const Name *name) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (! name) | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         return anonymousNamespaceBinding; | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  |     else if (const NameId *nameId = name->asNameId()) | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |         return findNamespaceBindingForNameId(nameId, /*lookAtParent = */ true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     else if (const QualifiedNameId *q = name->asQualifiedNameId()) { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         NamespaceBinding *current = this; | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for (unsigned i = 0; i < q->nameCount(); ++i) { | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  |             const NameId *namespaceName = q->nameAt(i)->asNameId(); | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |             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; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // invalid binding
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  | NamespaceBinding *NamespaceBinding::findNamespaceBindingForNameId(const NameId *name, | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |                                                                   bool lookAtParentNamespace) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     QSet<NamespaceBinding *> processed; | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |     return findNamespaceBindingForNameId_helper(name, lookAtParentNamespace, &processed); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  | NamespaceBinding *NamespaceBinding::findNamespaceBindingForNameId_helper(const NameId *name, | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |                                                                          bool lookAtParentNamespace, | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |                                                                          QSet<NamespaceBinding *> *processed) | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (processed->contains(this)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     processed->insert(this); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     foreach (NamespaceBinding *binding, children) { | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  |         const Name *bindingName = binding->name(); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (! bindingName) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  |         if (const NameId *bindingNameId = bindingName->asNameId()) { | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |             if (name->isEqualTo(bindingNameId)) | 
					
						
							|  |  |  |                 return binding; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     foreach (NamespaceBinding *u, usings) { | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |         if (NamespaceBinding *b = u->findNamespaceBindingForNameId_helper(name, lookAtParentNamespace, processed)) { | 
					
						
							|  |  |  |             return b; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     if (lookAtParentNamespace && parent) | 
					
						
							|  |  |  |         return parent->findNamespaceBindingForNameId_helper(name, lookAtParentNamespace, processed); | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NamespaceBinding *NamespaceBinding::findOrCreateNamespaceBinding(Namespace *symbol) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     if (NamespaceBinding *binding = findNamespaceBinding(symbol->name())) { | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |         int index = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         for (; index < binding->symbols.size(); ++index) { | 
					
						
							|  |  |  |             Namespace *ns = binding->symbols.at(index); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (ns == symbol) | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         if (index == binding->symbols.size()) | 
					
						
							|  |  |  |             binding->symbols.append(symbol); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return binding; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     NamespaceBinding *binding = new NamespaceBinding(this); | 
					
						
							|  |  |  |     binding->symbols.append(symbol); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (! symbol->name()) { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         Q_ASSERT(! anonymousNamespaceBinding); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         anonymousNamespaceBinding = binding; | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return binding; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void closure(const Location &loc, | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |                     NamespaceBinding *binding, const Name *name, | 
					
						
							|  |  |  |                     QList<NamespaceBinding *> *bindings) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (bindings->contains(binding)) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bindings->append(binding); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Q_ASSERT(name->isNameId()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 11:33:13 +01:00
										 |  |  |     const Identifier *id = name->asNameId()->identifier(); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |     bool ignoreUsingDirectives = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     foreach (Namespace *symbol, binding->symbols) { | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |         Scope *scope = symbol->members(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (Symbol *symbol = scope->lookat(id); symbol; symbol = symbol->next()) { | 
					
						
							|  |  |  |             if (symbol->name() != name || ! symbol->isNamespace()) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const Location l(symbol); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (l.fileId() == loc.fileId() && l.sourceLocation() < loc.sourceLocation()) { | 
					
						
							|  |  |  |                 ignoreUsingDirectives = true; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ignoreUsingDirectives) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     foreach (NamespaceBinding *u, binding->usings) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |         closure(loc, u, name, bindings); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NamespaceBinding *NamespaceBinding::resolveNamespace(const Location &loc, | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  |                                                      const Name *name, | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |                                                      bool lookAtParent) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (! name) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  |     else if (const NameId *nameId = name->asNameId()) { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         QList<NamespaceBinding *> bindings; | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |         closure(loc, this, nameId, &bindings); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QList<NamespaceBinding *> results; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         foreach (NamespaceBinding *binding, bindings) { | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |             if (NamespaceBinding *b = binding->findNamespaceBinding(nameId)) | 
					
						
							|  |  |  |                 results.append(b); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (results.size() == 1) | 
					
						
							|  |  |  |             return results.at(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         else if (results.size() > 1) { | 
					
						
							|  |  |  |             // ### FIXME: return 0;
 | 
					
						
							|  |  |  |             return results.at(0); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         else if (parent && lookAtParent) | 
					
						
							|  |  |  |             return parent->resolveNamespace(loc, name); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |     } else if (const QualifiedNameId *q = name->asQualifiedNameId()) { | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |         if (q->nameCount() == 1) { | 
					
						
							|  |  |  |             Q_ASSERT(q->isGlobal()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return globalNamespaceBinding()->resolveNamespace(loc, q->nameAt(0)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         NamespaceBinding *current = this; | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |         if (q->isGlobal()) | 
					
						
							|  |  |  |             current = globalNamespaceBinding(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         current = current->resolveNamespace(loc, q->nameAt(0)); | 
					
						
							|  |  |  |         for (unsigned i = 1; current && i < q->nameCount(); ++i) | 
					
						
							|  |  |  |             current = current->resolveNamespace(loc, q->nameAt(i), false); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         return current; | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ### rewrite me
 | 
					
						
							|  |  |  | QByteArray NamespaceBinding::qualifiedId() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     if (! parent) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |         return "<root>"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QByteArray s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     s.append(parent->qualifiedId()); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |     s.append("::"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 11:33:13 +01:00
										 |  |  |     if (const Identifier *id = identifier()) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |         s.append(id->chars(), id->size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         s.append("<anonymous>"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ### rewrite me
 | 
					
						
							|  |  |  | QByteArray ClassBinding::qualifiedId() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     QByteArray s = parent->qualifiedId(); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |     s += "::"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 11:33:13 +01:00
										 |  |  |     if (const Identifier *id = identifier()) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |         s.append(id->chars(), id->size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         s.append("<anonymous>"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  | Binding *ClassBinding::findClassOrNamespaceBinding(const Identifier *id, QSet<Binding *> *processed) | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (id->isEqualTo(identifier())) | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         return this; | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:51:04 +01:00
										 |  |  |     if (processed->contains(this)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     processed->insert(this); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     foreach (ClassBinding *nestedClassBinding, children) { | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |         if (id->isEqualTo(nestedClassBinding->identifier())) | 
					
						
							|  |  |  |             return nestedClassBinding; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     foreach (ClassBinding *baseClassBinding, baseClassBindings) { | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |         if (! baseClassBinding) | 
					
						
							|  |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:51:04 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-13 18:00:22 +02:00
										 |  |  |         else if (Binding *b = baseClassBinding->findClassOrNamespaceBinding(id, processed)) | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |             return b; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     if (parent) | 
					
						
							|  |  |  |         return parent->findClassOrNamespaceBinding(id, processed); | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  | ClassBinding *ClassBinding::findClassBinding(const Name *name, QSet<Binding *> *processed) | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (! name) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-13 18:00:22 +02:00
										 |  |  |     if (processed->contains(this)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     processed->insert(this); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |     if (const QualifiedNameId *q = name->asQualifiedNameId()) { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         Binding *currentBinding = this; | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for (unsigned i = 0; i < q->nameCount() - 1; ++i) { | 
					
						
							| 
									
										
										
										
											2009-12-01 11:33:13 +01:00
										 |  |  |             const Identifier *id = q->nameAt(i)->identifier(); | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |             if (! id) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |             Binding *classOrNamespaceBinding = currentBinding->findClassOrNamespaceBinding(id, processed); | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (! classOrNamespaceBinding) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             currentBinding = classOrNamespaceBinding; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (currentBinding) | 
					
						
							| 
									
										
										
										
											2009-07-13 18:00:22 +02:00
										 |  |  |             return currentBinding->findClassBinding(q->unqualifiedNameId(), processed); | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 11:33:13 +01:00
										 |  |  |     if (const Identifier *id = name->identifier()) { | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |         if (id->isEqualTo(identifier())) | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |             return this; | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         foreach (ClassBinding *nestedClassBinding, children) { | 
					
						
							| 
									
										
										
										
											2009-12-01 11:33:13 +01:00
										 |  |  |             if (const Identifier *nestedClassId = nestedClassBinding->identifier()) { | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |                 if (nestedClassId->isEqualTo(id)) | 
					
						
							|  |  |  |                     return nestedClassBinding; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         if (parent) | 
					
						
							|  |  |  |             return parent->findClassBinding(name, processed); | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | static int depth; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void NamespaceBinding::dump() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qDebug() << QByteArray(depth, ' ').constData() << "namespace" << qualifiedId().constData() | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |               << " # " << symbols.size(); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ++depth; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     foreach (ClassBinding *classBinding, classBindings) { | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |         classBinding->dump(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     foreach (NamespaceBinding *child, children) { | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |         child->dump(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     --depth; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ClassBinding::dump() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qDebug() << QByteArray(depth, ' ').constData() << "class" << qualifiedId().constData() | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |               << " # " << symbols.size(); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ++depth; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     foreach (ClassBinding *classBinding, children) { | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |         classBinding->dump(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     --depth; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // ClassBinding
 | 
					
						
							|  |  |  | ////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  | ClassBinding::ClassBinding(NamespaceBinding *parent) | 
					
						
							|  |  |  |     : parent(parent) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     parent->classBindings.append(this); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ClassBinding::ClassBinding(ClassBinding *parentClass) | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     : parent(parentClass) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     parentClass->children.append(this); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ClassBinding::~ClassBinding() | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  | { qDeleteAll(children); } | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  | const Name *ClassBinding::name() const | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     if (symbols.isEmpty()) | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     return symbols.first()->name(); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 11:33:13 +01:00
										 |  |  | const Identifier *ClassBinding::identifier() const | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  |     if (const Name *n = name()) | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |         return n->identifier(); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Binder
 | 
					
						
							|  |  |  | ////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Binder: protected SymbolVisitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     Binder(NamespaceBinding *globals); | 
					
						
							|  |  |  |     virtual ~Binder(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     NamespaceBinding *operator()(Document::Ptr doc, const Snapshot &snapshot) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         namespaceBinding = _globals; | 
					
						
							|  |  |  |         const Snapshot previousSnapshot = _snapshot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         _snapshot = snapshot; | 
					
						
							|  |  |  |         (void) bind(doc); | 
					
						
							|  |  |  |         _snapshot = previousSnapshot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return _globals; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Snapshot _snapshot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     NamespaceBinding *bind(Document::Ptr doc) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QSet<QString> processed; | 
					
						
							|  |  |  |         return bind(doc, &processed); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     NamespaceBinding *bind(Document::Ptr doc, QSet<QString> *processed) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (processed->contains(doc->fileName())) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         processed->insert(doc->fileName()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach (const Document::Include &i, doc->includes()) { | 
					
						
							| 
									
										
										
										
											2009-12-07 10:54:27 +01:00
										 |  |  |             if (Document::Ptr includedDoc = _snapshot.document(i.fileName())) { | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |                 /*NamepaceBinding *binding = */ bind(includedDoc, processed); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Namespace *ns = doc->globalNamespace(); | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         _globals->symbols.append(ns); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for (unsigned i = 0; i < ns->memberCount(); ++i) { | 
					
						
							|  |  |  |             (void) bind(ns->memberAt(i), _globals); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return _globals; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     NamespaceBinding *bind(Symbol *symbol, NamespaceBinding *binding); | 
					
						
							|  |  |  |     NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol); | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  |     NamespaceBinding *resolveNamespace(const Location &loc, const Name *name); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     NamespaceBinding *switchNamespaceBinding(NamespaceBinding *binding); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ClassBinding *findOrCreateClassBinding(Class *classSymbol); | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     ClassBinding *findClassBinding(const Name *name); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ClassBinding *switchClassBinding(ClassBinding *binding); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     using SymbolVisitor::visit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool visit(Namespace *); | 
					
						
							|  |  |  |     virtual bool visit(UsingNamespaceDirective *); | 
					
						
							|  |  |  |     virtual bool visit(Class *); | 
					
						
							|  |  |  |     virtual bool visit(Function *); | 
					
						
							|  |  |  |     virtual bool visit(Block *); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     NamespaceBinding *_globals; | 
					
						
							|  |  |  |     NamespaceBinding *namespaceBinding; | 
					
						
							|  |  |  |     ClassBinding *classBinding; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Binder::Binder(NamespaceBinding *globals) | 
					
						
							|  |  |  |     : _globals(globals), | 
					
						
							|  |  |  |       namespaceBinding(0), | 
					
						
							|  |  |  |       classBinding(0) | 
					
						
							|  |  |  | { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Binder::~Binder() | 
					
						
							|  |  |  | { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NamespaceBinding *Binder::bind(Symbol *symbol, NamespaceBinding *binding) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     NamespaceBinding *previousBinding = switchNamespaceBinding(binding); | 
					
						
							|  |  |  |     accept(symbol); | 
					
						
							|  |  |  |     return switchNamespaceBinding(previousBinding); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NamespaceBinding *Binder::findOrCreateNamespaceBinding(Namespace *symbol) | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  | { return namespaceBinding->findOrCreateNamespaceBinding(symbol); } | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-01 12:46:15 +01:00
										 |  |  | NamespaceBinding *Binder::resolveNamespace(const Location &loc, const Name *name) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (! namespaceBinding) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return namespaceBinding->resolveNamespace(loc, name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NamespaceBinding *Binder::switchNamespaceBinding(NamespaceBinding *binding) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     NamespaceBinding *previousBinding = namespaceBinding; | 
					
						
							|  |  |  |     namespaceBinding = binding; | 
					
						
							|  |  |  |     return previousBinding; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ClassBinding *Binder::findOrCreateClassBinding(Class *classSymbol) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-07-13 18:00:22 +02:00
										 |  |  |     // ### FINISH ME
 | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |     ClassBinding *binding = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (classBinding) | 
					
						
							|  |  |  |         binding = new ClassBinding(classBinding); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         binding = new ClassBinding(namespaceBinding); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     binding->symbols.append(classSymbol); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |     return binding; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  | ClassBinding *Binder::findClassBinding(const Name *name) | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     QSet<Binding *> processed; | 
					
						
							| 
									
										
										
										
											2009-07-13 18:00:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |     if (classBinding) { | 
					
						
							| 
									
										
										
										
											2009-07-13 18:00:22 +02:00
										 |  |  |         if (ClassBinding *k = classBinding->findClassBinding(name, &processed)) | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |             return k; | 
					
						
							| 
									
										
										
										
											2009-10-15 11:39:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         processed.clear(); | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (namespaceBinding) | 
					
						
							| 
									
										
										
										
											2009-07-13 18:00:22 +02:00
										 |  |  |         return namespaceBinding->findClassBinding(name, &processed); | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ClassBinding *Binder::switchClassBinding(ClassBinding *binding) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ClassBinding *previousClassBinding = classBinding; | 
					
						
							|  |  |  |     classBinding = binding; | 
					
						
							|  |  |  |     return previousClassBinding; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Binder::visit(Namespace *symbol) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     NamespaceBinding *binding = findOrCreateNamespaceBinding(symbol); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (unsigned i = 0; i < symbol->memberCount(); ++i) { | 
					
						
							|  |  |  |         Symbol *member = symbol->memberAt(i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bind(member, binding); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Binder::visit(UsingNamespaceDirective *u) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     NamespaceBinding *resolved = resolveNamespace(Location(u), u->name()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (! resolved) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |     namespaceBinding->usings.append(resolved); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Binder::visit(Class *classSymbol) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ClassBinding *binding = findOrCreateClassBinding(classSymbol); | 
					
						
							|  |  |  |     ClassBinding *previousClassBinding = switchClassBinding(binding); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (unsigned i = 0; i < classSymbol->baseClassCount(); ++i) { | 
					
						
							|  |  |  |         BaseClass *baseClass = classSymbol->baseClassAt(i); | 
					
						
							|  |  |  |         ClassBinding *baseClassBinding = findClassBinding(baseClass->name()); | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         binding->baseClassBindings.append(baseClassBinding); | 
					
						
							| 
									
										
										
										
											2009-06-03 11:55:52 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (unsigned i = 0; i < classSymbol->memberCount(); ++i) | 
					
						
							|  |  |  |         accept(classSymbol->memberAt(i)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     (void) switchClassBinding(previousClassBinding); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Binder::visit(Function *) | 
					
						
							|  |  |  | { return false; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Binder::visit(Block *) | 
					
						
							|  |  |  | { return false; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // end of anonymous namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-03 14:16:13 +02:00
										 |  |  | static NamespaceBinding *find_helper(Namespace *symbol, NamespaceBinding *binding, | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |                                      QSet<NamespaceBinding *> *processed) | 
					
						
							| 
									
										
										
										
											2009-06-03 14:16:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |     if (binding && ! processed->contains(binding)) { | 
					
						
							|  |  |  |         processed->insert(binding); | 
					
						
							| 
									
										
										
										
											2009-06-03 14:16:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         if (binding->symbols.contains(symbol)) | 
					
						
							| 
									
										
										
										
											2009-06-03 14:16:13 +02:00
										 |  |  |             return binding; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         foreach (NamespaceBinding *nestedBinding, binding->children) { | 
					
						
							| 
									
										
										
										
											2009-06-03 14:16:13 +02:00
										 |  |  |             if (NamespaceBinding *ns = find_helper(symbol, nestedBinding, processed)) | 
					
						
							|  |  |  |                 return ns; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |         if (NamespaceBinding *a = find_helper(symbol, binding->anonymousNamespaceBinding, processed)) | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |             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()) { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |             foreach (ClassBinding *classBinding, namespaceBinding->classBindings) { | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |                 if (ClassBinding *c = find_helper(symbol, classBinding, processed)) | 
					
						
							|  |  |  |                     return c; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |             foreach (NamespaceBinding *nestedBinding, namespaceBinding->children) { | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |                 if (ClassBinding *c = find_helper(symbol, nestedBinding, processed)) | 
					
						
							|  |  |  |                     return c; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |             if (ClassBinding *a = find_helper(symbol, namespaceBinding->anonymousNamespaceBinding, processed)) | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |                 return a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } else if (ClassBinding *classBinding = binding->asClassBinding()) { | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |             foreach (Class *klass, classBinding->symbols) { | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |                 if (klass == symbol) | 
					
						
							|  |  |  |                     return classBinding; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 17:00:51 +01:00
										 |  |  |             foreach (ClassBinding *nestedClassBinding, classBinding->children) { | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |                 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
 | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-06-03 14:16:13 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NamespaceBinding *NamespaceBinding::find(Namespace *symbol, NamespaceBinding *binding) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-07-10 16:04:36 +02:00
										 |  |  |     QSet<NamespaceBinding *> processed; | 
					
						
							|  |  |  |     return find_helper(symbol, binding, &processed); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ClassBinding *NamespaceBinding::find(Class *symbol, NamespaceBinding *binding) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QSet<Binding *> processed; | 
					
						
							| 
									
										
										
										
											2009-06-03 14:16:13 +02:00
										 |  |  |     return find_helper(symbol, binding, &processed); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-03 12:13:22 +02:00
										 |  |  | NamespaceBindingPtr CPlusPlus::bind(Document::Ptr doc, Snapshot snapshot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     NamespaceBindingPtr global(new NamespaceBinding()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Binder bind(global.data()); | 
					
						
							|  |  |  |     bind(doc, snapshot); | 
					
						
							|  |  |  |     return global; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |