diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index ad2d4cd0cd8..98d88e02df5 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -658,6 +658,7 @@ QmlJSTextEditorWidget::QmlJSTextEditorWidget(QWidget *parent) : m_outlineCombo(0), m_outlineModel(new QmlOutlineModel(this)), m_modelManager(0), + m_futureSemanticInfoRevision(0), m_contextPane(0), m_updateSelectedElements(false), m_findReferences(new FindReferences(this)), @@ -891,7 +892,7 @@ void QmlJSTextEditorWidget::onDocumentUpdated(QmlJS::Document::Ptr doc) if (file()->fileName() != doc->fileName()) return; - if (doc->editorRevision() != document()->revision()) { + if (doc->editorRevision() != editorRevision()) { // Maybe a dependency changed and our semantic info is now outdated. // Ignore 0-revision documents though, we get them when a file is initially opened // in an editor. @@ -904,7 +905,8 @@ void QmlJSTextEditorWidget::onDocumentUpdated(QmlJS::Document::Ptr doc) if (doc->ast()) { // got a correctly parsed (or recovered) file. - m_semanticInfoUpdater->update(SemanticInfoUpdaterSource(doc, m_modelManager->snapshot())); + m_futureSemanticInfoRevision = doc->editorRevision(); + m_semanticInfoUpdater->update(doc, m_modelManager->snapshot()); } else { // show parsing errors QList selections; @@ -1533,9 +1535,9 @@ void QmlJSTextEditorWidget::setTabSettings(const TextEditor::TabSettings &ts) void QmlJSTextEditorWidget::updateSemanticInfo() { - // If the document is already out of date, new semantic infos + // If the editor is newer than the future semantic info, new semantic infos // won't be accepted anyway. What we need is a reparse. - if (isSemanticInfoOutdated()) + if (editorRevision() != m_futureSemanticInfoRevision) return; // Save time by not doing it for non-active editors. @@ -1548,20 +1550,19 @@ void QmlJSTextEditorWidget::updateSemanticInfo() void QmlJSTextEditorWidget::updateSemanticInfoNow() { - // If the document is already out of date, new semantic infos + // If the editor is newer than the future semantic info, new semantic infos // won't be accepted anyway. What we need is a reparse. - if (isSemanticInfoOutdated()) + if (editorRevision() != m_futureSemanticInfoRevision) return; m_updateSemanticInfoTimer->stop(); - m_semanticInfoUpdater->update( - SemanticInfoUpdaterSource(m_semanticInfo.document, m_semanticInfo.snapshot)); + m_semanticInfoUpdater->reupdate(m_modelManager->snapshot()); } void QmlJSTextEditorWidget::acceptNewSemanticInfo(const SemanticInfo &semanticInfo) { - if (semanticInfo.document->editorRevision() != document()->revision()) { + if (semanticInfo.revision() != editorRevision()) { // ignore outdated semantic infos return; } diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h index 7cc67875537..a29366ceab5 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -245,6 +245,7 @@ private: Internal::SemanticInfoUpdater *m_semanticInfoUpdater; SemanticInfo m_semanticInfo; + int m_futureSemanticInfoRevision; QList m_quickFixes; diff --git a/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp b/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp index a4ef2ccb39d..9858e644532 100644 --- a/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp +++ b/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp @@ -59,10 +59,19 @@ void SemanticInfoUpdater::abort() m_condition.wakeOne(); } -void SemanticInfoUpdater::update(const SemanticInfoUpdaterSource &source) +void SemanticInfoUpdater::update(const QmlJS::Document::Ptr &doc, const QmlJS::Snapshot &snapshot) { QMutexLocker locker(&m_mutex); - m_source = source; + m_sourceDocument = doc; + m_sourceSnapshot = snapshot; + m_condition.wakeOne(); +} + +void SemanticInfoUpdater::reupdate(const QmlJS::Snapshot &snapshot) +{ + QMutexLocker locker(&m_mutex); + m_sourceDocument = m_lastSemanticInfo.document; + m_sourceSnapshot = snapshot; m_condition.wakeOne(); } @@ -73,22 +82,24 @@ void SemanticInfoUpdater::run() forever { m_mutex.lock(); - while (! (m_wasCancelled || m_source.isValid())) + while (! (m_wasCancelled || m_sourceDocument)) m_condition.wait(&m_mutex); const bool done = m_wasCancelled; - const SemanticInfoUpdaterSource source = m_source; - m_source.clear(); + QmlJS::Document::Ptr doc = m_sourceDocument; + QmlJS::Snapshot snapshot = m_sourceSnapshot; + m_sourceDocument.clear(); + m_sourceSnapshot = QmlJS::Snapshot(); m_mutex.unlock(); if (done) break; - const SemanticInfo info = makeNewSemanticInfo(source); + const SemanticInfo info = makeNewSemanticInfo(doc, snapshot); m_mutex.lock(); - const bool cancelledOrNewData = m_wasCancelled || m_source.isValid(); + const bool cancelledOrNewData = m_wasCancelled || m_sourceDocument; m_mutex.unlock(); if (! cancelledOrNewData) { @@ -98,13 +109,13 @@ void SemanticInfoUpdater::run() } } -SemanticInfo SemanticInfoUpdater::makeNewSemanticInfo(const SemanticInfoUpdaterSource &source) +SemanticInfo SemanticInfoUpdater::makeNewSemanticInfo(const QmlJS::Document::Ptr &doc, const QmlJS::Snapshot &snapshot) { using namespace QmlJS; SemanticInfo semanticInfo; - const Document::Ptr &doc = semanticInfo.document = source.document; - semanticInfo.snapshot = source.snapshot; + semanticInfo.document = doc; + semanticInfo.snapshot = snapshot; ModelManagerInterface *modelManager = ModelManagerInterface::instance(); diff --git a/src/plugins/qmljseditor/qmljssemanticinfoupdater.h b/src/plugins/qmljseditor/qmljssemanticinfoupdater.h index ed7a9a026f3..e2e6b564f05 100644 --- a/src/plugins/qmljseditor/qmljssemanticinfoupdater.h +++ b/src/plugins/qmljseditor/qmljssemanticinfoupdater.h @@ -43,30 +43,6 @@ namespace QmlJSEditor { namespace Internal { -struct SemanticInfoUpdaterSource -{ - QmlJS::Document::Ptr document; - QmlJS::Snapshot snapshot; - - SemanticInfoUpdaterSource() - { } - - SemanticInfoUpdaterSource(const QmlJS::Document::Ptr &document, - const QmlJS::Snapshot &snapshot) - : document(document) - , snapshot(snapshot) - { } - - bool isValid() const - { return document; } - - void clear() - { - document.clear(); - snapshot = QmlJS::Snapshot(); - } -}; - class SemanticInfoUpdater: public QThread { Q_OBJECT @@ -76,7 +52,8 @@ public: virtual ~SemanticInfoUpdater(); void abort(); - void update(const SemanticInfoUpdaterSource &source); + void update(const QmlJS::Document::Ptr &doc, const QmlJS::Snapshot &snapshot); + void reupdate(const QmlJS::Snapshot &snapshot); Q_SIGNALS: void updated(const QmlJSEditor::SemanticInfo &semanticInfo); @@ -85,13 +62,14 @@ protected: virtual void run(); private: - SemanticInfo makeNewSemanticInfo(const SemanticInfoUpdaterSource &source); + SemanticInfo makeNewSemanticInfo(const QmlJS::Document::Ptr &doc, const QmlJS::Snapshot &snapshot); private: QMutex m_mutex; QWaitCondition m_condition; bool m_wasCancelled; - SemanticInfoUpdaterSource m_source; + QmlJS::Document::Ptr m_sourceDocument; + QmlJS::Snapshot m_sourceSnapshot; SemanticInfo m_lastSemanticInfo; };