diff --git a/src/libs/qmljs/qmljs-lib.pri b/src/libs/qmljs/qmljs-lib.pri index 53984c306336ac30f1f3d622e55b492081819e60..753619790f0c16ade33e8de332da156b2f25b39e 100644 --- a/src/libs/qmljs/qmljs-lib.pri +++ b/src/libs/qmljs/qmljs-lib.pri @@ -20,6 +20,7 @@ HEADERS += \ $$PWD/qmljslink.h \ $$PWD/qmljscheck.h \ $$PWD/qmljsscopebuilder.h \ + $$PWD/qmljslookupcontext.h \ $$PWD/qmljslineinfo.h \ $$PWD/qmljscompletioncontextfinder.h \ $$PWD/qmljscomponentversion.h \ @@ -38,6 +39,7 @@ SOURCES += \ $$PWD/qmljslink.cpp \ $$PWD/qmljscheck.cpp \ $$PWD/qmljsscopebuilder.cpp \ + $$PWD/qmljslookupcontext.cpp \ $$PWD/qmljslineinfo.cpp \ $$PWD/qmljscompletioncontextfinder.cpp \ $$PWD/qmljscomponentversion.cpp \ diff --git a/src/libs/qmljs/qmljslookupcontext.cpp b/src/libs/qmljs/qmljslookupcontext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b8e333754f6c39f14b042041993bcff36edd331 --- /dev/null +++ b/src/libs/qmljs/qmljslookupcontext.cpp @@ -0,0 +1,88 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "qmljslookupcontext.h" +#include "qmljsinterpreter.h" +#include "qmljslink.h" +#include "qmljsscopebuilder.h" +#include "qmljsmodelmanagerinterface.h" +#include "qmljsevaluate.h" + +using namespace QmlJS; + +class QmlJS::LookupContextData +{ +public: + LookupContextData(Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path) + : context(&interp), + doc(doc), + snapshot(snapshot), + link(&context, doc, snapshot, ModelManagerInterface::instance()->importPaths()) + { + ScopeBuilder scopeBuilder(doc, &context); + scopeBuilder.push(path); + } + + Interpreter::Engine interp; + Interpreter::Context context; + Document::Ptr doc; + Snapshot snapshot; + Link link; +}; + +LookupContext::LookupContext(Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path) + : d(new LookupContextData(doc, snapshot, path)) +{ +} + +LookupContext::~LookupContext() +{ +} + +LookupContext::Ptr LookupContext::create(Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path) +{ + Ptr ptr(new LookupContext(doc, snapshot, path)); + return ptr; +} + +const Interpreter::Value *LookupContext::evaluate(AST::Node *node) const +{ + Evaluate check(&d->context); + return check(node); +} + +Interpreter::Engine *LookupContext::engine() const +{ + return &d->interp; +} + +Interpreter::Context *LookupContext::context() const +{ + return &d->context; +} diff --git a/src/libs/qmljs/qmljslookupcontext.h b/src/libs/qmljs/qmljslookupcontext.h new file mode 100644 index 0000000000000000000000000000000000000000..0ab35b99b3ddd051978d39da6f3f397980f1a88d --- /dev/null +++ b/src/libs/qmljs/qmljslookupcontext.h @@ -0,0 +1,72 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QMLJSLOOKUPCONTEXT_H +#define QMLJSLOOKUPCONTEXT_H + +#include "qmljsdocument.h" +#include "parser/qmljsastfwd_p.h" + +#include <QtCore/QSharedPointer> +#include <QtCore/QScopedPointer> + +namespace QmlJS { + +class LookupContextData; + +namespace Interpreter { +class Value; +class Engine; +class Context; +} + +class QMLJS_EXPORT LookupContext +{ + LookupContext(const Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path); + +public: + ~LookupContext(); + + typedef QSharedPointer<LookupContext> Ptr; + + static Ptr create(const Document::Ptr doc, const Snapshot &snapshot, + const QList<AST::Node *> &path); + + const Interpreter::Value *evaluate(AST::Node *node) const; + Interpreter::Engine *engine() const; + Interpreter::Context *context() const; + +private: + QScopedPointer<LookupContextData> d; +}; + +} // end of namespace QmlJS + +#endif // QMLJSLOOKUPCONTEXT_H + diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp index 90917547f54b1d36d3bc88d62e957724063837fc..fbd340587e3a28914dab7fb66d81cc0ccb39c051 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp @@ -31,12 +31,20 @@ using namespace QmlJS; +static ModelManagerInterface *g_instance = 0; + ModelManagerInterface::ModelManagerInterface(QObject *parent) : QObject(parent) { + Q_ASSERT(! g_instance); + g_instance = this; } ModelManagerInterface::~ModelManagerInterface() { } +ModelManagerInterface *ModelManagerInterface::instance() +{ + return g_instance; +} diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h index bf00b137453389bec4e3213cd9f4871f26aab5f8..7cd4e9bc47dbaaef30af0fab8c42aa168d8c1fb7 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.h +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h @@ -80,6 +80,8 @@ public: ModelManagerInterface(QObject *parent = 0); virtual ~ModelManagerInterface(); + static ModelManagerInterface *instance(); + virtual QmlJS::Snapshot snapshot() const = 0; virtual void updateSourceFiles(const QStringList &files, bool emitDocumentOnDiskChanged) = 0; diff --git a/src/plugins/qmljseditor/qmljscodecompletion.cpp b/src/plugins/qmljseditor/qmljscodecompletion.cpp index 7a6e413858b5fecc26be21368dd6815fcd2c43a0..1bd3c77a52fc4fd020ff7170400a0c226a72ac9a 100644 --- a/src/plugins/qmljseditor/qmljscodecompletion.cpp +++ b/src/plugins/qmljseditor/qmljscodecompletion.cpp @@ -33,12 +33,10 @@ #include <qmljs/qmljsmodelmanagerinterface.h> #include <qmljs/parser/qmljsast_p.h> -#include <qmljs/qmljsbind.h> #include <qmljs/qmljsinterpreter.h> +#include <qmljs/qmljslookupcontext.h> #include <qmljs/qmljsscanner.h> -#include <qmljs/qmljsevaluate.h> #include <qmljs/qmljscompletioncontextfinder.h> -#include <qmljs/qmljslink.h> #include <qmljs/qmljsscopebuilder.h> #include <texteditor/basetexteditor.h> @@ -689,13 +687,9 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor) const QIcon symbolIcon = iconForColor(Qt::darkCyan); const QIcon keywordIcon = iconForColor(Qt::darkYellow); - Interpreter::Engine interp; - Interpreter::Context context(&interp); - Link link(&context, document, snapshot, m_modelManager->importPaths()); - - // Set up the current scope chain. - ScopeBuilder scopeBuilder(document, &context); - scopeBuilder.push(semanticInfo.astPath(editor->position())); + const QList<AST::Node *> path = semanticInfo.astPath(editor->position()); + LookupContext::Ptr lookupContext = LookupContext::create(document, snapshot, path); + Interpreter::Context *context = lookupContext->context(); // Search for the operator that triggered the completion. QChar completionOperator; @@ -708,7 +702,7 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor) const Interpreter::ObjectValue *qmlScopeType = 0; if (contextFinder.isInQmlContext()) - qmlScopeType = context.lookupType(document.data(), contextFinder.qmlObjectTypeName()); + qmlScopeType = context->lookupType(document.data(), contextFinder.qmlObjectTypeName()); if (completionOperator.isSpace() || completionOperator.isNull() || isDelimiter(completionOperator) || (completionOperator == QLatin1Char('(') && m_startPosition != editor->position())) { @@ -721,7 +715,7 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor) doGlobalCompletion = false; doJsKeywordCompletion = false; - EnumerateProperties enumerateProperties(&context); + EnumerateProperties enumerateProperties(context); enumerateProperties.setGlobalCompletion(true); enumerateProperties.setEnumerateGeneratedSlots(true); @@ -733,11 +727,11 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor) m_completions.append(idPropertyCompletion); addCompletionsPropertyLhs(enumerateProperties(qmlScopeType), symbolIcon, PropertyOrder); - addCompletions(enumerateProperties(context.scopeChain().qmlTypes), symbolIcon, TypeOrder); + addCompletions(enumerateProperties(context->scopeChain().qmlTypes), symbolIcon, TypeOrder); - if (ScopeBuilder::isPropertyChangesObject(&context, qmlScopeType) - && context.scopeChain().qmlScopeObjects.size() == 2) { - addCompletions(enumerateProperties(context.scopeChain().qmlScopeObjects.first()), symbolIcon, SymbolOrder); + if (ScopeBuilder::isPropertyChangesObject(context, qmlScopeType) + && context->scopeChain().qmlScopeObjects.size() == 2) { + addCompletions(enumerateProperties(context->scopeChain().qmlScopeObjects.first()), symbolIcon, SymbolOrder); } } @@ -748,7 +742,7 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor) const Interpreter::Value *value = qmlScopeType; foreach (const QString &name, contextFinder.bindingPropertyName()) { if (const Interpreter::ObjectValue *objectValue = value->asObjectValue()) { - value = objectValue->property(name, &context); + value = objectValue->property(name, context); if (!value) break; } else { @@ -772,7 +766,7 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor) if (doGlobalCompletion) { // It's a global completion. - EnumerateProperties enumerateProperties(&context); + EnumerateProperties enumerateProperties(context); enumerateProperties.setGlobalCompletion(true); addCompletions(enumerateProperties(), symbolIcon, SymbolOrder); } @@ -813,14 +807,13 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor) QmlJS::AST::ExpressionNode *expression = expressionUnderCursor(tc); if (expression != 0 && ! isLiteral(expression)) { - Evaluate evaluate(&context); - // Evaluate the expression under cursor. - const Interpreter::Value *value = interp.convertToObject(evaluate(expression)); + Interpreter::Engine *interp = lookupContext->engine(); + const Interpreter::Value *value = interp->convertToObject(lookupContext->evaluate(expression)); //qDebug() << "type:" << interp.typeId(value); if (value && completionOperator == QLatin1Char('.')) { // member completion - EnumerateProperties enumerateProperties(&context); + EnumerateProperties enumerateProperties(context); if (contextFinder.isInLhsOfBinding() && qmlScopeType && expressionUnderCursor.text().at(0).isLower()) addCompletionsPropertyLhs(enumerateProperties(value), symbolIcon, PropertyOrder); else diff --git a/src/plugins/qmljseditor/qmljshoverhandler.cpp b/src/plugins/qmljseditor/qmljshoverhandler.cpp index 31e923b40c24f4d88548d1381f14fb6d8122af59..88d1326a59d8d504f5394b691c0844ac605dfebd 100644 --- a/src/plugins/qmljseditor/qmljshoverhandler.cpp +++ b/src/plugins/qmljseditor/qmljshoverhandler.cpp @@ -37,11 +37,8 @@ #include <coreplugin/editormanager/editormanager.h> #include <debugger/debuggerconstants.h> #include <extensionsystem/pluginmanager.h> -#include <qmljs/qmljsbind.h> -#include <qmljs/qmljsevaluate.h> +#include <qmljs/qmljslookupcontext.h> #include <qmljs/qmljsinterpreter.h> -#include <qmljs/qmljslink.h> -#include <qmljs/qmljsscopebuilder.h> #include <qmljs/parser/qmljsast_p.h> #include <texteditor/itexteditor.h> #include <texteditor/basetexteditor.h> @@ -151,17 +148,11 @@ void HoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, int p if (node && !(AST::cast<AST::StringLiteral *>(node) != 0 || AST::cast<AST::NumericLiteral *>(node) != 0)) { QList<AST::Node *> astPath = semanticInfo.astPath(pos); - Interpreter::Engine interp; - Interpreter::Context context(&interp); - Link link(&context, qmlDocument, snapshot, m_modelManager->importPaths()); - ScopeBuilder scopeBuilder(qmlDocument, &context); - scopeBuilder.push(astPath); - - Evaluate check(&context); - const Interpreter::Value *value = check(node); + LookupContext::Ptr lookupContext = LookupContext::create(qmlDocument, snapshot, astPath); + const Interpreter::Value *value = lookupContext->evaluate(node); QStringList baseClasses; - m_toolTip = prettyPrint(value, &context, &baseClasses); + m_toolTip = prettyPrint(value, lookupContext->context(), &baseClasses); foreach (const QString &baseClass, baseClasses) { QString helpId = QLatin1String("QML."); @@ -193,7 +184,7 @@ void HoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, int p } QString HoverHandler::prettyPrint(const QmlJS::Interpreter::Value *value, QmlJS::Interpreter::Context *context, - QStringList *baseClasses) const + QStringList *baseClasses) const { if (! value) return QString();