| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | /**************************************************************************
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-06-17 00:01:27 +10:00
										 |  |  | ** Contact: Nokia Corporation (qt-info@nokia.com) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Commercial Usage | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** 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. | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** GNU Lesser General Public License Usage | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** 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.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** 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.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | **************************************************************************/ | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "LookupContext.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-31 10:57:27 +01:00
										 |  |  | #include "ResolveExpression.h"
 | 
					
						
							|  |  |  | #include "Overview.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <CoreTypes.h>
 | 
					
						
							|  |  |  | #include <Symbols.h>
 | 
					
						
							|  |  |  | #include <Literals.h>
 | 
					
						
							|  |  |  | #include <Names.h>
 | 
					
						
							|  |  |  | #include <Scope.h>
 | 
					
						
							|  |  |  | #include <Control.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <QtDebug>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace CPlusPlus; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // LookupContext
 | 
					
						
							|  |  |  | /////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | LookupContext::LookupContext(Control *control) | 
					
						
							|  |  |  |     : _control(control), | 
					
						
							|  |  |  |       _symbol(0) | 
					
						
							|  |  |  | { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | LookupContext::LookupContext(Symbol *symbol, | 
					
						
							|  |  |  |                              Document::Ptr expressionDocument, | 
					
						
							|  |  |  |                              Document::Ptr thisDocument, | 
					
						
							| 
									
										
										
										
											2009-05-28 11:49:59 +02:00
										 |  |  |                              const Snapshot &snapshot) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     : _symbol(symbol), | 
					
						
							|  |  |  |       _expressionDocument(expressionDocument), | 
					
						
							|  |  |  |       _thisDocument(thisDocument), | 
					
						
							| 
									
										
										
										
											2009-05-28 11:49:59 +02:00
										 |  |  |       _snapshot(snapshot) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     _control = _expressionDocument->control(); | 
					
						
							|  |  |  |     _visibleScopes = buildVisibleScopes(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool LookupContext::isValid() const | 
					
						
							|  |  |  | { return _control != 0; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Control *LookupContext::control() const | 
					
						
							|  |  |  | { return _control; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Symbol *LookupContext::symbol() const | 
					
						
							|  |  |  | { return _symbol; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Document::Ptr LookupContext::expressionDocument() const | 
					
						
							|  |  |  | { return _expressionDocument; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Document::Ptr LookupContext::thisDocument() const | 
					
						
							|  |  |  | { return _thisDocument; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Document::Ptr LookupContext::document(const QString &fileName) const | 
					
						
							| 
									
										
										
										
											2009-05-28 11:49:59 +02:00
										 |  |  | { return _snapshot.value(fileName); } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 11:49:59 +02:00
										 |  |  | Snapshot LookupContext::snapshot() const | 
					
						
							|  |  |  | { return _snapshot; } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-13 09:41:07 +01:00
										 |  |  | bool LookupContext::maybeValidSymbol(Symbol *symbol, | 
					
						
							|  |  |  |                                      ResolveMode mode, | 
					
						
							|  |  |  |                                      const QList<Symbol *> &candidates) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (((mode & ResolveNamespace) && symbol->isNamespace()) || | 
					
						
							|  |  |  |         ((mode & ResolveClass)     && symbol->isClass())     || | 
					
						
							|  |  |  |          (mode & ResolveSymbol)) { | 
					
						
							|  |  |  |         return ! candidates.contains(symbol); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 12:39:18 +02:00
										 |  |  | QList<Scope *> LookupContext::resolveNestedNameSpecifier(QualifiedNameId *q, | 
					
						
							|  |  |  |                                                           const QList<Scope *> &visibleScopes) const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-11 10:31:38 +01:00
										 |  |  |     QList<Symbol *> candidates; | 
					
						
							| 
									
										
										
										
											2009-05-28 12:39:18 +02:00
										 |  |  |     QList<Scope *> scopes = visibleScopes; | 
					
						
							| 
									
										
										
										
											2009-02-11 10:31:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 12:39:18 +02:00
										 |  |  |     for (unsigned i = 0; i < q->nameCount() - 1; ++i) { | 
					
						
							| 
									
										
										
										
											2009-05-28 11:58:40 +02:00
										 |  |  |         Name *name = q->nameAt(i); | 
					
						
							| 
									
										
										
										
											2009-01-13 09:41:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 12:39:18 +02:00
										 |  |  |         candidates = resolveClassOrNamespace(name, scopes); | 
					
						
							| 
									
										
										
										
											2009-01-24 23:07:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 12:39:18 +02:00
										 |  |  |         if (candidates.isEmpty()) | 
					
						
							| 
									
										
										
										
											2009-05-28 11:58:40 +02:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-01-24 23:07:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 11:58:40 +02:00
										 |  |  |         scopes.clear(); | 
					
						
							| 
									
										
										
										
											2009-05-28 12:39:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 11:58:40 +02:00
										 |  |  |         foreach (Symbol *candidate, candidates) { | 
					
						
							| 
									
										
										
										
											2009-05-28 12:39:18 +02:00
										 |  |  |             ScopedSymbol *scoped = candidate->asScopedSymbol(); | 
					
						
							|  |  |  |             Scope *members = scoped->members(); | 
					
						
							| 
									
										
										
										
											2009-01-24 23:07:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 12:39:18 +02:00
										 |  |  |             if (! scopes.contains(members)) | 
					
						
							|  |  |  |                 scopes.append(members); | 
					
						
							| 
									
										
										
										
											2009-01-13 09:41:07 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-05-28 11:58:40 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 12:39:18 +02:00
										 |  |  |     return scopes; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QList<Symbol *> LookupContext::resolveQualifiedNameId(QualifiedNameId *q, | 
					
						
							|  |  |  |                                                       const QList<Scope *> &visibleScopes, | 
					
						
							|  |  |  |                                                       ResolveMode mode) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QList<Scope *> scopes; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (q->nameCount() == 1) | 
					
						
							|  |  |  |         scopes = visibleScopes;     // ### handle global scope lookup
 | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         scopes = resolveNestedNameSpecifier(q, visibleScopes); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-04 16:15:27 +02:00
										 |  |  |     QList<Scope *> expanded; | 
					
						
							|  |  |  |     foreach (Scope *scope, scopes) { | 
					
						
							|  |  |  |         expanded.append(scope); | 
					
						
							| 
									
										
										
										
											2009-05-28 12:39:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-04 16:15:27 +02:00
										 |  |  |         for (unsigned i = 0; i < scope->symbolCount(); ++i) { | 
					
						
							|  |  |  |             Symbol *member = scope->symbolAt(i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (ScopedSymbol *scopedSymbol = member->asScopedSymbol()) | 
					
						
							|  |  |  |                 expandEnumOrAnonymousSymbol(scopedSymbol, &expanded); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return resolve(q->unqualifiedNameId(), expanded, mode); | 
					
						
							| 
									
										
										
										
											2009-05-28 11:58:40 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-01-13 09:41:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 12:10:16 +02:00
										 |  |  | QList<Symbol *> LookupContext::resolveOperatorNameId(OperatorNameId *opId, | 
					
						
							|  |  |  |                                                      const QList<Scope *> &visibleScopes, | 
					
						
							|  |  |  |                                                      ResolveMode) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QList<Symbol *> candidates; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int scopeIndex = 0; scopeIndex < visibleScopes.size(); ++scopeIndex) { | 
					
						
							|  |  |  |         Scope *scope = visibleScopes.at(scopeIndex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (Symbol *symbol = scope->lookat(opId->kind()); symbol; symbol = symbol->next()) { | 
					
						
							|  |  |  |             if (! opId->isEqualTo(symbol->name())) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (! candidates.contains(symbol)) | 
					
						
							|  |  |  |                 candidates.append(symbol); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return candidates; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 11:58:40 +02:00
										 |  |  | QList<Symbol *> LookupContext::resolve(Name *name, const QList<Scope *> &visibleScopes, | 
					
						
							|  |  |  |                                        ResolveMode mode) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QList<Symbol *> candidates; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!name) | 
					
						
							| 
									
										
										
										
											2009-05-28 12:10:16 +02:00
										 |  |  |         return candidates; // nothing to do, the symbol is anonymous.
 | 
					
						
							| 
									
										
										
										
											2009-05-28 11:58:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 12:10:16 +02:00
										 |  |  |     else if (QualifiedNameId *q = name->asQualifiedNameId()) | 
					
						
							| 
									
										
										
										
											2009-05-28 11:58:40 +02:00
										 |  |  |         return resolveQualifiedNameId(q, visibleScopes, mode); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 12:10:16 +02:00
										 |  |  |     else if (OperatorNameId *opId = name->asOperatorNameId()) | 
					
						
							|  |  |  |         return resolveOperatorNameId(opId, visibleScopes, mode); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 15:24:17 +02:00
										 |  |  |     else if (Identifier *id = name->identifier()) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         for (int scopeIndex = 0; scopeIndex < visibleScopes.size(); ++scopeIndex) { | 
					
						
							|  |  |  |             Scope *scope = visibleScopes.at(scopeIndex); | 
					
						
							| 
									
										
										
										
											2009-05-28 12:10:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             for (Symbol *symbol = scope->lookat(id); symbol; symbol = symbol->next()) { | 
					
						
							| 
									
										
										
										
											2009-05-28 15:24:17 +02:00
										 |  |  |                 if (! symbol->name()) | 
					
						
							|  |  |  |                     continue; // nothing to do, the symbol is anonymous.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 else if (! maybeValidSymbol(symbol, mode, candidates)) | 
					
						
							|  |  |  |                     continue; // skip it, we're not looking for this kind of symbols
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 else if (Identifier *symbolId = symbol->identifier()) { | 
					
						
							|  |  |  |                     if (! symbolId->isEqualTo(id)) | 
					
						
							|  |  |  |                         continue; // skip it, the symbol's id is not compatible with this lookup.
 | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (QualifiedNameId *q = symbol->name()->asQualifiedNameId()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (name->isDestructorNameId() != q->unqualifiedNameId()->isDestructorNameId()) | 
					
						
							| 
									
										
										
										
											2009-01-13 09:41:07 +01:00
										 |  |  |                         continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 15:24:17 +02:00
										 |  |  |                     else if (q->nameCount() > 1) { | 
					
						
							| 
									
										
										
										
											2009-04-06 16:48:43 +02:00
										 |  |  |                         Name *classOrNamespaceName = control()->qualifiedNameId(q->names(), | 
					
						
							|  |  |  |                                                                                 q->nameCount() - 1); | 
					
						
							| 
									
										
										
										
											2009-03-25 12:28:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-06 16:48:43 +02:00
										 |  |  |                         if (Identifier *classOrNamespaceNameId = identifier(classOrNamespaceName)) { | 
					
						
							|  |  |  |                             if (classOrNamespaceNameId->isEqualTo(id)) | 
					
						
							|  |  |  |                                 continue; | 
					
						
							|  |  |  |                         } | 
					
						
							| 
									
										
										
										
											2009-01-13 09:41:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                         const QList<Symbol *> resolvedClassOrNamespace = | 
					
						
							|  |  |  |                                 resolveClassOrNamespace(classOrNamespaceName, visibleScopes); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         bool good = false; | 
					
						
							|  |  |  |                         foreach (Symbol *classOrNamespace, resolvedClassOrNamespace) { | 
					
						
							|  |  |  |                             ScopedSymbol *scoped = classOrNamespace->asScopedSymbol(); | 
					
						
							|  |  |  |                             if (visibleScopes.contains(scoped->members())) { | 
					
						
							|  |  |  |                                 good = true; | 
					
						
							|  |  |  |                                 break; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         if (! good) | 
					
						
							|  |  |  |                             continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } else if (symbol->name()->isDestructorNameId() != name->isDestructorNameId()) { | 
					
						
							| 
									
										
										
										
											2009-05-28 15:24:17 +02:00
										 |  |  |                     // ### FIXME: this is wrong!
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2009-01-13 09:41:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 15:24:17 +02:00
										 |  |  |                 if (! candidates.contains(symbol)) | 
					
						
							|  |  |  |                     candidates.append(symbol); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return candidates; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-28 11:49:59 +02:00
										 |  |  | Identifier *LookupContext::identifier(const Name *name) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (name) | 
					
						
							|  |  |  |         return name->identifier(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-19 14:15:56 +02:00
										 |  |  | void LookupContext::buildVisibleScopes_helper(Document::Ptr doc, QList<Scope *> *scopes, | 
					
						
							|  |  |  |                                               QSet<QString> *processed) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (doc && ! processed->contains(doc->fileName())) { | 
					
						
							|  |  |  |         processed->insert(doc->fileName()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (doc->globalSymbolCount()) | 
					
						
							|  |  |  |             scopes->append(doc->globalSymbols()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach (const Document::Include &incl, doc->includes()) { | 
					
						
							| 
									
										
										
										
											2009-05-28 11:49:59 +02:00
										 |  |  |             buildVisibleScopes_helper(_snapshot.value(incl.fileName()), | 
					
						
							| 
									
										
										
										
											2009-05-19 14:15:56 +02:00
										 |  |  |                                       scopes, processed); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | QList<Scope *> LookupContext::buildVisibleScopes() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QList<Scope *> scopes; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (_symbol) { | 
					
						
							|  |  |  |         for (Scope *scope = _symbol->scope(); scope; scope = scope->enclosingScope()) { | 
					
						
							| 
									
										
										
										
											2009-05-19 14:15:56 +02:00
										 |  |  |             if (scope == _thisDocument->globalSymbols()) | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             scopes.append(scope); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QSet<QString> processed; | 
					
						
							| 
									
										
										
										
											2009-05-19 14:15:56 +02:00
										 |  |  |     buildVisibleScopes_helper(_thisDocument, &scopes, &processed); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     while (true) { | 
					
						
							|  |  |  |         QList<Scope *> expandedScopes; | 
					
						
							|  |  |  |         expand(scopes, &expandedScopes); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (expandedScopes.size() == scopes.size()) | 
					
						
							|  |  |  |             return expandedScopes; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         scopes = expandedScopes; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return scopes; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QList<Scope *> LookupContext::visibleScopes(const QPair<FullySpecifiedType, Symbol *> &result) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Symbol *symbol = result.second; | 
					
						
							|  |  |  |     QList<Scope *> scopes; | 
					
						
							|  |  |  |     for (Scope *scope = symbol->scope(); scope; scope = scope->enclosingScope()) | 
					
						
							|  |  |  |         scopes.append(scope); | 
					
						
							|  |  |  |     scopes += visibleScopes(); | 
					
						
							|  |  |  |     scopes = expand(scopes); | 
					
						
							|  |  |  |     return scopes; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-04 16:15:27 +02:00
										 |  |  | void LookupContext::expandEnumOrAnonymousSymbol(ScopedSymbol *scopedSymbol, | 
					
						
							|  |  |  |                                                 QList<Scope *> *expandedScopes) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (! scopedSymbol || expandedScopes->contains(scopedSymbol->members())) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Scope *members = scopedSymbol->members(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (scopedSymbol->isEnum()) | 
					
						
							|  |  |  |         expandedScopes->append(members); | 
					
						
							|  |  |  |     else if (! scopedSymbol->name() && (scopedSymbol->isClass() || scopedSymbol->isNamespace())) { | 
					
						
							|  |  |  |         // anonymous class or namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expandedScopes->append(members); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (unsigned i = 0; i < members->symbolCount(); ++i) { | 
					
						
							|  |  |  |             Symbol *member = members->symbolAt(i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (ScopedSymbol *nested = member->asScopedSymbol()) { | 
					
						
							|  |  |  |                 expandEnumOrAnonymousSymbol(nested, expandedScopes); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | QList<Scope *> LookupContext::expand(const QList<Scope *> &scopes) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QList<Scope *> expanded; | 
					
						
							|  |  |  |     expand(scopes, &expanded); | 
					
						
							|  |  |  |     return expanded; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void LookupContext::expand(const QList<Scope *> &scopes, QList<Scope *> *expandedScopes) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     for (int i = 0; i < scopes.size(); ++i) { | 
					
						
							|  |  |  |         expand(scopes.at(i), scopes, expandedScopes); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-27 15:48:35 +02:00
										 |  |  | void LookupContext::expandNamespace(Namespace *ns, | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |                                     const QList<Scope *> &visibleScopes, | 
					
						
							|  |  |  |                                     QList<Scope *> *expandedScopes) const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |     if (Name *nsName = ns->name()) { | 
					
						
							|  |  |  |         const QList<Symbol *> namespaceList = resolveNamespace(nsName, visibleScopes); | 
					
						
							|  |  |  |         foreach (Symbol *otherNs, namespaceList) { | 
					
						
							|  |  |  |             if (otherNs == ns) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             expand(otherNs->asNamespace()->members(), visibleScopes, expandedScopes); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-27 15:48:35 +02:00
										 |  |  |     for (unsigned i = 0; i < ns->memberCount(); ++i) { // ### make me fast
 | 
					
						
							|  |  |  |         Symbol *symbol = ns->memberAt(i); | 
					
						
							|  |  |  |         if (Namespace *otherNs = symbol->asNamespace()) { | 
					
						
							|  |  |  |             if (! otherNs->name()) { | 
					
						
							| 
									
										
										
										
											2009-06-10 11:31:00 +02:00
										 |  |  |                 expand(otherNs->members(), visibleScopes, expandedScopes); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |         } else if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) { | 
					
						
							|  |  |  |             const QList<Symbol *> candidates = resolveNamespace(u->name(), visibleScopes); | 
					
						
							|  |  |  |             for (int j = 0; j < candidates.size(); ++j) { | 
					
						
							|  |  |  |                 expand(candidates.at(j)->asNamespace()->members(), | 
					
						
							|  |  |  |                        visibleScopes, expandedScopes); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |         } else if (Enum *e = symbol->asEnum()) { | 
					
						
							|  |  |  |             expand(e->members(), visibleScopes, expandedScopes); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-27 15:48:35 +02:00
										 |  |  | void LookupContext::expandClass(Class *klass, | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |                                 const QList<Scope *> &visibleScopes, | 
					
						
							|  |  |  |                                 QList<Scope *> *expandedScopes) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-27 15:48:35 +02:00
										 |  |  |     for (unsigned i = 0; i < klass->memberCount(); ++i) { | 
					
						
							|  |  |  |         Symbol *symbol = klass->memberAt(i); | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |         if (Class *nestedClass = symbol->asClass()) { | 
					
						
							|  |  |  |             if (! nestedClass->name()) { | 
					
						
							|  |  |  |                 expand(nestedClass->members(), visibleScopes, expandedScopes); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |         } else if (Enum *e = symbol->asEnum()) { | 
					
						
							|  |  |  |             expand(e->members(), visibleScopes, expandedScopes); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |     if (klass->baseClassCount()) { | 
					
						
							|  |  |  |         QList<Scope *> classVisibleScopes = visibleScopes; | 
					
						
							|  |  |  |         for (Scope *scope = klass->scope(); scope; scope = scope->enclosingScope()) { | 
					
						
							|  |  |  |             if (scope->isNamespaceScope()) { | 
					
						
							|  |  |  |                 Namespace *enclosingNamespace = scope->owner()->asNamespace(); | 
					
						
							|  |  |  |                 if (enclosingNamespace->name()) { | 
					
						
							|  |  |  |                     const QList<Symbol *> nsList = resolveNamespace(enclosingNamespace->name(), | 
					
						
							|  |  |  |                                                                     visibleScopes); | 
					
						
							|  |  |  |                     foreach (Symbol *ns, nsList) { | 
					
						
							|  |  |  |                         expand(ns->asNamespace()->members(), classVisibleScopes, | 
					
						
							|  |  |  |                                &classVisibleScopes); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for (unsigned i = 0; i < klass->baseClassCount(); ++i) { | 
					
						
							|  |  |  |             BaseClass *baseClass = klass->baseClassAt(i); | 
					
						
							|  |  |  |             Name *baseClassName = baseClass->name(); | 
					
						
							|  |  |  |             const QList<Symbol *> baseClassCandidates = resolveClass(baseClassName, | 
					
						
							|  |  |  |                                                                      classVisibleScopes); | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |             for (int j = 0; j < baseClassCandidates.size(); ++j) { | 
					
						
							| 
									
										
										
										
											2009-01-13 10:30:48 +01:00
										 |  |  |                 if (Class *baseClassSymbol = baseClassCandidates.at(j)->asClass()) | 
					
						
							|  |  |  |                     expand(baseClassSymbol->members(), visibleScopes, expandedScopes); | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-27 15:48:35 +02:00
										 |  |  | void LookupContext::expandBlock(Block *blockSymbol, | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |                                 const QList<Scope *> &visibleScopes, | 
					
						
							|  |  |  |                                 QList<Scope *> *expandedScopes) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-27 15:48:35 +02:00
										 |  |  |     for (unsigned i = 0; i < blockSymbol->memberCount(); ++i) { | 
					
						
							|  |  |  |         Symbol *symbol = blockSymbol->memberAt(i); | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |         if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) { | 
					
						
							|  |  |  |             const QList<Symbol *> candidates = resolveNamespace(u->name(), | 
					
						
							|  |  |  |                                                                 visibleScopes); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             for (int j = 0; j < candidates.size(); ++j) { | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |                 expand(candidates.at(j)->asNamespace()->members(), | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                        visibleScopes, expandedScopes); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-27 15:48:35 +02:00
										 |  |  | void LookupContext::expandFunction(Function *function, | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |                                    const QList<Scope *> &visibleScopes, | 
					
						
							|  |  |  |                                    QList<Scope *> *expandedScopes) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (! expandedScopes->contains(function->arguments())) | 
					
						
							|  |  |  |         expandedScopes->append(function->arguments()); | 
					
						
							| 
									
										
										
										
											2009-05-27 15:48:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |     if (QualifiedNameId *q = function->name()->asQualifiedNameId()) { | 
					
						
							|  |  |  |         Name *nestedNameSpec = 0; | 
					
						
							| 
									
										
										
										
											2009-04-06 16:48:43 +02:00
										 |  |  |         if (q->nameCount() == 1) | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  |             nestedNameSpec = q->nameAt(0); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             nestedNameSpec = control()->qualifiedNameId(q->names(), q->nameCount() - 1, | 
					
						
							|  |  |  |                                                         q->isGlobal()); | 
					
						
							|  |  |  |         const QList<Symbol *> candidates = resolveClassOrNamespace(nestedNameSpec, visibleScopes); | 
					
						
							|  |  |  |         for (int j = 0; j < candidates.size(); ++j) { | 
					
						
							|  |  |  |             expand(candidates.at(j)->asScopedSymbol()->members(), | 
					
						
							|  |  |  |                    visibleScopes, expandedScopes); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 12:08:38 +02:00
										 |  |  | void LookupContext::expandObjCMethod(ObjCMethod *method, | 
					
						
							| 
									
										
										
										
											2009-09-25 14:19:43 +02:00
										 |  |  |                                      const QList<Scope *> &, | 
					
						
							| 
									
										
										
										
											2009-09-25 12:08:38 +02:00
										 |  |  |                                      QList<Scope *> *expandedScopes) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (! expandedScopes->contains(method->arguments())) | 
					
						
							|  |  |  |         expandedScopes->append(method->arguments()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 13:27:01 +01:00
										 |  |  | void LookupContext::expand(Scope *scope, | 
					
						
							|  |  |  |                            const QList<Scope *> &visibleScopes, | 
					
						
							|  |  |  |                            QList<Scope *> *expandedScopes) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (expandedScopes->contains(scope)) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expandedScopes->append(scope); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-27 15:48:35 +02:00
										 |  |  |     if (Namespace *ns = scope->owner()->asNamespace()) { | 
					
						
							|  |  |  |         expandNamespace(ns, visibleScopes, expandedScopes); | 
					
						
							|  |  |  |     } else if (Class *klass = scope->owner()->asClass()) { | 
					
						
							|  |  |  |         expandClass(klass, visibleScopes, expandedScopes); | 
					
						
							|  |  |  |     } else if (Block *block = scope->owner()->asBlock()) { | 
					
						
							|  |  |  |         expandBlock(block, visibleScopes, expandedScopes); | 
					
						
							|  |  |  |     } else if (Function *fun = scope->owner()->asFunction()) { | 
					
						
							|  |  |  |         expandFunction(fun, visibleScopes, expandedScopes); | 
					
						
							| 
									
										
										
										
											2009-09-25 12:08:38 +02:00
										 |  |  |     } else if (ObjCMethod *meth = scope->owner()->asObjCMethod()) { | 
					
						
							|  |  |  |         expandObjCMethod(meth, visibleScopes, expandedScopes); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-09-25 14:00:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | Symbol *LookupContext::canonicalSymbol(Symbol *symbol) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Symbol *canonical = symbol; | 
					
						
							|  |  |  |     for (; symbol; symbol = symbol->next()) { | 
					
						
							|  |  |  |         if (symbol->name() == canonical->name()) | 
					
						
							|  |  |  |             canonical = symbol; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return canonical; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Symbol *LookupContext::canonicalSymbol(const QList<Symbol *> &candidates) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (candidates.isEmpty()) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Symbol *candidate = candidates.first(); | 
					
						
							|  |  |  |     if (candidate->scope()->isClassScope() && candidate->type()->isFunctionType()) { | 
					
						
							|  |  |  |         Function *function = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (int i = 0; i < candidates.size(); ++i) { | 
					
						
							|  |  |  |             Symbol *c = candidates.at(i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (! c->scope()->isClassScope()) | 
					
						
							| 
									
										
										
										
											2009-09-25 14:19:43 +02:00
										 |  |  |                 continue;  | 
					
						
							| 
									
										
										
										
											2009-09-25 14:00:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             else if (Function *f = c->type()->asFunctionType()) { | 
					
						
							|  |  |  |                 if (f->isVirtual()) | 
					
						
							|  |  |  |                     function = f; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (function) | 
					
						
							|  |  |  |             return canonicalSymbol(function); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return canonicalSymbol(candidate); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-09-25 14:19:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | Symbol *LookupContext::canonicalSymbol(const QList<QPair<FullySpecifiedType, Symbol *> > &results) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QList<Symbol *> candidates; | 
					
						
							|  |  |  |     QPair<FullySpecifiedType, Symbol *> result; | 
					
						
							|  |  |  |     foreach (result, results) { | 
					
						
							|  |  |  |         candidates.append(result.second); // ### not exacly.
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return canonicalSymbol(candidates); | 
					
						
							|  |  |  | } |