| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | #include "qmljslink.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "parser/qmljsast_p.h"
 | 
					
						
							|  |  |  | #include "qmljsdocument.h"
 | 
					
						
							|  |  |  | #include "qmljsbind.h"
 | 
					
						
							| 
									
										
										
										
											2010-02-19 15:55:11 +01:00
										 |  |  | #include "qmljsscopebuilder.h"
 | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <QtCore/QFileInfo>
 | 
					
						
							|  |  |  | #include <QtCore/QDir>
 | 
					
						
							|  |  |  | #include <QtCore/QDebug>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace QmlJS; | 
					
						
							|  |  |  | using namespace QmlJS::Interpreter; | 
					
						
							|  |  |  | using namespace QmlJS::AST; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-04 10:19:37 +01:00
										 |  |  | Link::Link(Context *context, Document::Ptr currentDoc, const Snapshot &snapshot) | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |     : _snapshot(snapshot) | 
					
						
							| 
									
										
										
										
											2010-02-04 10:19:37 +01:00
										 |  |  |     , _context(context) | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     _docs = reachableDocuments(currentDoc, snapshot); | 
					
						
							|  |  |  |     linkImports(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Link::~Link() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-03 10:59:52 +01:00
										 |  |  | Interpreter::Engine *Link::engine() | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-04 10:19:37 +01:00
										 |  |  |     return _context->engine(); | 
					
						
							| 
									
										
										
										
											2010-02-03 10:59:52 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-19 12:25:26 +01:00
										 |  |  | void Link::scopeChainAt(Document::Ptr doc, const QList<Node *> &astPath) | 
					
						
							| 
									
										
										
										
											2010-02-03 10:59:52 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  |     ScopeChain &scopeChain = _context->scopeChain(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |     // ### TODO: This object ought to contain the global namespace additions by QML.
 | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  |     scopeChain.globalScope = engine()->globalObject(); | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-19 12:25:26 +01:00
										 |  |  |     if (! doc) { | 
					
						
							|  |  |  |         scopeChain.update(); | 
					
						
							| 
									
										
										
										
											2010-02-03 10:59:52 +01:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2010-02-19 12:25:26 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-02-03 14:31:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-03 15:59:15 +01:00
										 |  |  |     Bind *bind = doc->bind(); | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  |     QHash<Document *, ScopeChain::QmlComponentChain *> componentScopes; | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |     if (doc->qmlProgram()) { | 
					
						
							|  |  |  |         _context->setLookupMode(Context::QmlLookup); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 11:21:03 +01:00
										 |  |  |         scopeChain.qmlComponentScope.clear(); | 
					
						
							| 
									
										
										
										
											2010-02-25 12:56:59 +01:00
										 |  |  |         componentScopes.insert(doc.data(), &scopeChain.qmlComponentScope); | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  |         makeComponentChain(doc, &scopeChain.qmlComponentScope, &componentScopes); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |         if (const ObjectValue *typeEnvironment = _context->typeEnvironment(doc.data())) | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  |             scopeChain.qmlTypes = typeEnvironment; | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2010-02-12 10:05:13 +01:00
										 |  |  |         // the global scope of a js file does not see the instantiating component
 | 
					
						
							| 
									
										
										
										
											2010-02-19 15:55:11 +01:00
										 |  |  |         if (astPath.size() > 0) { | 
					
						
							| 
									
										
										
										
											2010-02-12 10:05:13 +01:00
										 |  |  |             // add scope chains for all components that source this document
 | 
					
						
							|  |  |  |             foreach (Document::Ptr otherDoc, _docs) { | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  |                 if (otherDoc->bind()->includedScripts().contains(doc->fileName())) { | 
					
						
							|  |  |  |                     ScopeChain::QmlComponentChain *component = new ScopeChain::QmlComponentChain; | 
					
						
							|  |  |  |                     componentScopes.insert(otherDoc.data(), component); | 
					
						
							|  |  |  |                     scopeChain.qmlComponentScope.instantiatingComponents += component; | 
					
						
							|  |  |  |                     makeComponentChain(otherDoc, component, &componentScopes); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2010-02-12 10:05:13 +01:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // ### TODO: Which type environment do scripts see?
 | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  |         scopeChain.jsScopes += bind->rootObjectValue(); | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-02-03 10:59:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-19 15:55:11 +01:00
										 |  |  |     ScopeBuilder scopeBuilder(doc, _context); | 
					
						
							|  |  |  |     foreach (Node *node, astPath) | 
					
						
							|  |  |  |         scopeBuilder.push(node); | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  | void Link::makeComponentChain( | 
					
						
							|  |  |  |         Document::Ptr doc, | 
					
						
							|  |  |  |         ScopeChain::QmlComponentChain *target, | 
					
						
							|  |  |  |         QHash<Document *, ScopeChain::QmlComponentChain *> *components) | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (!doc->qmlProgram()) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2010-02-08 21:37:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |     Bind *bind = doc->bind(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // add scopes for all components instantiating this one
 | 
					
						
							|  |  |  |     foreach (Document::Ptr otherDoc, _docs) { | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  |         if (otherDoc == doc) | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |             continue; | 
					
						
							|  |  |  |         if (otherDoc->bind()->usesQmlPrototype(bind->rootObjectValue(), _context)) { | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  |             if (components->contains(otherDoc.data())) { | 
					
						
							| 
									
										
										
										
											2010-02-25 12:56:59 +01:00
										 |  |  | //                target->instantiatingComponents += components->value(otherDoc.data());
 | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 ScopeChain::QmlComponentChain *component = new ScopeChain::QmlComponentChain; | 
					
						
							|  |  |  |                 components->insert(otherDoc.data(), component); | 
					
						
							|  |  |  |                 target->instantiatingComponents += component; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 makeComponentChain(otherDoc, component, components); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-02-08 21:37:59 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  |     // build this component scope
 | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |     if (bind->rootObjectValue()) | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  |         target->rootObject = bind->rootObjectValue(); | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-03 14:31:03 +01:00
										 |  |  |     const QStringList &includedScripts = bind->includedScripts(); | 
					
						
							|  |  |  |     for (int index = includedScripts.size() - 1; index != -1; --index) { | 
					
						
							|  |  |  |         const QString &scriptFile = includedScripts.at(index); | 
					
						
							| 
									
										
										
										
											2010-02-03 10:59:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-03 14:31:03 +01:00
										 |  |  |         if (Document::Ptr scriptDoc = _snapshot.document(scriptFile)) { | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  |             if (scriptDoc->jsProgram()) | 
					
						
							|  |  |  |                 target->functionScopes += scriptDoc->bind()->rootObjectValue(); | 
					
						
							| 
									
										
										
										
											2010-02-03 10:59:52 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-19 10:14:34 +01:00
										 |  |  |     target->functionScopes += bind->functionEnvironment(); | 
					
						
							|  |  |  |     target->ids = bind->idEnvironment(); | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Link::linkImports() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     foreach (Document::Ptr doc, _docs) { | 
					
						
							| 
									
										
										
										
											2010-02-03 14:31:03 +01:00
										 |  |  |         ObjectValue *typeEnv = engine()->newObject(/*prototype =*/0); // ### FIXME
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Populate the _typeEnvironment with imports.
 | 
					
						
							|  |  |  |         populateImportedTypes(typeEnv, doc); | 
					
						
							| 
									
										
										
										
											2010-02-04 09:44:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-04 10:19:37 +01:00
										 |  |  |         _context->setTypeEnvironment(doc.data(), typeEnv); | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | static QString componentName(const QString &fileName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString componentName = fileName; | 
					
						
							|  |  |  |     int dotIndex = componentName.indexOf(QLatin1Char('.')); | 
					
						
							|  |  |  |     if (dotIndex != -1) | 
					
						
							|  |  |  |         componentName.truncate(dotIndex); | 
					
						
							|  |  |  |     componentName[0] = componentName[0].toUpper(); | 
					
						
							|  |  |  |     return componentName; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | void Link::populateImportedTypes(Interpreter::ObjectValue *typeEnv, Document::Ptr doc) | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (! (doc->qmlProgram() && doc->qmlProgram()->imports)) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 11:36:42 +01:00
										 |  |  |     // Add the implicitly available Script type
 | 
					
						
							|  |  |  |     const ObjectValue *scriptValue = engine()->metaTypeSystem().staticTypeForImport("Script"); | 
					
						
							|  |  |  |     if (scriptValue) | 
					
						
							|  |  |  |         typeEnv->setProperty("Script", scriptValue); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  |     QFileInfo fileInfo(doc->fileName()); | 
					
						
							|  |  |  |     const QString absolutePath = fileInfo.absolutePath(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-29 13:21:50 +01:00
										 |  |  |     // implicit imports:
 | 
					
						
							|  |  |  |     // qml files in the same directory are available without explicit imports
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |     foreach (Document::Ptr otherDoc, _docs) { | 
					
						
							|  |  |  |         if (otherDoc == doc) | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QFileInfo otherFileInfo(otherDoc->fileName()); | 
					
						
							|  |  |  |         const QString otherAbsolutePath = otherFileInfo.absolutePath(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (otherAbsolutePath != absolutePath) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |         typeEnv->setProperty(componentName(otherFileInfo.fileName()), | 
					
						
							| 
									
										
										
										
											2010-02-10 17:05:45 +01:00
										 |  |  |                              otherDoc->bind()->rootObjectValue()); | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // explicit imports, whether directories or files
 | 
					
						
							|  |  |  |     for (UiImportList *it = doc->qmlProgram()->imports; it; it = it->next) { | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |         if (! it->import) | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |         if (it->import->fileName) { | 
					
						
							|  |  |  |             importFile(typeEnv, doc, it->import, absolutePath); | 
					
						
							|  |  |  |         } else if (it->import->importUri) { | 
					
						
							|  |  |  |             importNonFile(typeEnv, doc, it->import); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |     import "content" | 
					
						
							|  |  |  |     import "content" as Xxx | 
					
						
							|  |  |  |     import "content" 4.6 | 
					
						
							|  |  |  |     import "content" 4.6 as Xxx | 
					
						
							| 
									
										
										
										
											2010-01-29 13:36:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |     import "http://www.ovi.com/" as Ovi | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | void Link::importFile(Interpreter::ObjectValue *typeEnv, Document::Ptr doc, | 
					
						
							|  |  |  |                       AST::UiImport *import, const QString &startPath) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-02 16:36:14 +01:00
										 |  |  |     Q_UNUSED(doc) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |     if (!import->fileName) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |     QString path = startPath; | 
					
						
							|  |  |  |     path += QLatin1Char('/'); | 
					
						
							|  |  |  |     path += import->fileName->asString(); | 
					
						
							|  |  |  |     path = QDir::cleanPath(path); | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |     ObjectValue *importNamespace = 0; | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |     foreach (Document::Ptr otherDoc, _docs) { | 
					
						
							|  |  |  |         QFileInfo otherFileInfo(otherDoc->fileName()); | 
					
						
							|  |  |  |         const QString otherAbsolutePath = otherFileInfo.absolutePath(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bool directoryImport = (path == otherAbsolutePath); | 
					
						
							|  |  |  |         bool fileImport = (path == otherDoc->fileName()); | 
					
						
							|  |  |  |         if (!directoryImport && !fileImport) | 
					
						
							|  |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |         if (directoryImport && import->importId && !importNamespace) { | 
					
						
							| 
									
										
										
										
											2010-02-03 14:31:03 +01:00
										 |  |  |             importNamespace = engine()->newObject(/*prototype =*/0); | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |             typeEnv->setProperty(import->importId->asString(), importNamespace); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-01-29 13:36:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |         QString targetName; | 
					
						
							|  |  |  |         if (fileImport && import->importId) { | 
					
						
							|  |  |  |             targetName = import->importId->asString(); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             targetName = componentName(otherFileInfo.fileName()); | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ObjectValue *importInto = typeEnv; | 
					
						
							|  |  |  |         if (importNamespace) | 
					
						
							|  |  |  |             importInto = importNamespace; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-10 17:05:45 +01:00
										 |  |  |         importInto->setProperty(targetName, otherDoc->bind()->rootObjectValue()); | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |   import Qt 4.6 | 
					
						
							|  |  |  |   import Qt 4.6 as Xxx | 
					
						
							|  |  |  |   (import com.nokia.qt is the same as the ones above) | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | void Link::importNonFile(Interpreter::ObjectValue *typeEnv, Document::Ptr doc, AST::UiImport *import) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ObjectValue *namespaceObject = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (import->importId) { // with namespace we insert an object in the type env. to hold the imported types
 | 
					
						
							| 
									
										
										
										
											2010-02-03 14:31:03 +01:00
										 |  |  |         namespaceObject = engine()->newObject(/*prototype */ 0); | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |         typeEnv->setProperty(import->importId->asString(), namespaceObject); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } else { // without namespace we insert all types directly into the type env.
 | 
					
						
							|  |  |  |         namespaceObject = typeEnv; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // try the metaobject system
 | 
					
						
							|  |  |  |     if (import->importUri) { | 
					
						
							|  |  |  |         const QString package = Bind::toString(import->importUri, '/'); | 
					
						
							| 
									
										
										
										
											2010-03-01 13:01:05 +01:00
										 |  |  |         int majorVersion = QmlObjectValue::NoVersion; | 
					
						
							|  |  |  |         int minorVersion = QmlObjectValue::NoVersion; | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (import->versionToken.isValid()) { | 
					
						
							|  |  |  |             const QString versionString = doc->source().mid(import->versionToken.offset, import->versionToken.length); | 
					
						
							|  |  |  |             const int dotIdx = versionString.indexOf(QLatin1Char('.')); | 
					
						
							|  |  |  |             if (dotIdx == -1) { | 
					
						
							|  |  |  |                 // only major (which is probably invalid, but let's handle it anyway)
 | 
					
						
							|  |  |  |                 majorVersion = versionString.toInt(); | 
					
						
							|  |  |  |                 minorVersion = 0; // ### TODO: Check with magic version numbers above
 | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 majorVersion = versionString.left(dotIdx).toInt(); | 
					
						
							|  |  |  |                 minorVersion = versionString.mid(dotIdx + 1).toInt(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-03-01 13:01:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-03 14:31:03 +01:00
										 |  |  |         foreach (QmlObjectValue *object, engine()->metaTypeSystem().staticTypesForImport(package, majorVersion, minorVersion)) { | 
					
						
							| 
									
										
										
										
											2010-03-01 13:01:05 +01:00
										 |  |  |             namespaceObject->setProperty(object->className(), object); | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 17:06:48 +01:00
										 |  |  | UiQualifiedId *Link::qualifiedTypeNameId(Node *node) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (UiObjectBinding *binding = AST::cast<UiObjectBinding *>(node)) | 
					
						
							|  |  |  |         return binding->qualifiedTypeNameId; | 
					
						
							|  |  |  |     else if (UiObjectDefinition *binding = AST::cast<UiObjectDefinition *>(node)) | 
					
						
							|  |  |  |         return binding->qualifiedTypeNameId; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-12 11:00:12 +01:00
										 |  |  | QT_BEGIN_NAMESPACE | 
					
						
							|  |  |  | static uint qHash(Document::Ptr doc) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |     return qHash(doc.data()); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-02-12 11:00:12 +01:00
										 |  |  | QT_END_NAMESPACE | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | QList<Document::Ptr> Link::reachableDocuments(Document::Ptr startDoc, const Snapshot &snapshot) | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |     QSet<Document::Ptr> docs; | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-10 16:23:04 +01:00
										 |  |  |     if (! startDoc) | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |         return docs.values(); | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |     QMultiHash<QString, Document::Ptr> documentByPath; | 
					
						
							|  |  |  |     foreach (Document::Ptr doc, snapshot) | 
					
						
							|  |  |  |         documentByPath.insert(doc->path(), doc); | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |     // ### TODO: This doesn't scale well. Maybe just use the whole snapshot?
 | 
					
						
							|  |  |  |     // Find all documents that (indirectly) include startDoc
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QList<Document::Ptr> todo; | 
					
						
							|  |  |  |         todo += startDoc; | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |         while (! todo.isEmpty()) { | 
					
						
							|  |  |  |             Document::Ptr doc = todo.takeFirst(); | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             docs += doc; | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             Snapshot::const_iterator it, end = snapshot.end(); | 
					
						
							|  |  |  |             for (it = snapshot.begin(); it != end; ++it) { | 
					
						
							|  |  |  |                 Document::Ptr otherDoc = *it; | 
					
						
							|  |  |  |                 if (docs.contains(otherDoc)) | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 QStringList localImports = otherDoc->bind()->localImports(); | 
					
						
							|  |  |  |                 if (localImports.contains(doc->fileName()) | 
					
						
							|  |  |  |                     || localImports.contains(doc->path()) | 
					
						
							|  |  |  |                     || otherDoc->bind()->includedScripts().contains(doc->fileName()) | 
					
						
							|  |  |  |                 ) { | 
					
						
							|  |  |  |                     todo += otherDoc; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-02-02 15:55:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |     // Find all documents that are included by these (even if indirectly).
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QSet<QString> processed; | 
					
						
							|  |  |  |         QStringList todo; | 
					
						
							|  |  |  |         foreach (Document::Ptr doc, docs) | 
					
						
							|  |  |  |             todo.append(doc->fileName()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         while (! todo.isEmpty()) { | 
					
						
							|  |  |  |             QString path = todo.takeFirst(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (processed.contains(path)) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             processed.insert(path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (Document::Ptr doc = snapshot.document(path)) { | 
					
						
							|  |  |  |                 docs += doc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (doc->qmlProgram()) | 
					
						
							|  |  |  |                     path = doc->path(); | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             QStringList localImports; | 
					
						
							|  |  |  |             foreach (Document::Ptr doc, documentByPath.values(path)) { | 
					
						
							|  |  |  |                 if (doc->qmlProgram()) { | 
					
						
							|  |  |  |                     docs += doc; | 
					
						
							|  |  |  |                     localImports += doc->bind()->localImports(); | 
					
						
							|  |  |  |                     localImports += doc->bind()->includedScripts(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             localImports.removeDuplicates(); | 
					
						
							|  |  |  |             todo += localImports; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-11 18:58:17 +01:00
										 |  |  |     return docs.values(); | 
					
						
							| 
									
										
										
										
											2010-01-28 14:53:53 +01:00
										 |  |  | } |