diff options
author | Christian Kamm <christian.d.kamm@nokia.com> | 2010-09-24 14:05:34 +0200 |
---|---|---|
committer | Christian Kamm <christian.d.kamm@nokia.com> | 2010-09-24 14:11:06 +0200 |
commit | 3f505e9982e2a07ce41e650d9ae547c436f12a43 (patch) | |
tree | f1c88bc932678aebc7054d7429f4d30acc66bced /src/libs/qmljs/qmljsscopebuilder.cpp | |
parent | 6755edc351c466262b872fed6f136a8159ece058 (diff) | |
download | qt-creator-3f505e9982e2a07ce41e650d9ae547c436f12a43.tar.gz |
QmlJS: Add initial 'Find Usages' support.
Diffstat (limited to 'src/libs/qmljs/qmljsscopebuilder.cpp')
-rw-r--r-- | src/libs/qmljs/qmljsscopebuilder.cpp | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/src/libs/qmljs/qmljsscopebuilder.cpp b/src/libs/qmljs/qmljsscopebuilder.cpp index ceffa41b4b..d1c9374b1d 100644 --- a/src/libs/qmljs/qmljsscopebuilder.cpp +++ b/src/libs/qmljs/qmljsscopebuilder.cpp @@ -38,10 +38,12 @@ using namespace QmlJS; using namespace QmlJS::Interpreter; using namespace QmlJS::AST; -ScopeBuilder::ScopeBuilder(Document::Ptr doc, Interpreter::Context *context) +ScopeBuilder::ScopeBuilder(Context *context, Document::Ptr doc, const Snapshot &snapshot) : _doc(doc) + , _snapshot(snapshot) , _context(context) { + initializeScopeChain(); } ScopeBuilder::~ScopeBuilder() @@ -92,6 +94,85 @@ void ScopeBuilder::pop() _context->scopeChain().update(); } +void ScopeBuilder::initializeScopeChain() +{ + ScopeChain &scopeChain = _context->scopeChain(); + scopeChain = ScopeChain(); // reset + + Interpreter::Engine *engine = _context->engine(); + + // ### TODO: This object ought to contain the global namespace additions by QML. + scopeChain.globalScope = engine->globalObject(); + + if (! _doc) { + scopeChain.update(); + return; + } + + Bind *bind = _doc->bind(); + QHash<Document *, ScopeChain::QmlComponentChain *> componentScopes; + + ScopeChain::QmlComponentChain *chain = new ScopeChain::QmlComponentChain; + scopeChain.qmlComponentScope = QSharedPointer<const ScopeChain::QmlComponentChain>(chain); + if (_doc->qmlProgram()) { + componentScopes.insert(_doc.data(), chain); + makeComponentChain(_doc, chain, &componentScopes); + + if (const TypeEnvironment *typeEnvironment = _context->typeEnvironment(_doc.data())) + scopeChain.qmlTypes = typeEnvironment; + } else { + // add scope chains for all components that import this file + foreach (Document::Ptr otherDoc, _snapshot) { + foreach (const ImportInfo &import, otherDoc->bind()->imports()) { + if (import.type() == ImportInfo::FileImport && _doc->fileName() == import.name()) { + ScopeChain::QmlComponentChain *component = new ScopeChain::QmlComponentChain; + componentScopes.insert(otherDoc.data(), component); + chain->instantiatingComponents += component; + makeComponentChain(otherDoc, component, &componentScopes); + } + } + } + + // ### TODO: Which type environment do scripts see? + + if (bind->rootObjectValue()) + scopeChain.jsScopes += bind->rootObjectValue(); + } + + scopeChain.update(); +} + +void ScopeBuilder::makeComponentChain( + Document::Ptr doc, + ScopeChain::QmlComponentChain *target, + QHash<Document *, ScopeChain::QmlComponentChain *> *components) +{ + if (!doc->qmlProgram()) + return; + + Bind *bind = doc->bind(); + + // add scopes for all components instantiating this one + foreach (Document::Ptr otherDoc, _snapshot) { + if (otherDoc == doc) + continue; + if (otherDoc->bind()->usesQmlPrototype(bind->rootObjectValue(), _context)) { + if (components->contains(otherDoc.data())) { +// target->instantiatingComponents += components->value(otherDoc.data()); + } else { + ScopeChain::QmlComponentChain *component = new ScopeChain::QmlComponentChain; + components->insert(otherDoc.data(), component); + target->instantiatingComponents += component; + + makeComponentChain(otherDoc, component, components); + } + } + } + + // build this component scope + target->document = doc; +} + void ScopeBuilder::setQmlScopeObject(Node *node) { ScopeChain &scopeChain = _context->scopeChain(); |