diff --git a/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp b/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp index 113ee3b471e8964113639a2f3bf48b60e6578ab8..7575d7dcee2ea06adfb33a251c9f5c364ff8a078 100644 --- a/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp +++ b/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp @@ -70,7 +70,7 @@ int BaseTextEditModifier::indentDepth() const bool BaseTextEditModifier::renameId(const QString &oldId, const QString &newId) { - if (QmlJSEditor::Internal::QmlJSTextEditor *qmljse = qobject_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(plainTextEdit())) { + if (QmlJSEditor::QmlJSTextEditor *qmljse = qobject_cast<QmlJSEditor::QmlJSTextEditor*>(plainTextEdit())) { qmljse->renameId(oldId, newId); return true; } else { diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index 54cf860b63545c511f7ab9919c2cc3793a9015f7..f399b32ed0e654f402170b356ad896aad18909e4 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -28,6 +28,7 @@ **************************************************************************/ #include "qmljseditor.h" +#include "qmljseditoreditable.h" #include "qmljseditorconstants.h" #include "qmljshighlighter.h" #include "qmljseditorplugin.h" @@ -36,13 +37,12 @@ #include "qmljsquickfix.h" #include "qmloutlinemodel.h" #include "qmljsfindreferences.h" +#include "qmljssemantichighlighter.h" #include <qmljs/qmljsbind.h> -#include <qmljs/qmljscheck.h> #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> @@ -52,9 +52,6 @@ #include <coreplugin/actionmanager/command.h> #include <coreplugin/editormanager/editormanager.h> #include <coreplugin/icore.h> -#include <coreplugin/coreconstants.h> -#include <coreplugin/modemanager.h> -#include <coreplugin/designmode.h> #include <coreplugin/mimedatabase.h> #include <extensionsystem/pluginmanager.h> #include <texteditor/basetextdocument.h> @@ -89,6 +86,7 @@ enum { using namespace QmlJS; using namespace QmlJS::AST; +using namespace QmlJSEditor; using namespace QmlJSEditor::Internal; static int blockStartState(const QTextBlock &block) @@ -628,51 +626,6 @@ int SemanticInfo::revision() const return 0; } -QmlJSEditorEditable::QmlJSEditorEditable(QmlJSTextEditor *editor) - : BaseTextEditorEditable(editor) -{ - m_context.add(QmlJSEditor::Constants::C_QMLJSEDITOR_ID); - m_context.add(TextEditor::Constants::C_TEXTEDITOR); -} - -// Use preferred mode from Bauhaus settings -static bool openInDesignMode() -{ - static bool bauhausDetected = false; - static bool bauhausPresent = false; - // Check if Bauhaus is loaded, that is, a Design mode widget is - // registered for the QML mime type. - if (!bauhausDetected) { - if (const Core::IMode *dm = Core::ModeManager::instance()->mode(QLatin1String(Core::Constants::MODE_DESIGN))) - if (const Core::DesignMode *designMode = qobject_cast<const Core::DesignMode *>(dm)) - bauhausPresent = designMode->registeredMimeTypes().contains(QLatin1String(QmlJSEditor::Constants::QML_MIMETYPE)); - bauhausDetected = true; - } - if (!bauhausPresent) - return false; - - return bool(QmlDesigner::Constants::QML_OPENDESIGNMODE_DEFAULT); -} - -QString QmlJSEditorEditable::preferredModeType() const -{ - Core::ModeManager *modeManager = Core::ModeManager::instance(); - if (modeManager->currentMode() - && (modeManager->currentMode()->type() == Core::Constants::MODE_DESIGN_TYPE - || modeManager->currentMode()->type() == Core::Constants::MODE_EDIT_TYPE)) - { - return modeManager->currentMode()->type(); - } - - // if we are in other mode than edit or design, use the hard-coded default. - // because the editor opening decision is modal, it would be confusing to - // have the user also access to this failsafe setting. - if (editor()->mimeType() == QLatin1String(QmlJSEditor::Constants::QML_MIMETYPE) - && openInDesignMode()) - return QLatin1String(Core::Constants::MODE_DESIGN_TYPE); - return QString(); -} - QmlJSTextEditor::QmlJSTextEditor(QWidget *parent) : TextEditor::BaseTextEditor(parent), m_outlineCombo(0), @@ -682,7 +635,7 @@ QmlJSTextEditor::QmlJSTextEditor(QWidget *parent) : m_updateSelectedElements(false), m_findReferences(new FindReferences(this)) { - qRegisterMetaType<QmlJSEditor::Internal::SemanticInfo>("QmlJSEditor::Internal::SemanticInfo"); + qRegisterMetaType<QmlJSEditor::SemanticInfo>("QmlJSEditor::SemanticInfo"); m_semanticHighlighter = new SemanticHighlighter(this); m_semanticHighlighter->start(); @@ -748,8 +701,8 @@ QmlJSTextEditor::QmlJSTextEditor(QWidget *parent) : connect(this->document(), SIGNAL(modificationChanged(bool)), this, SLOT(modificationChanged(bool))); } - connect(m_semanticHighlighter, SIGNAL(changed(QmlJSEditor::Internal::SemanticInfo)), - this, SLOT(updateSemanticInfo(QmlJSEditor::Internal::SemanticInfo))); + connect(m_semanticHighlighter, SIGNAL(changed(QmlJSEditor::SemanticInfo)), + this, SLOT(updateSemanticInfo(QmlJSEditor::SemanticInfo))); connect(this, SIGNAL(refactorMarkerClicked(TextEditor::RefactorMarker)), SLOT(onRefactorMarkerClicked(TextEditor::RefactorMarker))); @@ -885,7 +838,7 @@ void QmlJSTextEditor::onDocumentUpdated(QmlJS::Document::Ptr doc) if (doc->ast()) { // got a correctly parsed (or recovered) file. - const SemanticHighlighter::Source source = currentSource(/*force = */ true); + const SemanticHighlighterSource source = currentSource(/*force = */ true); m_semanticHighlighter->rehighlight(source); } else { // show parsing errors @@ -1857,7 +1810,7 @@ bool QmlJSTextEditor::hideContextPane() return b; } -SemanticHighlighter::Source QmlJSTextEditor::currentSource(bool force) +SemanticHighlighterSource QmlJSTextEditor::currentSource(bool force) { int line = 0, column = 0; convertPosition(position(), &line, &column); @@ -1870,119 +1823,8 @@ SemanticHighlighter::Source QmlJSTextEditor::currentSource(bool force) code = toPlainText(); // get the source code only when needed. const unsigned revision = document()->revision(); - SemanticHighlighter::Source source(snapshot, fileName, code, + SemanticHighlighterSource source(snapshot, fileName, code, line, column, revision); source.force = force; return source; } - -SemanticHighlighter::SemanticHighlighter(QObject *parent) - : QThread(parent), - m_done(false), - m_modelManager(0) -{ -} - -SemanticHighlighter::~SemanticHighlighter() -{ -} - -void SemanticHighlighter::abort() -{ - QMutexLocker locker(&m_mutex); - m_done = true; - m_condition.wakeOne(); -} - -void SemanticHighlighter::rehighlight(const Source &source) -{ - QMutexLocker locker(&m_mutex); - m_source = source; - m_condition.wakeOne(); -} - -bool SemanticHighlighter::isOutdated() -{ - QMutexLocker locker(&m_mutex); - const bool outdated = ! m_source.fileName.isEmpty() || m_done; - return outdated; -} - -void SemanticHighlighter::run() -{ - setPriority(QThread::LowestPriority); - - forever { - m_mutex.lock(); - - while (! (m_done || ! m_source.fileName.isEmpty())) - m_condition.wait(&m_mutex); - - const bool done = m_done; - const Source source = m_source; - m_source.clear(); - - m_mutex.unlock(); - - if (done) - break; - - const SemanticInfo info = semanticInfo(source); - - if (! isOutdated()) { - m_mutex.lock(); - m_lastSemanticInfo = info; - m_mutex.unlock(); - - emit changed(info); - } - } -} - -SemanticInfo SemanticHighlighter::semanticInfo(const Source &source) -{ - m_mutex.lock(); - const int revision = m_lastSemanticInfo.revision(); - m_mutex.unlock(); - - Snapshot snapshot; - Document::Ptr doc; - - if (! source.force && revision == source.revision) { - m_mutex.lock(); - snapshot = m_lastSemanticInfo.snapshot; - doc = m_lastSemanticInfo.document; - m_mutex.unlock(); - } - - if (! doc) { - snapshot = source.snapshot; - doc = snapshot.documentFromSource(source.code, source.fileName); - doc->setEditorRevision(source.revision); - doc->parse(); - snapshot.insert(doc); - } - - SemanticInfo semanticInfo; - semanticInfo.snapshot = snapshot; - semanticInfo.document = doc; - - Interpreter::Context *ctx = new Interpreter::Context; - Link link(ctx, doc, snapshot, ModelManagerInterface::instance()->importPaths()); - semanticInfo.m_context = QSharedPointer<const QmlJS::Interpreter::Context>(ctx); - semanticInfo.semanticMessages = link.diagnosticMessages(); - - QStringList importPaths; - if (m_modelManager) - importPaths = m_modelManager->importPaths(); - Check checker(doc, snapshot, ctx); - semanticInfo.semanticMessages.append(checker()); - - return semanticInfo; -} - -void SemanticHighlighter::setModelManager(QmlJS::ModelManagerInterface *modelManager) -{ - m_modelManager = modelManager; -} - diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h index 4c625cf60c6c0dc7808e171e7b1e1dbf5efe3989..f22336a4dbd74c78099c98a55b718e11f2fbcc34 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -38,10 +38,8 @@ #include <texteditor/basetexteditor.h> #include <texteditor/quickfix.h> -#include <QtCore/QWaitCondition> +#include <QtCore/QSharedPointer> #include <QtCore/QModelIndex> -#include <QtCore/QMutex> -#include <QtCore/QThread> QT_BEGIN_NAMESPACE class QComboBox; @@ -62,34 +60,16 @@ namespace QmlJS { The top-level namespace of the QmlJSEditor plug-in. */ namespace QmlJSEditor { -class Highlighter; class FindReferences; namespace Internal { - -class QmlJSTextEditor; class QmlOutlineModel; +class QmlJSEditorEditable; +class SemanticHighlighter; +struct SemanticHighlighterSource; +} // namespace Internal -class QmlJSEditorEditable : public TextEditor::BaseTextEditorEditable -{ - Q_OBJECT - -public: - QmlJSEditorEditable(QmlJSTextEditor *); - Core::Context context() const; - - bool duplicateSupported() const { return true; } - Core::IEditor *duplicate(QWidget *parent); - QString id() const; - bool isTemporary() const { return false; } - virtual bool open(const QString & fileName); - virtual QString preferredModeType() const; - -private: - Core::Context m_context; -}; - -struct Declaration +struct QMLJSEDITOR_EXPORT Declaration { QString text; int startLine; @@ -105,7 +85,7 @@ struct Declaration { } }; -class Range +class QMLJSEDITOR_EXPORT Range { public: Range(): ast(0) {} @@ -116,8 +96,6 @@ public: // attributes QTextCursor end; }; -class SemanticHighlighter; - class QMLJSEDITOR_EXPORT SemanticInfo { public: @@ -152,75 +130,7 @@ public: // attributes private: QSharedPointer<const QmlJS::Interpreter::Context> m_context; - friend class SemanticHighlighter; -}; - -class SemanticHighlighter: public QThread -{ - Q_OBJECT - -public: - SemanticHighlighter(QObject *parent = 0); - virtual ~SemanticHighlighter(); - - void abort(); - - struct Source - { - QmlJS::Snapshot snapshot; - QString fileName; - QString code; - int line; - int column; - int revision; - bool force; - - Source() - : line(0), column(0), revision(0), force(false) - { } - - Source(const QmlJS::Snapshot &snapshot, - const QString &fileName, - const QString &code, - int line, int column, - int revision) - : snapshot(snapshot), fileName(fileName), - code(code), line(line), column(column), - revision(revision), force(false) - { } - - void clear() - { - snapshot = QmlJS::Snapshot(); - fileName.clear(); - code.clear(); - line = 0; - column = 0; - revision = 0; - force = false; - } - }; - - void rehighlight(const Source &source); - void setModelManager(QmlJS::ModelManagerInterface *modelManager); - -Q_SIGNALS: - void changed(const QmlJSEditor::Internal::SemanticInfo &semanticInfo); - -protected: - virtual void run(); - -private: - bool isOutdated(); - SemanticInfo semanticInfo(const Source &source); - -private: - QMutex m_mutex; - QWaitCondition m_condition; - bool m_done; - Source m_source; - SemanticInfo m_lastSemanticInfo; - QmlJS::ModelManagerInterface *m_modelManager; + friend class Internal::SemanticHighlighter; }; class QMLJSEDITOR_EXPORT QmlJSTextEditor : public TextEditor::BaseTextEditor @@ -237,7 +147,7 @@ public: int editorRevision() const; bool isOutdated() const; - QmlOutlineModel *outlineModel() const; + Internal::QmlOutlineModel *outlineModel() const; QModelIndex outlineModelIndex(); bool updateSelectedElements() const; @@ -276,7 +186,7 @@ private slots: void semanticRehighlight(); void forceSemanticRehighlight(); - void updateSemanticInfo(const QmlJSEditor::Internal::SemanticInfo &semanticInfo); + void updateSemanticInfo(const QmlJSEditor::SemanticInfo &semanticInfo); void onCursorPositionChanged(); void onRefactorMarkerClicked(const TextEditor::RefactorMarker &marker); @@ -289,7 +199,7 @@ protected: void resizeEvent(QResizeEvent *event); void scrollContentsBy(int dx, int dy); TextEditor::BaseTextEditorEditable *createEditableInterface(); - void createToolBar(QmlJSEditorEditable *editable); + void createToolBar(Internal::QmlJSEditorEditable *editable); TextEditor::BaseTextEditor::Link findLinkAt(const QTextCursor &cursor, bool resolveTarget = true); //// brace matching @@ -307,7 +217,7 @@ private: void setSelectedElements(); QString wordUnderCursor() const; - SemanticHighlighter::Source currentSource(bool force = false); + Internal::SemanticHighlighterSource currentSource(bool force = false); QModelIndex indexForPosition(unsigned cursorPosition, const QModelIndex &rootIndex = QModelIndex()) const; bool hideContextPane(); @@ -320,14 +230,14 @@ private: QTimer *m_updateOutlineIndexTimer; QTimer *m_cursorPositionTimer; QComboBox *m_outlineCombo; - QmlOutlineModel *m_outlineModel; + Internal::QmlOutlineModel *m_outlineModel; QModelIndex m_outlineModelIndex; QmlJS::ModelManagerInterface *m_modelManager; QTextCharFormat m_occurrencesFormat; QTextCharFormat m_occurrencesUnusedFormat; QTextCharFormat m_occurrenceRenameFormat; - SemanticHighlighter *m_semanticHighlighter; + Internal::SemanticHighlighter *m_semanticHighlighter; SemanticInfo m_semanticInfo; QList<TextEditor::QuickFixOperation::Ptr> m_quickFixes; @@ -339,7 +249,6 @@ private: FindReferences *m_findReferences; }; -} // namespace Internal } // namespace QmlJSEditor #endif // QMLJSEDITOR_H diff --git a/src/plugins/qmljseditor/qmljseditor.pro b/src/plugins/qmljseditor/qmljseditor.pro index 8a6c725379cc8819d7bcb6d21fbd3ae5b6613e01..2c3c302e2953e2ecf3708f64acba0c179210c49f 100644 --- a/src/plugins/qmljseditor/qmljseditor.pro +++ b/src/plugins/qmljseditor/qmljseditor.pro @@ -32,7 +32,9 @@ HEADERS += \ quicktoolbarsettingspage.h \ quicktoolbar.h \ qmljscomponentnamedialog.h \ - qmljsfindreferences.h + qmljsfindreferences.h \ + qmljseditoreditable.h \ + qmljssemantichighlighter.h SOURCES += \ qmljscodecompletion.cpp \ @@ -58,7 +60,9 @@ SOURCES += \ quicktoolbarsettingspage.cpp \ quicktoolbar.cpp \ qmljscomponentnamedialog.cpp \ - qmljsfindreferences.cpp + qmljsfindreferences.cpp \ + qmljseditoreditable.cpp \ + qmljssemantichighlighter.cpp RESOURCES += qmljseditor.qrc OTHER_FILES += QmlJSEditor.pluginspec QmlJSEditor.mimetypes.xml diff --git a/src/plugins/qmljseditor/qmljseditoreditable.cpp b/src/plugins/qmljseditor/qmljseditoreditable.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0013fc9277b7eab6d2c58a4026549944d63da9df --- /dev/null +++ b/src/plugins/qmljseditor/qmljseditoreditable.cpp @@ -0,0 +1,92 @@ +/************************************************************************** +** +** 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 "qmljseditoreditable.h" +#include "qmljseditor.h" +#include "qmljseditorconstants.h" + +#include <texteditor/texteditorconstants.h> +#include <qmldesigner/qmldesignerconstants.h> + +#include <coreplugin/mimedatabase.h> +#include <coreplugin/icore.h> +#include <coreplugin/designmode.h> +#include <coreplugin/modemanager.h> +#include <coreplugin/coreconstants.h> + +namespace QmlJSEditor { +namespace Internal { + +QmlJSEditorEditable::QmlJSEditorEditable(QmlJSTextEditor *editor) + : BaseTextEditorEditable(editor) +{ + m_context.add(QmlJSEditor::Constants::C_QMLJSEDITOR_ID); + m_context.add(TextEditor::Constants::C_TEXTEDITOR); +} + +// Use preferred mode from Bauhaus settings +static bool openInDesignMode() +{ + static bool bauhausDetected = false; + static bool bauhausPresent = false; + // Check if Bauhaus is loaded, that is, a Design mode widget is + // registered for the QML mime type. + if (!bauhausDetected) { + if (const Core::IMode *dm = Core::ModeManager::instance()->mode(QLatin1String(Core::Constants::MODE_DESIGN))) + if (const Core::DesignMode *designMode = qobject_cast<const Core::DesignMode *>(dm)) + bauhausPresent = designMode->registeredMimeTypes().contains(QLatin1String(QmlJSEditor::Constants::QML_MIMETYPE)); + bauhausDetected = true; + } + if (!bauhausPresent) + return false; + + return bool(QmlDesigner::Constants::QML_OPENDESIGNMODE_DEFAULT); +} + +QString QmlJSEditorEditable::preferredModeType() const +{ + Core::ModeManager *modeManager = Core::ModeManager::instance(); + if (modeManager->currentMode() + && (modeManager->currentMode()->type() == Core::Constants::MODE_DESIGN_TYPE + || modeManager->currentMode()->type() == Core::Constants::MODE_EDIT_TYPE)) + { + return modeManager->currentMode()->type(); + } + + // if we are in other mode than edit or design, use the hard-coded default. + // because the editor opening decision is modal, it would be confusing to + // have the user also access to this failsafe setting. + if (editor()->mimeType() == QLatin1String(QmlJSEditor::Constants::QML_MIMETYPE) + && openInDesignMode()) + return QLatin1String(Core::Constants::MODE_DESIGN_TYPE); + return QString(); +} + +} // namespace Internal +} // namespace QmlJSEditor diff --git a/src/plugins/qmljseditor/qmljseditoreditable.h b/src/plugins/qmljseditor/qmljseditoreditable.h new file mode 100644 index 0000000000000000000000000000000000000000..86253b5c9956e23a39b809d7170f630abc069eb5 --- /dev/null +++ b/src/plugins/qmljseditor/qmljseditoreditable.h @@ -0,0 +1,62 @@ +/************************************************************************** +** +** 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 QMLJSEDITOREDITABLE_H +#define QMLJSEDITOREDITABLE_H + +#include <texteditor/basetexteditor.h> + +namespace QmlJSEditor { +class QmlJSTextEditor; + +namespace Internal { + +class QmlJSEditorEditable : public TextEditor::BaseTextEditorEditable +{ + Q_OBJECT + +public: + explicit QmlJSEditorEditable(QmlJSTextEditor *); + Core::Context context() const; + + bool duplicateSupported() const { return true; } + Core::IEditor *duplicate(QWidget *parent); + QString id() const; + bool isTemporary() const { return false; } + virtual bool open(const QString & fileName); + virtual QString preferredModeType() const; + +private: + Core::Context m_context; +}; + +} // namespace Internal +} // namespace QmlJSEditor + +#endif // QMLJSEDITOREDITABLE_H diff --git a/src/plugins/qmljseditor/qmljseditorfactory.cpp b/src/plugins/qmljseditor/qmljseditorfactory.cpp index 61d30e9247e97987b1061574c8db808706d0dfa9..dbdafac49758d4901c376682875408003d63ffc3 100644 --- a/src/plugins/qmljseditor/qmljseditorfactory.cpp +++ b/src/plugins/qmljseditor/qmljseditorfactory.cpp @@ -28,6 +28,7 @@ **************************************************************************/ #include "qmljseditorfactory.h" +#include "qmljseditoreditable.h" #include "qmljseditor.h" #include "qmljseditoractionhandler.h" #include "qmljseditorconstants.h" @@ -124,7 +125,7 @@ Core::IEditor *QmlJSEditorFactory::createEditor(QWidget *parent) SLOT(updateEditorInfoBar(Core::IEditor*))); } } - QmlJSTextEditor *rc = new QmlJSTextEditor(parent); + QmlJSEditor::QmlJSTextEditor *rc = new QmlJSEditor::QmlJSTextEditor(parent); QmlJSEditorPlugin::instance()->initializeEditor(rc); return rc->editableInterface(); } diff --git a/src/plugins/qmljseditor/qmljseditorplugin.cpp b/src/plugins/qmljseditor/qmljseditorplugin.cpp index 0b1cc3f39a718fea0e68f743b237fba9a35ce1d1..4aae75e28a59fdfd52561ee8382c481b6d225854 100644 --- a/src/plugins/qmljseditor/qmljseditorplugin.cpp +++ b/src/plugins/qmljseditor/qmljseditorplugin.cpp @@ -247,7 +247,7 @@ ExtensionSystem::IPlugin::ShutdownFlag QmlJSEditorPlugin::aboutToShutdown() return IPlugin::aboutToShutdown(); } -void QmlJSEditorPlugin::initializeEditor(QmlJSEditor::Internal::QmlJSTextEditor *editor) +void QmlJSEditorPlugin::initializeEditor(QmlJSEditor::QmlJSTextEditor *editor) { QTC_ASSERT(m_instance, /**/); diff --git a/src/plugins/qmljseditor/qmljseditorplugin.h b/src/plugins/qmljseditor/qmljseditorplugin.h index b45c867dbc76afe3a9e68d7e58885fd193dca9d0..786a2f2675527b680f32f7bc45b6987208039420 100644 --- a/src/plugins/qmljseditor/qmljseditorplugin.h +++ b/src/plugins/qmljseditor/qmljseditorplugin.h @@ -58,11 +58,11 @@ namespace QmlJS { namespace QmlJSEditor { class QmlFileWizard; +class QmlJSTextEditor; namespace Internal { class QmlJSEditorFactory; -class QmlJSTextEditor; class QmlJSPreviewRunner; class QmlJSQuickFixCollector; class QmlTaskManager; @@ -85,7 +85,7 @@ public: QmlJSQuickFixCollector *quickFixCollector() const; - void initializeEditor(QmlJSTextEditor *editor); + void initializeEditor(QmlJSEditor::QmlJSTextEditor *editor); public Q_SLOTS: void followSymbolUnderCursor(); diff --git a/src/plugins/qmljseditor/qmljshoverhandler.cpp b/src/plugins/qmljseditor/qmljshoverhandler.cpp index 5e7f24ddf0cf1a4343f5017b4a3e7e2bbea0ac7f..b2ac1eb457410e55d1cd78f7ead1b2db3da58ac2 100644 --- a/src/plugins/qmljseditor/qmljshoverhandler.cpp +++ b/src/plugins/qmljseditor/qmljshoverhandler.cpp @@ -28,6 +28,7 @@ **************************************************************************/ #include "qmljseditor.h" +#include "qmljseditoreditable.h" #include "qmlexpressionundercursor.h" #include "qmljshoverhandler.h" @@ -104,12 +105,12 @@ void HoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos) if (!m_modelManager) return; - QmlJSTextEditor *qmlEditor = qobject_cast<QmlJSTextEditor *>(editor->widget()); + QmlJSEditor::QmlJSTextEditor *qmlEditor = qobject_cast<QmlJSEditor::QmlJSTextEditor *>(editor->widget()); if (!qmlEditor) return; if (!matchDiagnosticMessage(qmlEditor, pos)) { - const SemanticInfo &semanticInfo = qmlEditor->semanticInfo(); + const QmlJSEditor::SemanticInfo &semanticInfo = qmlEditor->semanticInfo(); if (! semanticInfo.isValid() || semanticInfo.revision() != qmlEditor->editorRevision()) return; @@ -129,7 +130,7 @@ void HoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos) } } -bool HoverHandler::matchDiagnosticMessage(QmlJSTextEditor *qmlEditor, int pos) +bool HoverHandler::matchDiagnosticMessage(QmlJSEditor::QmlJSTextEditor *qmlEditor, int pos) { foreach (const QTextEdit::ExtraSelection &sel, qmlEditor->extraSelections(TextEditor::BaseTextEditor::CodeWarningsSelection)) { diff --git a/src/plugins/qmljseditor/qmljshoverhandler.h b/src/plugins/qmljseditor/qmljshoverhandler.h index 77e967e39dff915a6ae0bcd247b9941d9ebab34f..ea59ccdb79f1f6ea6867ebca6b051bfe973d5eec 100644 --- a/src/plugins/qmljseditor/qmljshoverhandler.h +++ b/src/plugins/qmljseditor/qmljshoverhandler.h @@ -49,10 +49,11 @@ class ITextEditor; } namespace QmlJSEditor { +class QmlJSTextEditor; + namespace Internal { class SemanticInfo; -class QmlJSTextEditor; class HoverHandler : public TextEditor::BaseHoverHandler { @@ -67,7 +68,7 @@ private: virtual void identifyMatch(TextEditor::ITextEditor *editor, int pos); virtual void operateTooltip(TextEditor::ITextEditor *editor, const QPoint &point); - bool matchDiagnosticMessage(QmlJSTextEditor *qmlEditor, int pos); + bool matchDiagnosticMessage(QmlJSEditor::QmlJSTextEditor *qmlEditor, int pos); bool matchColorItem(const QmlJS::LookupContext::Ptr &lookupContext, const QmlJS::Document::Ptr &qmlDocument, const QList<QmlJS::AST::Node *> &astPath, diff --git a/src/plugins/qmljseditor/qmljsoutline.cpp b/src/plugins/qmljseditor/qmljsoutline.cpp index b1465819dee035146e6fad825e419fa154549797..fcfdb885fc77e200a0bb7a03d71b87158720e624 100644 --- a/src/plugins/qmljseditor/qmljsoutline.cpp +++ b/src/plugins/qmljseditor/qmljsoutline.cpp @@ -1,5 +1,6 @@ #include "qmljsoutline.h" #include "qmloutlinemodel.h" +#include "qmljseditoreditable.h" #include "qmljsoutlinetreeview.h" #include <coreplugin/icore.h> diff --git a/src/plugins/qmljseditor/qmljsquickfix.h b/src/plugins/qmljseditor/qmljsquickfix.h index 57e6b2521f6868ed357d1551267520fd440d62f6..b316e117e04c04ffc7a4b9b6ef9d9166f0aa7760 100644 --- a/src/plugins/qmljseditor/qmljsquickfix.h +++ b/src/plugins/qmljseditor/qmljsquickfix.h @@ -65,7 +65,7 @@ public: /// Creates a new state for the given editor. QmlJSQuickFixState(TextEditor::BaseTextEditor *editor); - Internal::SemanticInfo semanticInfo() const; + SemanticInfo semanticInfo() const; /// \returns the snapshot holding the document of the editor. QmlJS::Snapshot snapshot() const; @@ -76,7 +76,7 @@ public: const QmlJSRefactoringFile currentFile() const; private: - Internal::SemanticInfo _semanticInfo; + SemanticInfo _semanticInfo; }; /*! diff --git a/src/plugins/qmljseditor/qmljssemantichighlighter.cpp b/src/plugins/qmljseditor/qmljssemantichighlighter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0881ee879b93de12905cb8df7b6babbf904a130f --- /dev/null +++ b/src/plugins/qmljseditor/qmljssemantichighlighter.cpp @@ -0,0 +1,152 @@ +/************************************************************************** +** +** 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 "qmljssemantichighlighter.h" +#include "qmljsmodelmanager.h" + +#include <qmljs/qmljsdocument.h> +#include <qmljs/qmljscheck.h> +#include <qmljs/qmljsinterpreter.h> +#include <qmljs/qmljslink.h> + +namespace QmlJSEditor { +namespace Internal { + +SemanticHighlighter::SemanticHighlighter(QObject *parent) + : QThread(parent), + m_done(false), + m_modelManager(0) +{ +} + +SemanticHighlighter::~SemanticHighlighter() +{ +} + +void SemanticHighlighter::abort() +{ + QMutexLocker locker(&m_mutex); + m_done = true; + m_condition.wakeOne(); +} + +void SemanticHighlighter::rehighlight(const SemanticHighlighterSource &source) +{ + QMutexLocker locker(&m_mutex); + m_source = source; + m_condition.wakeOne(); +} + +bool SemanticHighlighter::isOutdated() +{ + QMutexLocker locker(&m_mutex); + const bool outdated = ! m_source.fileName.isEmpty() || m_done; + return outdated; +} + +void SemanticHighlighter::run() +{ + setPriority(QThread::LowestPriority); + + forever { + m_mutex.lock(); + + while (! (m_done || ! m_source.fileName.isEmpty())) + m_condition.wait(&m_mutex); + + const bool done = m_done; + const SemanticHighlighterSource source = m_source; + m_source.clear(); + + m_mutex.unlock(); + + if (done) + break; + + const SemanticInfo info = semanticInfo(source); + + if (! isOutdated()) { + m_mutex.lock(); + m_lastSemanticInfo = info; + m_mutex.unlock(); + + emit changed(info); + } + } +} + +SemanticInfo SemanticHighlighter::semanticInfo(const SemanticHighlighterSource &source) +{ + m_mutex.lock(); + const int revision = m_lastSemanticInfo.revision(); + m_mutex.unlock(); + + QmlJS::Snapshot snapshot; + QmlJS::Document::Ptr doc; + + if (! source.force && revision == source.revision) { + m_mutex.lock(); + snapshot = m_lastSemanticInfo.snapshot; + doc = m_lastSemanticInfo.document; + m_mutex.unlock(); + } + + if (! doc) { + snapshot = source.snapshot; + doc = snapshot.documentFromSource(source.code, source.fileName); + doc->setEditorRevision(source.revision); + doc->parse(); + snapshot.insert(doc); + } + + SemanticInfo semanticInfo; + semanticInfo.snapshot = snapshot; + semanticInfo.document = doc; + + QmlJS::Interpreter::Context *ctx = new QmlJS::Interpreter::Context; + QmlJS::Link link(ctx, doc, snapshot, QmlJS::ModelManagerInterface::instance()->importPaths()); + semanticInfo.m_context = QSharedPointer<const QmlJS::Interpreter::Context>(ctx); + semanticInfo.semanticMessages = link.diagnosticMessages(); + + QStringList importPaths; + if (m_modelManager) + importPaths = m_modelManager->importPaths(); + QmlJS::Check checker(doc, snapshot, ctx); + semanticInfo.semanticMessages.append(checker()); + + return semanticInfo; +} + +void SemanticHighlighter::setModelManager(QmlJS::ModelManagerInterface *modelManager) +{ + m_modelManager = modelManager; +} + +} // namespace Internal +} // namespace QmlJSEditor diff --git a/src/plugins/qmljseditor/qmljssemantichighlighter.h b/src/plugins/qmljseditor/qmljssemantichighlighter.h new file mode 100644 index 0000000000000000000000000000000000000000..dff097ba7f2ad03abbb490599733acbf9c283179 --- /dev/null +++ b/src/plugins/qmljseditor/qmljssemantichighlighter.h @@ -0,0 +1,113 @@ +/************************************************************************** +** +** 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 SEMANTICHIGHLIGHTER_H +#define SEMANTICHIGHLIGHTER_H + +#include "qmljseditor.h" + +#include <QtCore/QWaitCondition> +#include <QtCore/QModelIndex> +#include <QtCore/QMutex> +#include <QtCore/QThread> + +namespace QmlJSEditor { +namespace Internal { + +struct SemanticHighlighterSource +{ + QmlJS::Snapshot snapshot; + QString fileName; + QString code; + int line; + int column; + int revision; + bool force; + + SemanticHighlighterSource() + : line(0), column(0), revision(0), force(false) + { } + + SemanticHighlighterSource(const QmlJS::Snapshot &snapshot, + const QString &fileName, + const QString &code, + int line, int column, + int revision) + : snapshot(snapshot), fileName(fileName), + code(code), line(line), column(column), + revision(revision), force(false) + { } + + void clear() + { + snapshot = QmlJS::Snapshot(); + fileName.clear(); + code.clear(); + line = 0; + column = 0; + revision = 0; + force = false; + } +}; + +class SemanticHighlighter: public QThread +{ + Q_OBJECT + +public: + SemanticHighlighter(QObject *parent = 0); + virtual ~SemanticHighlighter(); + + void abort(); + void rehighlight(const SemanticHighlighterSource &source); + void setModelManager(QmlJS::ModelManagerInterface *modelManager); + +Q_SIGNALS: + void changed(const QmlJSEditor::SemanticInfo &semanticInfo); + +protected: + virtual void run(); + +private: + bool isOutdated(); + SemanticInfo semanticInfo(const SemanticHighlighterSource &source); + +private: + QMutex m_mutex; + QWaitCondition m_condition; + bool m_done; + SemanticHighlighterSource m_source; + SemanticInfo m_lastSemanticInfo; + QmlJS::ModelManagerInterface *m_modelManager; +}; + +} // namespace Internal +} // namespace QmlJSEditor + +#endif // SEMANTICHIGHLIGHTER_H diff --git a/src/plugins/qmljsinspector/qmljsinspector.cpp b/src/plugins/qmljsinspector/qmljsinspector.cpp index 997be7ee553529125ef523ce758bb6b6d4dde38c..66c9b4333a664bfb593db10df7c94f113f6da522 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.cpp +++ b/src/plugins/qmljsinspector/qmljsinspector.cpp @@ -187,7 +187,7 @@ void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextE { Q_UNUSED(mousePos); if (m_clientProxy && editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { - QmlJSEditor::Internal::QmlJSTextEditor *qmlEditor = static_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(editor->widget()); + QmlJSEditor::QmlJSTextEditor *qmlEditor = static_cast<QmlJSEditor::QmlJSTextEditor*>(editor->widget()); QTextCursor tc(qmlEditor->document()); tc.setPosition(cursorPos); diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp index 7dca4c4e428717c656e9a9969668cc47ca9f2d83..966ac15e8f098137d3554458d99ff22a890dea61 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp @@ -128,7 +128,7 @@ QmlJS::ModelManagerInterface *QmlJSLiveTextPreview::modelManager() void QmlJSLiveTextPreview::associateEditor(Core::IEditor *editor) { if (editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { - QmlJSEditor::Internal::QmlJSTextEditor* qmljsEditor = qobject_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(editor->widget()); + QmlJSEditor::QmlJSTextEditor* qmljsEditor = qobject_cast<QmlJSEditor::QmlJSTextEditor*>(editor->widget()); if (qmljsEditor && !m_editors.contains(qmljsEditor)) { qmljsEditor->setUpdateSelectedElements(true); m_editors << qmljsEditor; @@ -142,7 +142,7 @@ void QmlJSLiveTextPreview::associateEditor(Core::IEditor *editor) void QmlJSLiveTextPreview::unassociateEditor(Core::IEditor *oldEditor) { if (oldEditor && oldEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { - QmlJSEditor::Internal::QmlJSTextEditor* qmljsEditor = qobject_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(oldEditor->widget()); + QmlJSEditor::QmlJSTextEditor* qmljsEditor = qobject_cast<QmlJSEditor::QmlJSTextEditor*>(oldEditor->widget()); if (qmljsEditor && m_editors.contains(qmljsEditor)) { m_editors.removeOne(qmljsEditor); qmljsEditor->setUpdateSelectedElements(false); @@ -630,12 +630,12 @@ void QmlJSLiveTextPreview::setClientProxy(ClientProxy *clientProxy) connect(m_clientProxy.data(), SIGNAL(objectTreeUpdated()), SLOT(updateDebugIds())); - foreach(QWeakPointer<QmlJSEditor::Internal::QmlJSTextEditor> qmlEditor, m_editors) { + foreach(QWeakPointer<QmlJSEditor::QmlJSTextEditor> qmlEditor, m_editors) { if (qmlEditor) qmlEditor.data()->setUpdateSelectedElements(true); } } else { - foreach(QWeakPointer<QmlJSEditor::Internal::QmlJSTextEditor> qmlEditor, m_editors) { + foreach(QWeakPointer<QmlJSEditor::QmlJSTextEditor> qmlEditor, m_editors) { if (qmlEditor) qmlEditor.data()->setUpdateSelectedElements(false); } diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.h b/src/plugins/qmljsinspector/qmljslivetextpreview.h index 0681e6e2cba8c1eb3ac0085c8a06748f832f2867..da25d594208e33beb4b68356eda4a49256ba090d 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.h +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.h @@ -48,10 +48,8 @@ namespace QmlJS { } namespace QmlJSEditor { -namespace Internal { class QmlJSTextEditor; } -} namespace QmlJSInspector { namespace Internal { @@ -114,7 +112,7 @@ private: QmlJS::Document::Ptr m_initialDoc; //the document that was loaded by the server QString m_filename; - QList<QWeakPointer<QmlJSEditor::Internal::QmlJSTextEditor> > m_editors; + QList<QWeakPointer<QmlJSEditor::QmlJSTextEditor> > m_editors; bool m_applyChangesToQmlObserver; QmlJS::Document::Ptr m_docWithUnappliedChanges;