diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp index 7a1f7e3bf0405e7bac2467ee24acc196697ac838..147852fe3251bdc3f8f2737880ee84eba14e2c2d 100644 --- a/src/libs/qmljs/qmljscheck.cpp +++ b/src/libs/qmljs/qmljscheck.cpp @@ -157,10 +157,9 @@ public: Check::Check(Document::Ptr doc, const Snapshot &snapshot, const QStringList &importPaths) : _doc(doc) , _snapshot(snapshot) - , _context(&_engine) , _link(&_context, doc, snapshot, importPaths) , _scopeBuilder(doc, &_context) - , _ignoreTypeErrors(_context.documentImportsPlugins(_doc.data())) + , _ignoreTypeErrors(false) { } diff --git a/src/libs/qmljs/qmljscheck.h b/src/libs/qmljs/qmljscheck.h index a6fddba361fd2d1211b98455cf73be5ead36a943..918d62fd588dec5f3b436c779e0f162e1d7efed1 100644 --- a/src/libs/qmljs/qmljscheck.h +++ b/src/libs/qmljs/qmljscheck.h @@ -71,7 +71,6 @@ private: Document::Ptr _doc; Snapshot _snapshot; - Interpreter::Engine _engine; Interpreter::Context _context; Link _link; ScopeBuilder _scopeBuilder; diff --git a/src/libs/qmljs/qmljsicontextpane.h b/src/libs/qmljs/qmljsicontextpane.h index ccb176ad261200e47cbf02a9971fa2f8ed31873c..759af9a2f52f2bb086fbb36ee96f00fa9213f268 100644 --- a/src/libs/qmljs/qmljsicontextpane.h +++ b/src/libs/qmljs/qmljsicontextpane.h @@ -33,7 +33,7 @@ #include <QObject> #include "qmljs_global.h" #include <qmljs/parser/qmljsastfwd_p.h> -#include <qmljs/qmljsdocument.h> +#include <qmljs/qmljslookupcontext.h> namespace TextEditor { @@ -52,9 +52,9 @@ class QMLJS_EXPORT IContextPane : public QObject public: IContextPane(QObject *parent = 0) : QObject(parent) {} virtual ~IContextPane() {} - virtual void apply(TextEditor::BaseTextEditorEditable *editor, Document::Ptr doc, const QmlJS::Snapshot &snapshot, AST::Node *node, bool update, bool force = false) = 0; + virtual void apply(TextEditor::BaseTextEditorEditable *editor, LookupContext::Ptr lookupContext, AST::Node *node, bool update, bool force = false) = 0; virtual void setEnabled(bool) = 0; - virtual bool isAvailable(TextEditor::BaseTextEditorEditable *editor, Document::Ptr doc, const QmlJS::Snapshot &snapshot, AST::Node *node) = 0; + virtual bool isAvailable(TextEditor::BaseTextEditorEditable *editor, LookupContext::Ptr lookupContext, AST::Node *node) = 0; virtual QWidget* widget() = 0; signals: void closed(); diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index 61770b747936a6e27afa2cab8c8c966c929a8029..e47e4c1fadb03d42c607b69b01a559dbd218de17 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -1419,8 +1419,8 @@ QList<const ObjectValue *> ScopeChain::all() const } -Context::Context(Engine *engine) - : _engine(engine), +Context::Context() + : _engine(new Engine), _qmlScopeObjectIndex(-1), _qmlScopeObjectSet(false) { @@ -1430,9 +1430,10 @@ Context::~Context() { } +// the engine is only guaranteed to live as long as the context Engine *Context::engine() const { - return _engine; + return _engine.data(); } const ScopeChain &Context::scopeChain() const @@ -1530,7 +1531,7 @@ void Context::setProperty(const ObjectValue *object, const QString &name, const _properties[object].insert(name, value); } -QString Context::defaultPropertyName(const ObjectValue *object) +QString Context::defaultPropertyName(const ObjectValue *object) const { for (const ObjectValue *o = object; o; o = o->prototype(this)) { if (const ASTObjectValue *astObjValue = dynamic_cast<const ASTObjectValue *>(o)) { @@ -1544,16 +1545,6 @@ QString Context::defaultPropertyName(const ObjectValue *object) return QString(); } -bool Context::documentImportsPlugins(const QmlJS::Document *doc) const -{ - return _documentsImportingPlugins.contains(doc->fileName()); -} - -void Context::setDocumentImportsPlugins(const QmlJS::Document *doc) -{ - _documentsImportingPlugins.insert(doc->fileName()); -} - Reference::Reference(Engine *engine) : _engine(engine) { diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index 201b89cb009badeca1b70b9553ddd149d2758707..5ec91c009d5a48d8dc23452e1a4318e7fa90d32a 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -271,7 +271,7 @@ private: class QMLJS_EXPORT Context { public: - Context(Engine *engine); + Context(); ~Context(); Engine *engine() const; @@ -289,18 +289,14 @@ public: const Value *property(const ObjectValue *object, const QString &name) const; void setProperty(const ObjectValue *object, const QString &name, const Value *value); - QString defaultPropertyName(const ObjectValue *object); - - bool documentImportsPlugins(const Document *doc) const; - void setDocumentImportsPlugins(const Document *doc); + QString defaultPropertyName(const ObjectValue *object) const; private: typedef QHash<QString, const Value *> Properties; - Engine *_engine; + QSharedPointer<Engine> _engine; QHash<const ObjectValue *, Properties> _properties; QHash<QString, const ObjectValue *> _typeEnvironments; - QSet<QString> _documentsImportingPlugins; ScopeChain _scopeChain; int _qmlScopeObjectIndex; bool _qmlScopeObjectSet; @@ -628,8 +624,7 @@ protected: class QMLJS_EXPORT Engine { - Engine(const Engine &other); - void operator = (const Engine &other); + Q_DISABLE_COPY(Engine) public: Engine(); diff --git a/src/libs/qmljs/qmljslookupcontext.cpp b/src/libs/qmljs/qmljslookupcontext.cpp index 30fafb7f17ff2e8480901f760ef09d417455be0f..d943948107675aec392c967ba3db27ae66600eca 100644 --- a/src/libs/qmljs/qmljslookupcontext.cpp +++ b/src/libs/qmljs/qmljslookupcontext.cpp @@ -40,20 +40,30 @@ class QmlJS::LookupContextData { public: LookupContextData(Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path) - : context(&interp), + : doc(doc), + snapshot(snapshot) + { + // since we keep the document and snapshot around, we don't need to keep the Link instance + Link link(&context, doc, snapshot, ModelManagerInterface::instance()->importPaths()); + + ScopeBuilder scopeBuilder(doc, &context); + scopeBuilder.push(path); + } + + LookupContextData(Document::Ptr doc, const Snapshot &snapshot, + const Interpreter::Context &linkedContextWithoutScope, + const QList<AST::Node *> &path) + : context(linkedContextWithoutScope), doc(doc), - snapshot(snapshot), - link(&context, doc, snapshot, ModelManagerInterface::instance()->importPaths()) + snapshot(snapshot) { 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) @@ -61,6 +71,13 @@ LookupContext::LookupContext(Document::Ptr doc, const Snapshot &snapshot, const { } +LookupContext::LookupContext(const Document::Ptr doc, const Snapshot &snapshot, + const Interpreter::Context &linkedContextWithoutScope, + const QList<AST::Node *> &path) + : d(new LookupContextData(doc, snapshot, linkedContextWithoutScope, path)) +{ +} + LookupContext::~LookupContext() { } @@ -71,17 +88,37 @@ LookupContext::Ptr LookupContext::create(Document::Ptr doc, const Snapshot &snap return ptr; } +LookupContext::Ptr LookupContext::create(const Document::Ptr doc, const Snapshot &snapshot, + const Interpreter::Context &linkedContextWithoutScope, + const QList<AST::Node *> &path) +{ + Ptr ptr(new LookupContext(doc, snapshot, linkedContextWithoutScope, path)); + return ptr; +} + const Interpreter::Value *LookupContext::evaluate(AST::Node *node) const { Evaluate check(&d->context); return check(node); } +Document::Ptr LookupContext::document() const +{ + return d->doc; +} + +Snapshot LookupContext::snapshot() const +{ + return d->snapshot; +} + +// the engine is only guaranteed to live as long as the LookupContext Interpreter::Engine *LookupContext::engine() const { - return &d->interp; + return d->context.engine(); } +// the context is only guaranteed to live as long as the LookupContext const Interpreter::Context *LookupContext::context() const { return &d->context; diff --git a/src/libs/qmljs/qmljslookupcontext.h b/src/libs/qmljs/qmljslookupcontext.h index ca93b43aa9ac35dfc8dbb74697c7881f7df3712f..b4736c7abc76269b74baff8498e2cfdc7e3f0d82 100644 --- a/src/libs/qmljs/qmljslookupcontext.h +++ b/src/libs/qmljs/qmljslookupcontext.h @@ -31,6 +31,7 @@ #define QMLJSLOOKUPCONTEXT_H #include "qmljsdocument.h" +#include "qmljsinterpreter.h" #include "parser/qmljsastfwd_p.h" #include <QtCore/QSharedPointer> @@ -42,23 +43,34 @@ class LookupContextData; namespace Interpreter { class Value; -class Engine; class Context; } class QMLJS_EXPORT LookupContext { + Q_DISABLE_COPY(LookupContext) + LookupContext(const Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path); + LookupContext(const Document::Ptr doc, const Snapshot &snapshot, + const Interpreter::Context &linkedContextWithoutScope, + const QList<AST::Node *> &path); public: ~LookupContext(); typedef QSharedPointer<LookupContext> Ptr; + // consider using SemanticInfo::lookupContext instead, it's faster + static Ptr create(const Document::Ptr doc, const Snapshot &snapshot, + const QList<AST::Node *> &path); static Ptr create(const Document::Ptr doc, const Snapshot &snapshot, + const Interpreter::Context &linkedContextWithoutScope, const QList<AST::Node *> &path); const Interpreter::Value *evaluate(AST::Node *node) const; + + Document::Ptr document() const; + Snapshot snapshot() const; Interpreter::Engine *engine() const; const Interpreter::Context *context() const; diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index af5b789c83832a38b4f62a5eb4a9362ce84ed4ac..97184c979250eb80014ec59a693490fe11db3b6d 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -187,15 +187,14 @@ public: const QStringList importPaths) : m_snapshot(snapshot) , m_doc(doc) - , m_engine(new Interpreter::Engine) - , m_context(new Interpreter::Context(m_engine)) + , m_context(new Interpreter::Context) , m_link(m_context, doc, snapshot, importPaths) , m_scopeBuilder(doc, m_context) { } ~ReadingContext() - { delete m_context; delete m_engine; } + { delete m_context; } Document::Ptr doc() const { return m_doc; } @@ -328,11 +327,11 @@ public: if (!value) return false; const Interpreter::ObjectValue *objectValue = value->asObjectValue(); - if (objectValue && objectValue->prototype(m_context) == m_engine->arrayPrototype()) + if (objectValue && objectValue->prototype(m_context) == m_context->engine()->arrayPrototype()) return true; for (const Interpreter::ObjectValue *iter = containingObject; iter; iter = iter->prototype(m_context)) { - if (iter->property(name, m_context) == m_engine->arrayPrototype()) + if (iter->property(name, m_context) == m_context->engine()->arrayPrototype()) return true; if (const Interpreter::QmlObjectValue *qmlIter = dynamic_cast<const Interpreter::QmlObjectValue *>(iter)) { if (qmlIter->isListProperty(name)) @@ -451,7 +450,6 @@ public: private: Snapshot m_snapshot; Document::Ptr m_doc; - Interpreter::Engine *m_engine; Interpreter::Context *m_context; Link m_link; ScopeBuilder m_scopeBuilder; diff --git a/src/plugins/qmljseditor/qmljscodecompletion.cpp b/src/plugins/qmljseditor/qmljscodecompletion.cpp index d2222860a9ee3a451df9745f1f0e20ef53923fe4..c85d3e44b3fb5d2d3b03569109358f8c562704ee 100644 --- a/src/plugins/qmljseditor/qmljscodecompletion.cpp +++ b/src/plugins/qmljseditor/qmljscodecompletion.cpp @@ -691,7 +691,7 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor) const QIcon keywordIcon = iconForColor(Qt::darkYellow); const QList<AST::Node *> path = semanticInfo.astPath(editor->position()); - LookupContext::Ptr lookupContext = LookupContext::create(document, snapshot, path); + LookupContext::Ptr lookupContext = semanticInfo.lookupContext(path); const Interpreter::Context *context = lookupContext->context(); // Search for the operator that triggered the completion. diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index 605b459e620f06da1a8bb083b3661fc6b0a3a9df..c2cb5610d5568e2dbd2a07dd9e090a9862969641 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -40,6 +40,7 @@ #include <qmljs/qmljsdocument.h> #include <qmljs/qmljsicontextpane.h> #include <qmljs/qmljslookupcontext.h> +#include <qmljs/qmljslink.h> #include <qmljs/parser/qmljsastvisitor_p.h> #include <qmljs/parser/qmljsast_p.h> #include <qmljs/parser/qmljsengine_p.h> @@ -553,6 +554,18 @@ QList<AST::Node *> SemanticInfo::astPath(int cursorPosition) const return path; } +LookupContext::Ptr SemanticInfo::lookupContext(const QList<QmlJS::AST::Node *> &path) const +{ + // create and link context if necessary + if (!m_context) { + Interpreter::Context *ctx = new Interpreter::Context; + Link link(ctx, document, snapshot, ModelManagerInterface::instance()->importPaths()); + m_context = QSharedPointer<const QmlJS::Interpreter::Context>(ctx); + } + + return LookupContext::create(document, snapshot, *m_context, path); +} + static bool importContainsCursor(UiImport *importAst, unsigned cursorPosition) { return cursorPosition >= importAst->firstSourceLocation().begin() @@ -962,9 +975,9 @@ void QmlJSTextEditor::updateCursorPositionNow() Node *oldNode = m_semanticInfo.declaringMemberNoProperties(m_oldCursorPosition); Node *newNode = m_semanticInfo.declaringMemberNoProperties(position()); if (oldNode != newNode && m_oldCursorPosition != -1) - m_contextPane->apply(editableInterface(), m_semanticInfo.document, m_semanticInfo.snapshot, newNode, false); + m_contextPane->apply(editableInterface(), m_semanticInfo.lookupContext(), newNode, false); if (oldNode != newNode && - m_contextPane->isAvailable(editableInterface(), m_semanticInfo.document, m_semanticInfo.snapshot, newNode) && + m_contextPane->isAvailable(editableInterface(), m_semanticInfo.lookupContext(), newNode) && !m_contextPane->widget()->isVisible()) { QList<TextEditor::Internal::RefactorMarker> markers; if (UiObjectMember *m = newNode->uiObjectMemberCast()) { @@ -1042,22 +1055,19 @@ class SelectedElement: protected Visitor unsigned m_cursorPositionStart; unsigned m_cursorPositionEnd; QList<UiObjectMember *> m_selectedMembers; - Document::Ptr m_document; - Snapshot m_snapshot; LookupContext::Ptr m_lookupContext; public: SelectedElement() : m_cursorPositionStart(0), m_cursorPositionEnd(0) {} - QList<UiObjectMember *> operator()(Document::Ptr doc, Snapshot snapshot, unsigned startPosition, unsigned endPosition) + QList<UiObjectMember *> operator()(LookupContext::Ptr lookupContext, unsigned startPosition, unsigned endPosition) { - m_document = doc; - m_snapshot = snapshot; + m_lookupContext = lookupContext; m_cursorPositionStart = startPosition; m_cursorPositionEnd = endPosition; m_selectedMembers.clear(); - Node::accept(doc->qmlProgram(), this); + Node::accept(lookupContext->document()->qmlProgram(), this); return m_selectedMembers; } @@ -1092,14 +1102,10 @@ protected: inline bool hasVisualPresentation(Node *ast) { - Bind *bind = m_document->bind(); + Bind *bind = m_lookupContext->document()->bind(); const Interpreter::ObjectValue *objValue = bind->findQmlObject(ast); QStringList prototypes; - if (m_lookupContext.isNull()) { - m_lookupContext = LookupContext::create(m_document, m_snapshot, QList<Node*>()); - } - while (objValue) { prototypes.append(objValue->className()); objValue = objValue->prototype(m_lookupContext->context()); @@ -1189,7 +1195,7 @@ void QmlJSTextEditor::setSelectedElements() if (m_semanticInfo.document) { SelectedElement selectedMembers; - QList<UiObjectMember *> members = selectedMembers(m_semanticInfo.document, m_semanticInfo.snapshot, + QList<UiObjectMember *> members = selectedMembers(m_semanticInfo.lookupContext(), startPos, endPos); if (!members.isEmpty()) { foreach(UiObjectMember *m, members) { @@ -1376,7 +1382,7 @@ TextEditor::BaseTextEditor::Link QmlJSTextEditor::findLinkAt(const QTextCursor & return Link(); } - LookupContext::Ptr lookupContext = LookupContext::create(semanticInfo.document, semanticInfo.snapshot, semanticInfo.astPath(cursorPosition)); + LookupContext::Ptr lookupContext = semanticInfo.lookupContext(semanticInfo.astPath(cursorPosition)); const Interpreter::Value *value = lookupContext->evaluate(node); QString fileName; @@ -1422,7 +1428,7 @@ void QmlJSTextEditor::showContextPane() { if (m_contextPane) { Node *newNode = m_semanticInfo.declaringMemberNoProperties(position()); - m_contextPane->apply(editableInterface(), m_semanticInfo.document, m_semanticInfo.snapshot, newNode, false, true); + m_contextPane->apply(editableInterface(), m_semanticInfo.lookupContext(), newNode, false, true); m_oldCursorPosition = position(); QList<TextEditor::Internal::RefactorMarker> markers; setRefactorMarkers(markers); @@ -1481,7 +1487,7 @@ void QmlJSTextEditor::wheelEvent(QWheelEvent *event) BaseTextEditor::wheelEvent(event); if (visible) - m_contextPane->apply(editableInterface(), m_semanticInfo.document, m_semanticInfo.snapshot, m_semanticInfo.declaringMemberNoProperties(position()), false, true); + m_contextPane->apply(editableInterface(), m_semanticInfo.lookupContext(), m_semanticInfo.declaringMemberNoProperties(position()), false, true); } void QmlJSTextEditor::resizeEvent(QResizeEvent *event) @@ -1723,7 +1729,7 @@ void QmlJSTextEditor::updateSemanticInfo(const SemanticInfo &semanticInfo) if (m_contextPane) { Node *newNode = m_semanticInfo.declaringMemberNoProperties(position()); if (newNode) { - m_contextPane->apply(editableInterface(), doc, m_semanticInfo.snapshot, newNode, true); + m_contextPane->apply(editableInterface(), m_semanticInfo.lookupContext(), newNode, true); showTextMarker(); } } @@ -1776,7 +1782,7 @@ bool QmlJSTextEditor::hideContextPane() { bool b = (m_contextPane) && m_contextPane->widget()->isVisible(); if (b) - m_contextPane->apply(editableInterface(), m_semanticInfo.document, m_semanticInfo.snapshot, 0, false); + m_contextPane->apply(editableInterface(), m_semanticInfo.lookupContext(), 0, false); return b; } diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h index 058f5e6bd489c5325421aa2f0a64fcdd1639bae2..7e3c4efa0d52ca6a60e23906707606dfc4059b72 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -34,6 +34,7 @@ #include <qmljs/qmljsdocument.h> #include <qmljs/qmljsscanner.h> +#include <qmljs/qmljsinterpreter.h> #include <texteditor/basetexteditor.h> #include <QtCore/QWaitCondition> @@ -53,6 +54,7 @@ class ICore; namespace QmlJS { class ModelManagerInterface; class IContextPane; + class LookupContext; } /*! @@ -129,6 +131,9 @@ public: // Returns the list of nodes that enclose the given position. QList<QmlJS::AST::Node *> astPath(int cursorPosition) const; + // Returns a context for the given path + QSharedPointer<QmlJS::LookupContext> lookupContext(const QList<QmlJS::AST::Node *> &path = QList<QmlJS::AST::Node *>()) const; + public: // attributes QmlJS::Document::Ptr document; QmlJS::Snapshot snapshot; @@ -138,6 +143,10 @@ public: // attributes // these are in addition to the parser messages in the document QList<QmlJS::DiagnosticMessage> semanticMessages; + +private: + // created lazily + mutable QSharedPointer<const QmlJS::Interpreter::Context> m_context; }; class SemanticHighlighter: public QThread diff --git a/src/plugins/qmljseditor/qmljshoverhandler.cpp b/src/plugins/qmljseditor/qmljshoverhandler.cpp index 3d929d93d9ac6d58e143af8a9b7afe436be3352a..2e95585b92f2f228f9d17a22398fb2f40f250278 100644 --- a/src/plugins/qmljseditor/qmljshoverhandler.cpp +++ b/src/plugins/qmljseditor/qmljshoverhandler.cpp @@ -111,9 +111,8 @@ void HoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos) if (astPath.isEmpty()) return; - const Snapshot &snapshot = semanticInfo.snapshot; const Document::Ptr qmlDocument = semanticInfo.document; - LookupContext::Ptr lookupContext = LookupContext::create(qmlDocument, snapshot, astPath); + LookupContext::Ptr lookupContext = semanticInfo.lookupContext(astPath); if (!matchColorItem(lookupContext, qmlDocument, astPath, pos)) handleOrdinaryMatch(lookupContext, semanticInfo.nodeUnderCursor(pos)); diff --git a/src/plugins/qmljseditor/qmloutlinemodel.cpp b/src/plugins/qmljseditor/qmloutlinemodel.cpp index 7b2d9bf7e59581d0ae6ce44bafe713dde4bb1a10..8d9186c27edb676bc7e5b9d40bb4878c34ad4594 100644 --- a/src/plugins/qmljseditor/qmloutlinemodel.cpp +++ b/src/plugins/qmljseditor/qmloutlinemodel.cpp @@ -42,10 +42,7 @@ QVariant QmlOutlineItem::data(int role) const return QVariant(); QList<AST::Node *> astPath = m_outlineModel->m_semanticInfo.astPath(location.begin()); - - Document::Ptr document = m_outlineModel->m_semanticInfo.document; - Snapshot snapshot = m_outlineModel->m_semanticInfo.snapshot; - LookupContext::Ptr lookupContext = LookupContext::create(document, snapshot, astPath); + LookupContext::Ptr lookupContext = m_outlineModel->m_semanticInfo.lookupContext(astPath); const Interpreter::Value *value = lookupContext->evaluate(uiQualifiedId); return prettyPrint(value, lookupContext->context()); @@ -331,10 +328,9 @@ void QmlOutlineModel::update(const SemanticInfo &semanticInfo) // Set up lookup context once to do the element type lookup // - // We're simplifying here by using the root context everywhere - // (empty node list). However, creating the LookupContext is quite expensive (about 3ms), - // and there is AFAIK no way to introduce new type names in a sub-context. - m_context = LookupContext::create(semanticInfo.document, semanticInfo.snapshot, QList<AST::Node*>()); + // We're simplifying here by using the root context everywhere; should be + // ok since there is AFAIK no way to introduce new type names in a sub-context. + m_context = semanticInfo.lookupContext(); m_typeToIcon.clear(); m_itemToNode.clear(); m_itemToIdNode.clear(); diff --git a/src/plugins/qmljseditor/quicktoolbar.cpp b/src/plugins/qmljseditor/quicktoolbar.cpp index 60e257828be0643d070246d09a162b10e3b4183a..0d746e9fc85395ee87f7ad56e7cec0c78b832536 100644 --- a/src/plugins/qmljseditor/quicktoolbar.cpp +++ b/src/plugins/qmljseditor/quicktoolbar.cpp @@ -98,13 +98,16 @@ QuickToolBar::~QuickToolBar() m_widget.clear(); } -void QuickToolBar::apply(TextEditor::BaseTextEditorEditable *editor, Document::Ptr doc, const QmlJS::Snapshot &snapshot, AST::Node *node, bool update, bool force) +void QuickToolBar::apply(TextEditor::BaseTextEditorEditable *editor, LookupContext::Ptr lookupContext, AST::Node *node, bool update, bool force) { if (!QuickToolBarSettings::get().enableContextPane && !force && !update) { contextWidget()->hide(); return; } + if (lookupContext.isNull()) + return; + Document::Ptr doc = lookupContext->document(); if (doc.isNull()) return; @@ -113,7 +116,6 @@ void QuickToolBar::apply(TextEditor::BaseTextEditorEditable *editor, Document::P m_blockWriting = true; - LookupContext::Ptr lookupContext = LookupContext::create(doc, snapshot, QList<Node*>()); const Interpreter::ObjectValue *scopeObject = doc->bind()->findQmlObject(node); QStringList prototypes; @@ -211,43 +213,45 @@ void QuickToolBar::apply(TextEditor::BaseTextEditorEditable *editor, Document::P } -bool QuickToolBar::isAvailable(TextEditor::BaseTextEditorEditable *, Document::Ptr doc, const QmlJS::Snapshot &snapshot, AST::Node *node) +bool QuickToolBar::isAvailable(TextEditor::BaseTextEditorEditable *, LookupContext::Ptr lookupContext, AST::Node *node) { + if (lookupContext.isNull()) + return false; + Document::Ptr doc = lookupContext->document(); if (doc.isNull()) return false; if (!node) return false; - LookupContext::Ptr lookupContext = LookupContext::create(doc, snapshot, QList<Node*>()); - const Interpreter::ObjectValue *scopeObject = doc->bind()->findQmlObject(node); + const Interpreter::ObjectValue *scopeObject = doc->bind()->findQmlObject(node); - QStringList prototypes; + QStringList prototypes; - while (scopeObject) { - prototypes.append(scopeObject->className()); - scopeObject = scopeObject->prototype(lookupContext->context()); - } + while (scopeObject) { + prototypes.append(scopeObject->className()); + scopeObject = scopeObject->prototype(lookupContext->context()); + } - if (prototypes.contains("PropertyChanges")) { - const Interpreter::ObjectValue *targetObject = getPropertyChangesTarget(node, lookupContext); - prototypes.clear(); - while (targetObject) { - prototypes.append(targetObject->className()); - targetObject = targetObject->prototype(lookupContext->context()); - } + if (prototypes.contains("PropertyChanges")) { + const Interpreter::ObjectValue *targetObject = getPropertyChangesTarget(node, lookupContext); + prototypes.clear(); + while (targetObject) { + prototypes.append(targetObject->className()); + targetObject = targetObject->prototype(lookupContext->context()); } + } - if (prototypes.contains("Rectangle") || + if (prototypes.contains("Rectangle") || prototypes.contains("Image") || prototypes.contains("BorderImage") || prototypes.contains("TextEdit") || prototypes.contains("TextInput") || prototypes.contains("PropertyAnimation") || prototypes.contains("Text")) - return true; + return true; - return false; + return false; } void QuickToolBar::setProperty(const QString &propertyName, const QVariant &value) diff --git a/src/plugins/qmljseditor/quicktoolbar.h b/src/plugins/qmljseditor/quicktoolbar.h index 75ea8d54c11faa4697c795cea7a8b17b8927bf1b..79c57165546db09e5655b309ab4f0c27957242f5 100644 --- a/src/plugins/qmljseditor/quicktoolbar.h +++ b/src/plugins/qmljseditor/quicktoolbar.h @@ -30,8 +30,8 @@ class QuickToolBar : public QmlJS::IContextPane public: QuickToolBar(QObject *parent = 0); ~QuickToolBar(); - void apply(TextEditor::BaseTextEditorEditable *editor, QmlJS::Document::Ptr doc, const QmlJS::Snapshot &snapshot, QmlJS::AST::Node *node, bool update, bool force = 0); - bool isAvailable(TextEditor::BaseTextEditorEditable *editor, QmlJS::Document::Ptr doc, const QmlJS::Snapshot &snapshot, QmlJS::AST::Node *node); + void apply(TextEditor::BaseTextEditorEditable *editor, QmlJS::LookupContext::Ptr lookupContext, QmlJS::AST::Node *node, bool update, bool force = 0); + bool isAvailable(TextEditor::BaseTextEditorEditable *editor, QmlJS::LookupContext::Ptr lookupContext, QmlJS::AST::Node *node); void setProperty(const QString &propertyName, const QVariant &value); void removeProperty(const QString &propertyName); void setEnabled(bool);