| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | /**************************************************************************
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-01-11 16:28:15 +01:00
										 |  |  | ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** Contact: Nokia Corporation (info@qt.nokia.com) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											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
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** 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
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2010-12-17 16:01:08 +01:00
										 |  |  | ** In addition, as a special exception, Nokia gives you certain additional | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** rights. These rights are described in the Nokia Qt LGPL Exception | 
					
						
							| 
									
										
										
										
											2010-12-17 16:01:08 +01:00
										 |  |  | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** Other Usage | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** Alternatively, this file may be used in accordance with the terms and | 
					
						
							|  |  |  | ** conditions contained in a signed written agreement between you and Nokia. | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2010-12-17 16:01:08 +01:00
										 |  |  | ** If you have questions regarding the use of this file, please contact | 
					
						
							| 
									
										
										
										
											2011-05-06 15:05:37 +02:00
										 |  |  | ** Nokia at info@qt.nokia.com. | 
					
						
							| 
									
										
										
										
											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 "CppDocument.h"
 | 
					
						
							| 
									
										
										
										
											2009-06-03 16:16:20 +02:00
										 |  |  | #include "FastPreprocessor.h"
 | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  | #include "LookupContext.h"
 | 
					
						
							|  |  |  | #include "Overview.h"
 | 
					
						
							| 
									
										
										
										
											2010-08-13 15:28:22 +02:00
										 |  |  | #include "Bind.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <Control.h>
 | 
					
						
							|  |  |  | #include <TranslationUnit.h>
 | 
					
						
							|  |  |  | #include <DiagnosticClient.h>
 | 
					
						
							|  |  |  | #include <Literals.h>
 | 
					
						
							|  |  |  | #include <Symbols.h>
 | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  | #include <Names.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <AST.h>
 | 
					
						
							| 
									
										
										
										
											2011-01-05 12:19:09 +01:00
										 |  |  | #include <ASTPatternBuilder.h>
 | 
					
						
							|  |  |  | #include <ASTMatcher.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <Scope.h>
 | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  | #include <SymbolVisitor.h>
 | 
					
						
							| 
									
										
										
										
											2010-12-10 10:32:46 +01:00
										 |  |  | #include <NameVisitor.h>
 | 
					
						
							|  |  |  | #include <TypeVisitor.h>
 | 
					
						
							|  |  |  | #include <CoreTypes.h>
 | 
					
						
							| 
									
										
										
										
											2011-08-10 09:50:04 +02:00
										 |  |  | #include <LookupContext.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-29 10:16:48 +02:00
										 |  |  | #include <QtCore/QByteArray>
 | 
					
						
							|  |  |  | #include <QtCore/QBitArray>
 | 
					
						
							| 
									
										
										
										
											2009-11-09 13:53:28 +01:00
										 |  |  | #include <QtCore/QDir>
 | 
					
						
							| 
									
										
										
										
											2009-07-29 10:16:48 +02:00
										 |  |  | #include <QtCore/QtDebug>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |     \namespace CPlusPlus | 
					
						
							|  |  |  |     The namespace for C++ related tools. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | using namespace CPlusPlus; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-17 13:42:04 +02:00
										 |  |  | class LastVisibleSymbolAt: protected SymbolVisitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Symbol *root; | 
					
						
							|  |  |  |     unsigned line; | 
					
						
							|  |  |  |     unsigned column; | 
					
						
							|  |  |  |     Symbol *symbol; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     LastVisibleSymbolAt(Symbol *root) | 
					
						
							|  |  |  |         : root(root), line(0), column(0), symbol(0) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Symbol *operator()(unsigned line, unsigned column) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         this->line = line; | 
					
						
							|  |  |  |         this->column = column; | 
					
						
							|  |  |  |         this->symbol = 0; | 
					
						
							|  |  |  |         accept(root); | 
					
						
							|  |  |  |         if (! symbol) | 
					
						
							|  |  |  |             symbol = root; | 
					
						
							|  |  |  |         return symbol; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     bool preVisit(Symbol *s) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (s->asBlock()) { | 
					
						
							|  |  |  |             if (s->line() < line || (s->line() == line && s->column() <= column)) { | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             // skip blocks
 | 
					
						
							|  |  |  |         } if (s->line() < line || (s->line() == line && s->column() <= column)) { | 
					
						
							|  |  |  |             symbol = s; | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-12 12:53:16 +02:00
										 |  |  | class FindScopeAt: protected SymbolVisitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     TranslationUnit *_unit; | 
					
						
							|  |  |  |     unsigned _line; | 
					
						
							|  |  |  |     unsigned _column; | 
					
						
							|  |  |  |     Scope *_scope; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2010-07-16 15:24:42 +02:00
										 |  |  |     /** line and column should be 1-based */ | 
					
						
							| 
									
										
										
										
											2010-05-12 12:53:16 +02:00
										 |  |  |     FindScopeAt(TranslationUnit *unit, unsigned line, unsigned column) | 
					
						
							|  |  |  |         : _unit(unit), _line(line), _column(column), _scope(0) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Scope *operator()(Symbol *symbol) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         accept(symbol); | 
					
						
							|  |  |  |         return _scope; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |     bool process(Scope *symbol) | 
					
						
							| 
									
										
										
										
											2010-05-12 12:53:16 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         if (! _scope) { | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |             Scope *scope = symbol; | 
					
						
							| 
									
										
										
										
											2010-05-12 12:53:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |             for (unsigned i = 0; i < scope->memberCount(); ++i) { | 
					
						
							|  |  |  |                 accept(scope->memberAt(i)); | 
					
						
							| 
									
										
										
										
											2010-05-12 12:53:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 if (_scope) | 
					
						
							|  |  |  |                     return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             unsigned startLine, startColumn; | 
					
						
							| 
									
										
										
										
											2010-07-19 10:42:07 +02:00
										 |  |  |             _unit->getPosition(scope->startOffset(), &startLine, &startColumn); | 
					
						
							| 
									
										
										
										
											2010-05-12 12:53:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (_line > startLine || (_line == startLine && _column >= startColumn)) { | 
					
						
							|  |  |  |                 unsigned endLine, endColumn; | 
					
						
							| 
									
										
										
										
											2010-07-19 10:42:07 +02:00
										 |  |  |                 _unit->getPosition(scope->endOffset(), &endLine, &endColumn); | 
					
						
							| 
									
										
										
										
											2010-05-12 12:53:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-10 12:16:25 +02:00
										 |  |  |                 if (_line < endLine || (_line == endLine && _column < endColumn)) | 
					
						
							| 
									
										
										
										
											2010-05-12 12:53:16 +02:00
										 |  |  |                     _scope = scope; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     using SymbolVisitor::visit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool preVisit(Symbol *) | 
					
						
							|  |  |  |     { return ! _scope; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool visit(UsingNamespaceDirective *) { return false; } | 
					
						
							|  |  |  |     virtual bool visit(UsingDeclaration *) { return false; } | 
					
						
							|  |  |  |     virtual bool visit(NamespaceAlias *) { return false; } | 
					
						
							|  |  |  |     virtual bool visit(Declaration *) { return false; } | 
					
						
							|  |  |  |     virtual bool visit(Argument *) { return false; } | 
					
						
							|  |  |  |     virtual bool visit(TypenameArgument *) { return false; } | 
					
						
							|  |  |  |     virtual bool visit(BaseClass *) { return false; } | 
					
						
							|  |  |  |     virtual bool visit(ForwardClassDeclaration *) { return false; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool visit(Enum *symbol) | 
					
						
							|  |  |  |     { return process(symbol); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool visit(Function *symbol) | 
					
						
							|  |  |  |     { return process(symbol); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool visit(Namespace *symbol) | 
					
						
							|  |  |  |     { return process(symbol); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool visit(Class *symbol) | 
					
						
							|  |  |  |     { return process(symbol); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool visit(Block *symbol) | 
					
						
							|  |  |  |     { return process(symbol); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Objective-C
 | 
					
						
							|  |  |  |     virtual bool visit(ObjCBaseClass *) { return false; } | 
					
						
							|  |  |  |     virtual bool visit(ObjCBaseProtocol *) { return false; } | 
					
						
							|  |  |  |     virtual bool visit(ObjCForwardClassDeclaration *) { return false; } | 
					
						
							|  |  |  |     virtual bool visit(ObjCForwardProtocolDeclaration *) { return false; } | 
					
						
							|  |  |  |     virtual bool visit(ObjCPropertyDeclaration *) { return false; } | 
					
						
							| 
									
										
										
										
											2010-05-20 16:07:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     virtual bool visit(ObjCClass *symbol) | 
					
						
							|  |  |  |     { return process(symbol); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool visit(ObjCProtocol *symbol) | 
					
						
							|  |  |  |     { return process(symbol); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool visit(ObjCMethod *symbol) | 
					
						
							|  |  |  |     { return process(symbol); } | 
					
						
							| 
									
										
										
										
											2010-05-12 12:53:16 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-03 18:41:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | class DocumentDiagnosticClient : public DiagnosticClient | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     enum { MAX_MESSAGE_COUNT = 10 }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     DocumentDiagnosticClient(Document *doc, QList<Document::DiagnosticMessage> *messages) | 
					
						
							|  |  |  |         : doc(doc), | 
					
						
							| 
									
										
										
										
											2009-06-04 11:42:02 +02:00
										 |  |  |           messages(messages), | 
					
						
							|  |  |  |           errorCount(0) | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  |     { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void report(int level, | 
					
						
							| 
									
										
										
										
											2009-12-01 11:33:13 +01:00
										 |  |  |                         const StringLiteral *fileId, | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  |                         unsigned line, unsigned column, | 
					
						
							|  |  |  |                         const char *format, va_list ap) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-06-04 11:42:02 +02:00
										 |  |  |         if (level == Error) { | 
					
						
							|  |  |  |             ++errorCount; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (errorCount >= MAX_MESSAGE_COUNT) | 
					
						
							|  |  |  |                 return; // ignore the error
 | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  |         const QString fileName = QString::fromUtf8(fileId->chars(), fileId->size()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  |         if (fileName != doc->fileName()) | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  |         QString message; | 
					
						
							|  |  |  |         message.vsprintf(format, ap); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  |         Document::DiagnosticMessage m(convertLevel(level), doc->fileName(), | 
					
						
							|  |  |  |                                       line, column, message); | 
					
						
							|  |  |  |         messages->append(m); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  |     static int convertLevel(int level) { | 
					
						
							|  |  |  |         switch (level) { | 
					
						
							|  |  |  |             case Warning: return Document::DiagnosticMessage::Warning; | 
					
						
							|  |  |  |             case Error:   return Document::DiagnosticMessage::Error; | 
					
						
							|  |  |  |             case Fatal:   return Document::DiagnosticMessage::Fatal; | 
					
						
							|  |  |  |             default:      return Document::DiagnosticMessage::Error; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-04 11:42:02 +02:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  |     Document *doc; | 
					
						
							|  |  |  |     QList<Document::DiagnosticMessage> *messages; | 
					
						
							| 
									
										
										
										
											2009-06-04 11:42:02 +02:00
										 |  |  |     int errorCount; | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | } // anonymous namespace
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | Document::Document(const QString &fileName) | 
					
						
							| 
									
										
										
										
											2009-11-09 13:53:28 +01:00
										 |  |  |     : _fileName(QDir::cleanPath(fileName)), | 
					
						
							| 
									
										
										
										
											2009-07-14 14:23:12 +02:00
										 |  |  |       _globalNamespace(0), | 
					
						
							| 
									
										
										
										
											2009-12-15 15:52:55 +01:00
										 |  |  |       _revision(0), | 
					
						
							|  |  |  |       _editorRevision(0) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     _control = new Control(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _control->setDiagnosticClient(new DocumentDiagnosticClient(this, &_diagnosticMessages)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QByteArray localFileName = fileName.toUtf8(); | 
					
						
							| 
									
										
										
										
											2010-08-11 14:24:28 +02:00
										 |  |  |     const StringLiteral *fileId = _control->stringLiteral(localFileName.constData(), | 
					
						
							| 
									
										
										
										
											2009-12-01 11:33:13 +01:00
										 |  |  |                                                                       localFileName.size()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     _translationUnit = new TranslationUnit(_control, fileId); | 
					
						
							|  |  |  |     _translationUnit->setQtMocRunEnabled(true); | 
					
						
							| 
									
										
										
										
											2010-05-21 10:51:48 +02:00
										 |  |  |     _translationUnit->setCxxOxEnabled(true); | 
					
						
							| 
									
										
										
										
											2009-02-04 11:36:17 +01:00
										 |  |  |     _translationUnit->setObjCEnabled(true); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     (void) _control->switchTranslationUnit(_translationUnit); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Document::~Document() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     delete _translationUnit; | 
					
						
							|  |  |  |     delete _control->diagnosticClient(); | 
					
						
							|  |  |  |     delete _control; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Control *Document::control() const | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return _control; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-14 14:23:12 +02:00
										 |  |  | unsigned Document::revision() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _revision; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Document::setRevision(unsigned revision) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _revision = revision; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 15:52:55 +01:00
										 |  |  | unsigned Document::editorRevision() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _editorRevision; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Document::setEditorRevision(unsigned editorRevision) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _editorRevision = editorRevision; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 12:34:02 +01:00
										 |  |  | QDateTime Document::lastModified() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _lastModified; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Document::setLastModified(const QDateTime &lastModified) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _lastModified = lastModified; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | QString Document::fileName() const | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return _fileName; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | QStringList Document::includedFiles() const | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-10 17:21:01 +01:00
										 |  |  |     QStringList files; | 
					
						
							|  |  |  |     foreach (const Include &i, _includes) | 
					
						
							|  |  |  |         files.append(i.fileName()); | 
					
						
							|  |  |  |     files.removeDuplicates(); | 
					
						
							|  |  |  |     return files; | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-10 17:21:01 +01:00
										 |  |  | void Document::addIncludeFile(const QString &fileName, unsigned line) | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-09 13:53:28 +01:00
										 |  |  |     _includes.append(Include(QDir::cleanPath(fileName), line)); | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-08 12:59:33 +01:00
										 |  |  | void Document::appendMacro(const Macro ¯o) | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-08 12:59:33 +01:00
										 |  |  |     _definedMacros.append(macro); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 11:47:30 +01:00
										 |  |  | void Document::addMacroUse(const Macro ¯o, unsigned offset, unsigned length, | 
					
						
							| 
									
										
										
										
											2009-12-21 14:47:22 +01:00
										 |  |  |                            unsigned beginLine, | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  |                            const QVector<MacroArgumentReference> &actuals, bool inCondition) | 
					
						
							| 
									
										
										
										
											2008-12-04 12:05:04 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-21 14:47:22 +01:00
										 |  |  |     MacroUse use(macro, offset, offset + length, beginLine); | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  |     use.setInCondition(inCondition); | 
					
						
							| 
									
										
										
										
											2009-03-04 11:47:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     foreach (const MacroArgumentReference &actual, actuals) { | 
					
						
							|  |  |  |         const Block arg(actual.position(), actual.position() + actual.length()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         use.addArgument(arg); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _macroUses.append(use); | 
					
						
							| 
									
										
										
										
											2008-12-04 12:05:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  | void Document::addUndefinedMacroUse(const QByteArray &name, unsigned offset) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QByteArray copy(name.data(), name.size()); | 
					
						
							|  |  |  |     UndefinedMacroUse use(copy, offset); | 
					
						
							|  |  |  |     _undefinedMacroUses.append(use); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |     \class Document::MacroUse | 
					
						
							|  |  |  |     \brief Represents the usage of a macro in a \l {Document}. | 
					
						
							|  |  |  |     \sa Document::UndefinedMacroUse | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |     \class Document::UndefinedMacroUse | 
					
						
							|  |  |  |     \brief Represents a macro that was looked up, but not found. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Holds data about the reference to a macro in an \tt{#ifdef} or \tt{#ifndef} | 
					
						
							|  |  |  |     or argument to the \tt{defined} operator inside an \tt{#if} or \tt{#elif} that does | 
					
						
							|  |  |  |     not exist. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     \sa Document::undefinedMacroUses(), Document::MacroUse, Macro | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |     \fn QByteArray Document::UndefinedMacroUse::name() const | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Returns the name of the macro that was not found. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |     \fn QList<UndefinedMacroUse> Document::undefinedMacroUses() const | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Returns a list of referenced but undefined macros. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     \sa Document::macroUses(), Document::definedMacros(), Macro | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |     \fn QList<MacroUse> Document::macroUses() const | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Returns a list of macros used. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     \sa Document::undefinedMacroUses(), Document::definedMacros(), Macro | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |     \fn QList<Macro> Document::definedMacros() const | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Returns the list of macros defined. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     \sa Document::macroUses(), Document::undefinedMacroUses() | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | TranslationUnit *Document::translationUnit() const | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return _translationUnit; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | bool Document::skipFunctionBody() const | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return _translationUnit->skipFunctionBody(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | void Document::setSkipFunctionBody(bool skipFunctionBody) | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     _translationUnit->setSkipFunctionBody(skipFunctionBody); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | unsigned Document::globalSymbolCount() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (! _globalNamespace) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return _globalNamespace->memberCount(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Symbol *Document::globalSymbolAt(unsigned index) const | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return _globalNamespace->memberAt(index); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | Namespace *Document::globalNamespace() const | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return _globalNamespace; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-18 15:21:07 +01:00
										 |  |  | void Document::setGlobalNamespace(Namespace *globalNamespace) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _globalNamespace = globalNamespace; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-12 12:53:16 +02:00
										 |  |  | Scope *Document::scopeAt(unsigned line, unsigned column) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     FindScopeAt findScopeAt(_translationUnit, line, column); | 
					
						
							| 
									
										
										
										
											2010-05-12 14:41:25 +02:00
										 |  |  |     if (Scope *scope = findScopeAt(_globalNamespace)) | 
					
						
							|  |  |  |         return scope; | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |     return globalNamespace(); | 
					
						
							| 
									
										
										
										
											2010-05-12 12:53:16 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 13:01:56 +02:00
										 |  |  | Symbol *Document::lastVisibleSymbolAt(unsigned line, unsigned column) const | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-08-17 13:42:04 +02:00
										 |  |  |     LastVisibleSymbolAt lastVisibleSymbolAt(globalNamespace()); | 
					
						
							|  |  |  |     return lastVisibleSymbolAt(line, column); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-21 14:47:22 +01:00
										 |  |  | const Macro *Document::findMacroDefinitionAt(unsigned line) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     foreach (const Macro ¯o, _definedMacros) { | 
					
						
							|  |  |  |         if (macro.line() == line) | 
					
						
							|  |  |  |             return ¯o; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const Document::MacroUse *Document::findMacroUseAt(unsigned offset) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     foreach (const Document::MacroUse &use, _macroUses) { | 
					
						
							|  |  |  |         if (use.contains(offset)) | 
					
						
							|  |  |  |             return &use; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const Document::UndefinedMacroUse *Document::findUndefinedMacroUseAt(unsigned offset) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     foreach (const Document::UndefinedMacroUse &use, _undefinedMacroUses) { | 
					
						
							|  |  |  |         if (use.contains(offset)) | 
					
						
							|  |  |  |             return &use; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | Document::Ptr Document::create(const QString &fileName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Document::Ptr doc(new Document(fileName)); | 
					
						
							|  |  |  |     return doc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-05 14:29:57 +02:00
										 |  |  | QByteArray Document::source() const | 
					
						
							|  |  |  | { return _source; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | void Document::setSource(const QByteArray &source) | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-24 11:04:52 +01:00
										 |  |  |     _source = source; | 
					
						
							|  |  |  |     _translationUnit->setSource(_source.constBegin(), _source.size()); | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | void Document::startSkippingBlocks(unsigned start) | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     _skippedBlocks.append(Block(start, 0)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | void Document::stopSkippingBlocks(unsigned stop) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-10 22:56:04 +01:00
										 |  |  |     if (_skippedBlocks.isEmpty()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     unsigned start = _skippedBlocks.back().begin(); | 
					
						
							|  |  |  |     if (start > stop) | 
					
						
							|  |  |  |         _skippedBlocks.removeLast(); // Ignore this block, it's invalid.
 | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         _skippedBlocks.back() = Block(start, stop); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 11:04:52 +01:00
										 |  |  | bool Document::isTokenized() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _translationUnit->isTokenized(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Document::tokenize() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _translationUnit->tokenize(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Document::isParsed() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _translationUnit->isParsed(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-03 14:01:19 +01:00
										 |  |  | bool Document::parse(ParseMode mode) | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-03 14:01:19 +01:00
										 |  |  |     TranslationUnit::ParseMode m = TranslationUnit::ParseTranlationUnit; | 
					
						
							|  |  |  |     switch (mode) { | 
					
						
							|  |  |  |     case ParseTranlationUnit: | 
					
						
							|  |  |  |         m = TranslationUnit::ParseTranlationUnit; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case ParseDeclaration: | 
					
						
							|  |  |  |         m = TranslationUnit::ParseDeclaration; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case ParseExpression: | 
					
						
							|  |  |  |         m = TranslationUnit::ParseExpression; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-30 15:07:30 +02:00
										 |  |  |     case ParseDeclarator: | 
					
						
							|  |  |  |         m = TranslationUnit::ParseDeclarator; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-03 14:01:19 +01:00
										 |  |  |     case ParseStatement: | 
					
						
							|  |  |  |         m = TranslationUnit::ParseStatement; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return _translationUnit->parse(m); | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-26 09:11:14 +02:00
										 |  |  | void Document::check(CheckMode mode) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-10 15:43:17 +01:00
										 |  |  |     Q_ASSERT(!_globalNamespace); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-30 16:13:43 +02:00
										 |  |  |     if (! isParsed()) | 
					
						
							|  |  |  |         parse(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-13 15:28:22 +02:00
										 |  |  |     _globalNamespace = _control->newNamespace(0); | 
					
						
							|  |  |  |     Bind semantic(_translationUnit); | 
					
						
							| 
									
										
										
										
											2009-06-26 09:11:14 +02:00
										 |  |  |     if (mode == FastCheck) | 
					
						
							|  |  |  |         semantic.setSkipFunctionBodies(true); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-03 14:01:19 +01:00
										 |  |  |     if (! _translationUnit->ast()) | 
					
						
							|  |  |  |         return; // nothing to do.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (TranslationUnitAST *ast = _translationUnit->ast()->asTranslationUnit()) { | 
					
						
							| 
									
										
										
										
											2010-08-13 15:28:22 +02:00
										 |  |  |         semantic(ast, _globalNamespace); | 
					
						
							| 
									
										
										
										
											2009-06-17 11:11:21 +02:00
										 |  |  |     } else if (ExpressionAST *ast = _translationUnit->ast()->asExpression()) { | 
					
						
							| 
									
										
										
										
											2010-08-13 15:28:22 +02:00
										 |  |  |         semantic(ast, _globalNamespace); | 
					
						
							| 
									
										
										
										
											2011-08-10 09:50:04 +02:00
										 |  |  |     } else if (DeclarationAST *ast = translationUnit()->ast()->asDeclaration()) { | 
					
						
							|  |  |  |         semantic(ast, _globalNamespace); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 10:13:15 +01:00
										 |  |  | class FindExposedQmlTypes : protected ASTVisitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Document *_doc; | 
					
						
							|  |  |  |     QList<Document::ExportedQmlType> _exportedTypes; | 
					
						
							| 
									
										
										
										
											2011-01-05 12:19:09 +01:00
										 |  |  |     CompoundStatementAST *_compound; | 
					
						
							|  |  |  |     ASTMatcher _matcher; | 
					
						
							|  |  |  |     ASTPatternBuilder _builder; | 
					
						
							|  |  |  |     Overview _overview; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 10:13:15 +01:00
										 |  |  | public: | 
					
						
							|  |  |  |     FindExposedQmlTypes(Document *doc) | 
					
						
							|  |  |  |         : ASTVisitor(doc->translationUnit()) | 
					
						
							|  |  |  |         , _doc(doc) | 
					
						
							| 
									
										
										
										
											2011-01-05 12:19:09 +01:00
										 |  |  |         , _compound(0) | 
					
						
							| 
									
										
										
										
											2010-12-03 10:13:15 +01:00
										 |  |  |     {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<Document::ExportedQmlType> operator()() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         _exportedTypes.clear(); | 
					
						
							|  |  |  |         accept(translationUnit()->ast()); | 
					
						
							|  |  |  |         return _exportedTypes; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2011-01-05 12:19:09 +01:00
										 |  |  |     virtual bool visit(CompoundStatementAST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         CompoundStatementAST *old = _compound; | 
					
						
							|  |  |  |         _compound = ast; | 
					
						
							|  |  |  |         accept(ast->statement_list); | 
					
						
							|  |  |  |         _compound = old; | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 10:13:15 +01:00
										 |  |  |     virtual bool visit(CallAST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         IdExpressionAST *idExp = ast->base_expression->asIdExpression(); | 
					
						
							|  |  |  |         if (!idExp || !idExp->name) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         TemplateIdAST *templateId = idExp->name->asTemplateId(); | 
					
						
							|  |  |  |         if (!templateId || !templateId->identifier_token) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // check the name
 | 
					
						
							|  |  |  |         const Identifier *templateIdentifier = translationUnit()->identifier(templateId->identifier_token); | 
					
						
							|  |  |  |         if (!templateIdentifier) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         const QString callName = QString::fromUtf8(templateIdentifier->chars()); | 
					
						
							|  |  |  |         if (callName != QLatin1String("qmlRegisterType")) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // must have a single typeid template argument
 | 
					
						
							|  |  |  |         if (!templateId->template_argument_list || !templateId->template_argument_list->value | 
					
						
							|  |  |  |                 || templateId->template_argument_list->next) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         TypeIdAST *typeId = templateId->template_argument_list->value->asTypeId(); | 
					
						
							|  |  |  |         if (!typeId) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // must have four arguments
 | 
					
						
							|  |  |  |         if (!ast->expression_list | 
					
						
							|  |  |  |                 || !ast->expression_list->value || !ast->expression_list->next | 
					
						
							|  |  |  |                 || !ast->expression_list->next->value || !ast->expression_list->next->next | 
					
						
							|  |  |  |                 || !ast->expression_list->next->next->value || !ast->expression_list->next->next->next | 
					
						
							|  |  |  |                 || !ast->expression_list->next->next->next->value | 
					
						
							|  |  |  |                 || ast->expression_list->next->next->next->next) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-05 12:19:09 +01:00
										 |  |  |         // last argument must be a string literal
 | 
					
						
							| 
									
										
										
										
											2010-12-03 10:13:15 +01:00
										 |  |  |         const StringLiteral *nameLit = 0; | 
					
						
							|  |  |  |         if (StringLiteralAST *nameAst = ast->expression_list->next->next->next->value->asStringLiteral()) | 
					
						
							|  |  |  |             nameLit = translationUnit()->stringLiteral(nameAst->literal_token); | 
					
						
							|  |  |  |         if (!nameLit) { | 
					
						
							| 
									
										
										
										
											2011-03-03 11:55:48 +01:00
										 |  |  |             // disable this warning for now, we don't want to encourage using string literals if they don't mean to
 | 
					
						
							|  |  |  |             // in the future, we will also accept annotations for the qmlRegisterType arguments in comments
 | 
					
						
							|  |  |  | //            translationUnit()->warning(ast->expression_list->next->next->next->value->firstToken(),
 | 
					
						
							|  |  |  | //                                       "The type will only be available in Qt Creator's QML editors when the type name is a string literal");
 | 
					
						
							| 
									
										
										
										
											2010-12-03 10:13:15 +01:00
										 |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-05 12:19:09 +01:00
										 |  |  |         // if the first argument is a string literal, things are easy
 | 
					
						
							|  |  |  |         QString packageName; | 
					
						
							|  |  |  |         if (StringLiteralAST *packageAst = ast->expression_list->value->asStringLiteral()) { | 
					
						
							|  |  |  |             const StringLiteral *packageLit = translationUnit()->stringLiteral(packageAst->literal_token); | 
					
						
							|  |  |  |             packageName = QString::fromUtf8(packageLit->chars(), packageLit->size()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // as a special case, allow an identifier package argument if there's a
 | 
					
						
							|  |  |  |         // Q_ASSERT(QLatin1String(uri) == QLatin1String("actual uri"));
 | 
					
						
							|  |  |  |         // in the enclosing compound statement
 | 
					
						
							|  |  |  |         IdExpressionAST *uriName = ast->expression_list->value->asIdExpression(); | 
					
						
							|  |  |  |         if (packageName.isEmpty() && uriName && _compound) { | 
					
						
							|  |  |  |             for (StatementListAST *it = _compound->statement_list; it; it = it->next) { | 
					
						
							|  |  |  |                 StatementAST *stmt = it->value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 packageName = nameOfUriAssert(stmt, uriName); | 
					
						
							|  |  |  |                 if (!packageName.isEmpty()) | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 10:13:15 +01:00
										 |  |  |         // second and third argument must be integer literals
 | 
					
						
							|  |  |  |         const NumericLiteral *majorLit = 0; | 
					
						
							|  |  |  |         const NumericLiteral *minorLit = 0; | 
					
						
							|  |  |  |         if (NumericLiteralAST *majorAst = ast->expression_list->next->value->asNumericLiteral()) | 
					
						
							|  |  |  |             majorLit = translationUnit()->numericLiteral(majorAst->literal_token); | 
					
						
							|  |  |  |         if (NumericLiteralAST *minorAst = ast->expression_list->next->next->value->asNumericLiteral()) | 
					
						
							|  |  |  |             minorLit = translationUnit()->numericLiteral(minorAst->literal_token); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // build the descriptor
 | 
					
						
							|  |  |  |         Document::ExportedQmlType exportedType; | 
					
						
							|  |  |  |         exportedType.typeName = QString::fromUtf8(nameLit->chars(), nameLit->size()); | 
					
						
							| 
									
										
										
										
											2011-01-05 12:19:09 +01:00
										 |  |  |         if (!packageName.isEmpty() && majorLit && minorLit && majorLit->isInt() && minorLit->isInt()) { | 
					
						
							|  |  |  |             exportedType.packageName = packageName; | 
					
						
							| 
									
										
										
										
											2010-12-03 10:13:15 +01:00
										 |  |  |             exportedType.majorVersion = QString::fromUtf8(majorLit->chars(), majorLit->size()).toInt(); | 
					
						
							|  |  |  |             exportedType.minorVersion = QString::fromUtf8(minorLit->chars(), minorLit->size()).toInt(); | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2011-03-03 11:55:48 +01:00
										 |  |  |             // disable this warning, see above for details
 | 
					
						
							|  |  |  | //            translationUnit()->warning(ast->base_expression->firstToken(),
 | 
					
						
							|  |  |  | //                                       "The module will not be available in Qt Creator's QML editors because the uri and version numbers\n"
 | 
					
						
							|  |  |  | //                                       "cannot be determined by static analysis. The type will still be available globally.");
 | 
					
						
							| 
									
										
										
										
											2010-12-03 10:13:15 +01:00
										 |  |  |             exportedType.packageName = QLatin1String("<default>"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // we want to do lookup later, so also store the surrounding scope
 | 
					
						
							|  |  |  |         unsigned line, column; | 
					
						
							|  |  |  |         translationUnit()->getTokenStartPosition(ast->firstToken(), &line, &column); | 
					
						
							|  |  |  |         exportedType.scope = _doc->scopeAt(line, column); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // and the expression
 | 
					
						
							|  |  |  |         const Token begin = translationUnit()->tokenAt(typeId->firstToken()); | 
					
						
							|  |  |  |         const Token last = translationUnit()->tokenAt(typeId->lastToken() - 1); | 
					
						
							|  |  |  |         exportedType.typeExpression = _doc->source().mid(begin.begin(), last.end() - begin.begin()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         _exportedTypes += exportedType; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-01-05 12:19:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     QString stringOf(AST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         const Token begin = translationUnit()->tokenAt(ast->firstToken()); | 
					
						
							|  |  |  |         const Token last = translationUnit()->tokenAt(ast->lastToken() - 1); | 
					
						
							|  |  |  |         return _doc->source().mid(begin.begin(), last.end() - begin.begin()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ExpressionAST *skipStringCall(ExpressionAST *exp) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!exp) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         IdExpressionAST *callName = _builder.IdExpression(); | 
					
						
							|  |  |  |         CallAST *call = _builder.Call(callName); | 
					
						
							|  |  |  |         if (!exp->match(call, &_matcher)) | 
					
						
							|  |  |  |             return exp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const QString name = stringOf(callName); | 
					
						
							|  |  |  |         if (name != QLatin1String("QLatin1String") | 
					
						
							|  |  |  |                 && name != QLatin1String("QString")) | 
					
						
							|  |  |  |             return exp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!call->expression_list || call->expression_list->next) | 
					
						
							|  |  |  |             return exp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return call->expression_list->value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString nameOfUriAssert(StatementAST *stmt, IdExpressionAST *uriName) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QString null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         IdExpressionAST *outerCallName = _builder.IdExpression(); | 
					
						
							|  |  |  |         BinaryExpressionAST *binary = _builder.BinaryExpression(); | 
					
						
							|  |  |  |         // assert(... == ...);
 | 
					
						
							|  |  |  |         ExpressionStatementAST *pattern = _builder.ExpressionStatement( | 
					
						
							|  |  |  |                     _builder.Call(outerCallName, _builder.ExpressionList( | 
					
						
							|  |  |  |                                      binary))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!stmt->match(pattern, &_matcher)) { | 
					
						
							|  |  |  |             outerCallName = _builder.IdExpression(); | 
					
						
							|  |  |  |             binary = _builder.BinaryExpression(); | 
					
						
							|  |  |  |             // the expansion of Q_ASSERT(...),
 | 
					
						
							|  |  |  |             // ((!(... == ...)) ? qt_assert(...) : ...);
 | 
					
						
							|  |  |  |             pattern = _builder.ExpressionStatement( | 
					
						
							|  |  |  |                         _builder.NestedExpression( | 
					
						
							|  |  |  |                             _builder.ConditionalExpression( | 
					
						
							|  |  |  |                                 _builder.NestedExpression( | 
					
						
							|  |  |  |                                     _builder.UnaryExpression( | 
					
						
							|  |  |  |                                         _builder.NestedExpression( | 
					
						
							|  |  |  |                                             binary))), | 
					
						
							|  |  |  |                                 _builder.Call(outerCallName)))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!stmt->match(pattern, &_matcher)) | 
					
						
							|  |  |  |                 return null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const QString outerCall = stringOf(outerCallName); | 
					
						
							|  |  |  |         if (outerCall != QLatin1String("qt_assert") | 
					
						
							|  |  |  |                 && outerCall != QLatin1String("assert") | 
					
						
							|  |  |  |                 && outerCall != QLatin1String("Q_ASSERT")) | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (translationUnit()->tokenAt(binary->binary_op_token).kind() != T_EQUAL_EQUAL) | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ExpressionAST *lhsExp = skipStringCall(binary->left_expression); | 
					
						
							|  |  |  |         ExpressionAST *rhsExp = skipStringCall(binary->right_expression); | 
					
						
							|  |  |  |         if (!lhsExp || !rhsExp) | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         StringLiteralAST *uriString = lhsExp->asStringLiteral(); | 
					
						
							|  |  |  |         IdExpressionAST *uriArgName = lhsExp->asIdExpression(); | 
					
						
							|  |  |  |         if (!uriString) | 
					
						
							|  |  |  |             uriString = rhsExp->asStringLiteral(); | 
					
						
							|  |  |  |         if (!uriArgName) | 
					
						
							|  |  |  |             uriArgName = rhsExp->asIdExpression(); | 
					
						
							|  |  |  |         if (!uriString || !uriArgName) | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (stringOf(uriArgName) != stringOf(uriName)) | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const StringLiteral *packageLit = translationUnit()->stringLiteral(uriString->literal_token); | 
					
						
							|  |  |  |         return QString::fromUtf8(packageLit->chars(), packageLit->size()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-12-03 10:13:15 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Document::findExposedQmlTypes() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (! _translationUnit->ast()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-05 12:19:09 +01:00
										 |  |  |     QByteArray qmlRegisterTypeToken("qmlRegisterType"); | 
					
						
							|  |  |  |     if (_translationUnit->control()->findIdentifier( | 
					
						
							|  |  |  |                 qmlRegisterTypeToken.constData(), qmlRegisterTypeToken.size())) { | 
					
						
							|  |  |  |         FindExposedQmlTypes finder(this); | 
					
						
							|  |  |  |         _exportedQmlTypes = finder(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-12-03 10:13:15 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 11:04:52 +01:00
										 |  |  | void Document::releaseSource() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _source.clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | void Document::releaseTranslationUnit() | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     _translationUnit->release(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-03-04 11:47:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | Snapshot::Snapshot() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Snapshot::~Snapshot() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-07 10:54:27 +01:00
										 |  |  | int Snapshot::size() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _documents.size(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Snapshot::isEmpty() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _documents.isEmpty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Document::Ptr Snapshot::operator[](const QString &fileName) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _documents.value(fileName, Document::Ptr()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Snapshot::const_iterator Snapshot::find(const QString &fileName) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _documents.find(fileName); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Snapshot::remove(const QString &fileName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _documents.remove(fileName); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Snapshot::contains(const QString &fileName) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _documents.contains(fileName); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 11:47:30 +01:00
										 |  |  | void Snapshot::insert(Document::Ptr doc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (doc) | 
					
						
							| 
									
										
										
										
											2009-12-07 10:54:27 +01:00
										 |  |  |         _documents.insert(doc->fileName(), doc); | 
					
						
							| 
									
										
										
										
											2009-03-04 11:47:30 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-15 15:38:20 +02:00
										 |  |  | QByteArray Snapshot::preprocessedCode(const QString &source, const QString &fileName) const | 
					
						
							| 
									
										
										
										
											2009-06-03 16:16:20 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     FastPreprocessor pp(*this); | 
					
						
							|  |  |  |     return pp.run(fileName, source); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Document::Ptr Snapshot::documentFromSource(const QByteArray &preprocessedCode, | 
					
						
							|  |  |  |                                            const QString &fileName) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-06-24 16:40:30 +02:00
										 |  |  |     Document::Ptr newDoc = Document::create(fileName); | 
					
						
							| 
									
										
										
										
											2009-06-03 16:16:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-07 10:54:27 +01:00
										 |  |  |     if (Document::Ptr thisDocument = document(fileName)) { | 
					
						
							| 
									
										
										
										
											2009-11-05 12:34:02 +01:00
										 |  |  |         newDoc->_revision = thisDocument->_revision; | 
					
						
							| 
									
										
										
										
											2009-12-15 15:52:55 +01:00
										 |  |  |         newDoc->_editorRevision = thisDocument->_editorRevision; | 
					
						
							| 
									
										
										
										
											2009-11-05 12:34:02 +01:00
										 |  |  |         newDoc->_lastModified = thisDocument->_lastModified; | 
					
						
							| 
									
										
										
										
											2009-06-03 16:16:20 +02:00
										 |  |  |         newDoc->_includes = thisDocument->_includes; | 
					
						
							|  |  |  |         newDoc->_definedMacros = thisDocument->_definedMacros; | 
					
						
							| 
									
										
										
										
											2009-10-15 16:24:15 +02:00
										 |  |  |         newDoc->_macroUses = thisDocument->_macroUses; | 
					
						
							| 
									
										
										
										
											2009-06-03 16:16:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-24 16:40:30 +02:00
										 |  |  |     newDoc->setSource(preprocessedCode); | 
					
						
							|  |  |  |     return newDoc; | 
					
						
							| 
									
										
										
										
											2009-06-03 16:16:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-07 10:54:27 +01:00
										 |  |  | Document::Ptr Snapshot::document(const QString &fileName) const | 
					
						
							| 
									
										
										
										
											2009-12-02 17:05:36 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-07 11:20:16 +01:00
										 |  |  |     return _documents.value(fileName); | 
					
						
							| 
									
										
										
										
											2009-12-02 17:05:36 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-10 11:59:01 +02:00
										 |  |  | Snapshot Snapshot::simplified(Document::Ptr doc) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Snapshot snapshot; | 
					
						
							|  |  |  |     simplified_helper(doc, &snapshot); | 
					
						
							|  |  |  |     return snapshot; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Snapshot::simplified_helper(Document::Ptr doc, Snapshot *snapshot) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (! doc) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (! snapshot->contains(doc->fileName())) { | 
					
						
							|  |  |  |         snapshot->insert(doc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach (const Document::Include &incl, doc->includes()) { | 
					
						
							| 
									
										
										
										
											2009-12-07 10:54:27 +01:00
										 |  |  |             Document::Ptr includedDoc = document(incl.fileName()); | 
					
						
							| 
									
										
										
										
											2009-07-10 11:59:01 +02:00
										 |  |  |             simplified_helper(includedDoc, snapshot); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace { | 
					
						
							|  |  |  | class FindMatchingDefinition: public SymbolVisitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Symbol *_declaration; | 
					
						
							| 
									
										
										
										
											2010-11-18 17:39:16 +01:00
										 |  |  |     const OperatorNameId *_oper; | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  |     QList<Function *> _result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     FindMatchingDefinition(Symbol *declaration) | 
					
						
							| 
									
										
										
										
											2010-11-18 17:39:16 +01:00
										 |  |  |         : _declaration(declaration) | 
					
						
							|  |  |  |         , _oper(0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (_declaration->name()) | 
					
						
							|  |  |  |             _oper = _declaration->name()->asOperatorNameId(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QList<Function *> result() const { return _result; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     using SymbolVisitor::visit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool visit(Function *fun) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-11-18 17:39:16 +01:00
										 |  |  |         if (_oper) { | 
					
						
							|  |  |  |             if (const Name *name = fun->unqualifiedName()) { | 
					
						
							|  |  |  |                     if (_oper->isEqualTo(name)) | 
					
						
							|  |  |  |                         _result.append(fun); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if (const Identifier *id = _declaration->identifier()) { | 
					
						
							|  |  |  |             if (id->isEqualTo(fun->identifier())) | 
					
						
							|  |  |  |                 _result.append(fun); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool visit(Block *) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | } // end of anonymous namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-10 09:50:04 +02:00
										 |  |  | // strict means the returned symbol has to match exactly,
 | 
					
						
							|  |  |  | // including argument count and argument types
 | 
					
						
							|  |  |  | Symbol *Snapshot::findMatchingDefinition(Symbol *declaration, bool strict) const | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-18 17:39:16 +01:00
										 |  |  |     if (!declaration) | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-05 13:34:27 +02:00
										 |  |  |     Document::Ptr thisDocument = document(QString::fromUtf8(declaration->fileName(), declaration->fileNameLength())); | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  |     if (! thisDocument) { | 
					
						
							| 
									
										
										
										
											2010-07-05 13:34:27 +02:00
										 |  |  |         qWarning() << "undefined document:" << declaration->fileName(); | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Function *declarationTy = declaration->type()->asFunctionType(); | 
					
						
							|  |  |  |     if (! declarationTy) { | 
					
						
							|  |  |  |         qWarning() << "not a function:" << declaration->fileName() << declaration->line() << declaration->column(); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     foreach (Document::Ptr doc, *this) { | 
					
						
							| 
									
										
										
										
											2010-11-18 17:39:16 +01:00
										 |  |  |         const Identifier *id = declaration->identifier(); | 
					
						
							|  |  |  |         if (id && ! doc->control()->findIdentifier(id->chars(), | 
					
						
							|  |  |  |                                                    id->size())) | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2010-11-18 17:39:16 +01:00
										 |  |  |         if (!id) { | 
					
						
							|  |  |  |             if (!declaration->name()) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             const OperatorNameId *oper = declaration->name()->asOperatorNameId(); | 
					
						
							|  |  |  |             if (!oper) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             if (!doc->control()->findOperatorNameId(oper->kind())) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         FindMatchingDefinition candidates(declaration); | 
					
						
							|  |  |  |         candidates.accept(doc->globalNamespace()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const QList<Function *> result = candidates.result(); | 
					
						
							|  |  |  |         if (! result.isEmpty()) { | 
					
						
							|  |  |  |             LookupContext context(doc, *this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             QList<Function *> viableFunctions; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-21 11:35:03 +02:00
										 |  |  |             ClassOrNamespace *enclosingType = context.lookupType(declaration); | 
					
						
							|  |  |  |             if (! enclosingType) | 
					
						
							|  |  |  |                 continue; // nothing to do
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  |             foreach (Function *fun, result) { | 
					
						
							| 
									
										
										
										
											2010-08-26 16:16:22 +02:00
										 |  |  |                 const QList<LookupItem> declarations = context.lookup(fun->name(), fun->enclosingScope()); | 
					
						
							| 
									
										
										
										
											2010-05-21 11:35:03 +02:00
										 |  |  |                 if (declarations.isEmpty()) | 
					
						
							|  |  |  |                     continue; | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-16 11:03:39 +02:00
										 |  |  |                 const LookupItem best = declarations.first(); | 
					
						
							|  |  |  |                 if (enclosingType == context.lookupType(best.declaration())) | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  |                     viableFunctions.append(fun); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (viableFunctions.isEmpty()) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-10 09:50:04 +02:00
										 |  |  |             else if (! strict && viableFunctions.length() == 1) | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  |                 return viableFunctions.first(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             Function *best = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             foreach (Function *fun, viableFunctions) { | 
					
						
							| 
									
										
										
										
											2010-12-10 10:32:46 +01:00
										 |  |  |                 if (! (fun->unqualifiedName() && fun->unqualifiedName()->isEqualTo(declaration->unqualifiedName()))) | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  |                     continue; | 
					
						
							|  |  |  |                 else if (fun->argumentCount() == declarationTy->argumentCount()) { | 
					
						
							| 
									
										
										
										
											2011-08-10 09:50:04 +02:00
										 |  |  |                     if (! strict && ! best) | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  |                         best = fun; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     unsigned argc = 0; | 
					
						
							|  |  |  |                     for (; argc < declarationTy->argumentCount(); ++argc) { | 
					
						
							|  |  |  |                         Symbol *arg = fun->argumentAt(argc); | 
					
						
							|  |  |  |                         Symbol *otherArg = declarationTy->argumentAt(argc); | 
					
						
							|  |  |  |                         if (! arg->type().isEqualTo(otherArg->type())) | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (argc == declarationTy->argumentCount()) | 
					
						
							|  |  |  |                         best = fun; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-10 09:50:04 +02:00
										 |  |  |             if (!strict && ! best) | 
					
						
							| 
									
										
										
										
											2010-05-11 12:47:20 +02:00
										 |  |  |                 best = viableFunctions.first(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return best; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-06-16 15:35:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | Class *Snapshot::findMatchingClassDeclaration(Symbol *declaration) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (! declaration->identifier()) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     foreach (Document::Ptr doc, *this) { | 
					
						
							|  |  |  |         if (! doc->control()->findIdentifier(declaration->identifier()->chars(), | 
					
						
							|  |  |  |                                              declaration->identifier()->size())) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         LookupContext context(doc, *this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ClassOrNamespace *type = context.lookupType(declaration); | 
					
						
							| 
									
										
										
										
											2010-06-18 09:26:38 +02:00
										 |  |  |         if (!type) | 
					
						
							| 
									
										
										
										
											2010-06-16 15:35:34 +02:00
										 |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-18 09:26:38 +02:00
										 |  |  |         foreach (Symbol *s, type->symbols()) { | 
					
						
							|  |  |  |             if (Class *c = s->asClass()) | 
					
						
							|  |  |  |                 return c; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-06-16 15:35:34 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-08-10 09:50:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | void CPlusPlus::findMatchingDeclaration(const LookupContext &context, | 
					
						
							|  |  |  |                                         Function *functionType, | 
					
						
							|  |  |  |                                         QList<Declaration *> *typeMatch, | 
					
						
							|  |  |  |                                         QList<Declaration *> *argumentCountMatch, | 
					
						
							|  |  |  |                                         QList<Declaration *> *nameMatch) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Scope *enclosingScope = functionType->enclosingScope(); | 
					
						
							|  |  |  |     while (! (enclosingScope->isNamespace() || enclosingScope->isClass())) | 
					
						
							|  |  |  |         enclosingScope = enclosingScope->enclosingScope(); | 
					
						
							|  |  |  |     Q_ASSERT(enclosingScope != 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const Name *functionName = functionType->name(); | 
					
						
							|  |  |  |     if (! functionName) | 
					
						
							|  |  |  |         return; // anonymous function names are not valid c++
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ClassOrNamespace *binding = 0; | 
					
						
							|  |  |  |     const QualifiedNameId *qName = functionName->asQualifiedNameId(); | 
					
						
							|  |  |  |     if (qName) { | 
					
						
							|  |  |  |         if (qName->base()) | 
					
						
							|  |  |  |             binding = context.lookupType(qName->base(), enclosingScope); | 
					
						
							|  |  |  |         functionName = qName->name(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!binding) { // declaration for a global function
 | 
					
						
							|  |  |  |         binding = context.lookupType(enclosingScope); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!binding) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const Identifier *funcId = functionName->identifier(); | 
					
						
							|  |  |  |     if (!funcId) // E.g. operator, which we might be able to handle in the future...
 | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     foreach (Symbol *s, binding->symbols()) { | 
					
						
							|  |  |  |         Class *matchingClass = s->asClass(); | 
					
						
							|  |  |  |         if (!matchingClass) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (Symbol *s = matchingClass->find(funcId); s; s = s->next()) { | 
					
						
							|  |  |  |             if (! s->name()) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             else if (! funcId->isEqualTo(s->identifier())) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             else if (! s->type()->isFunctionType()) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             else if (Declaration *decl = s->asDeclaration()) { | 
					
						
							|  |  |  |                 if (Function *declFunTy = decl->type()->asFunctionType()) { | 
					
						
							|  |  |  |                     if (functionType->isEqualTo(declFunTy)) | 
					
						
							|  |  |  |                         typeMatch->prepend(decl); | 
					
						
							|  |  |  |                     else if (functionType->argumentCount() == declFunTy->argumentCount()) | 
					
						
							|  |  |  |                         argumentCountMatch->prepend(decl); | 
					
						
							|  |  |  |                     else | 
					
						
							|  |  |  |                         nameMatch->append(decl); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QList<Declaration *> CPlusPlus::findMatchingDeclaration(const LookupContext &context, Function *functionType) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QList<Declaration *> result; | 
					
						
							|  |  |  |     QList<Declaration *> nameMatch, argumentCountMatch, typeMatch; | 
					
						
							|  |  |  |     findMatchingDeclaration(context, functionType, &typeMatch, &argumentCountMatch, &nameMatch); | 
					
						
							|  |  |  |     result.append(typeMatch); | 
					
						
							|  |  |  |     result.append(argumentCountMatch); | 
					
						
							|  |  |  |     result.append(nameMatch); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } |