From 0c27b276584691f05e3efc88c95014f5bb5c3fa6 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 17 Apr 2013 10:58:20 +0200 Subject: C++ Detach the CppEditor from code-model internals. - Moved document update handling into CppTools. - Moved semantic info calculation into CppTools. - Moved semantic highlighting into CppTools. Change-Id: I253861bf074a64b1f657f7a4a8e6583871b5285f Reviewed-by: Nikolai Kosjar --- src/plugins/cpptools/cpptoolseditorsupport.h | 151 +++++++++++++++++++++------ 1 file changed, 121 insertions(+), 30 deletions(-) (limited to 'src/plugins/cpptools/cpptoolseditorsupport.h') diff --git a/src/plugins/cpptools/cpptoolseditorsupport.h b/src/plugins/cpptools/cpptoolseditorsupport.h index b6e297abec..c36951c1b3 100644 --- a/src/plugins/cpptools/cpptoolseditorsupport.h +++ b/src/plugins/cpptools/cpptoolseditorsupport.h @@ -30,63 +30,154 @@ #ifndef CPPTOOLSEDITORSUPPORT_H #define CPPTOOLSEDITORSUPPORT_H +#include "cpphighlightingsupport.h" +#include "cppmodelmanager.h" +#include "cppsemanticinfo.h" + +#include + +#include #include #include -#include - -QT_BEGIN_NAMESPACE -class QTimer; -QT_END_NAMESPACE +#include namespace CPlusPlus { class AST; } namespace TextEditor { -class ITextEditor; +class BaseTextEditor; class ITextMark; } // namespace TextEditor namespace CppTools { -namespace Internal { -class CppModelManager; - -class CppEditorSupport: public QObject +/** + * \brief The CppEditorSupport class oversees the actions that happen when a C++ text editor updates + * its document. + * + * The following steps are taken: + * 1. the text editor fires a contentsChanged() signal that triggers updateDocument + * 2. update document will start a timer, or reset the timer if it was already running. This way + * subsequent updates (e.g. keypresses) get bunched together instead of running the subsequent + * actions for every key press + * 3. when the timer from step 2 fires, updateDocumentNow() is triggered. That tells the + * model-manager to update the CPlusPlus::Document by re-indexing it. + * 4. when the model-manager finishes, it fires a documentUpdated(CPlusPlus::Document::Ptr) signal, + * that is connected to onDocumentUpdated(CPlusPlus::Document::Ptr), which does 4 things: + * a) updates the ifdeffed-out blocks in the EditorUpdate + * b) calls setExtraDiagnostics with the diagnostics from the parser, which in turn calls + * onDiagnosticsChanged on the UI thread, and that schedules an editor update timer. When this + * timer fires, updateEditorNow() is called, which will apply the updates to the editor. + * c) a semantic-info recalculation is started in a future + * d) the documentUpdated() signal is emitted, which can be used by a widget to do things + * 5. semantic-info calculation from 4c is done by a future that calls recalculateSemanticInfoNow(), + * which emits semanticInfoUpdated() when it is finished. Editors can also listen in on this + * signal to do things like highlighting the local usages. + * 6. the semanticInfoUpdated() is connected to the startHighlighting() slot, which will start + * another future for doing the semantic highlighting. The highlighterStarted signal is emitted, + * with the highlighting future as a parameter, so editors can hook it up to a QFutureWatcher + * and get notifications. + * + * Both the semantic info calculation and the highlighting calculation will cancel an already running + * future. They will also check that the result of a previous step is not already outdated, meaning + * that they check the revision of the editor document to see if a user changed the document while + * the calculation was running. + */ +class CPPTOOLS_EXPORT CppEditorSupport: public QObject { Q_OBJECT public: - CppEditorSupport(CppModelManager *modelManager); + CppEditorSupport(Internal::CppModelManager *modelManager, TextEditor::BaseTextEditor *textEditor); virtual ~CppEditorSupport(); - TextEditor::ITextEditor *textEditor() const; - void setTextEditor(TextEditor::ITextEditor *textEditor); - - int updateDocumentInterval() const; - void setUpdateDocumentInterval(int updateDocumentInterval); + QString fileName() const; - QString contents(); + QString contents() const; unsigned editorRevision() const; -Q_SIGNALS: - void contentsChanged(); + void setExtraDiagnostics(const QString &key, + const QList &messages); + + /// Retrieve the semantic info, which will get recalculated on the current + /// thread if it is outdate. + SemanticInfo recalculateSemanticInfo(bool emitSignalWhenFinished = true); + + /// Recalculates the semantic info in a future, and will emit the semanticInfoUpdated() signal + /// when finished. + /// \param force do not check if the old semantic info is still valid + void recalculateSemanticInfoDetached(bool force = false); -private Q_SLOTS: +signals: + void documentUpdated(); + void diagnosticsChanged(); + void semanticInfoUpdated(CppTools::SemanticInfo); + void highlighterStarted(QFuture, unsigned revision); + +private slots: void updateDocument(); void updateDocumentNow(); + void onDocumentUpdated(CPlusPlus::Document::Ptr doc); + void startHighlighting(); + + void onDiagnosticsChanged(); + + void updateEditor(); + void updateEditorNow(); + +private: + typedef TextEditor::BaseTextEditorWidget::BlockRange BlockRange; + struct EditorUpdates { + EditorUpdates() + : revision(-1) + {} + int revision; + QList selections; + QList ifdefedOutBlocks; + }; + + enum { + UpdateDocumentDefaultInterval = 150, + UpdateEditorInterval = 300 + }; + +private: + SemanticInfo::Source currentSource(bool force); + void recalculateSemanticInfoNow(const SemanticInfo::Source &source, bool emitSignalWhenFinished, + CPlusPlus::TopLevelDeclarationProcessor *processor = 0); + void recalculateSemanticInfoDetached_helper(QFutureInterface &future, + SemanticInfo::Source source); + private: - enum { UPDATE_DOCUMENT_DEFAULT_INTERVAL = 150 }; - - CppModelManager *_modelManager; - QPointer _textEditor; - QTimer *_updateDocumentTimer; - int _updateDocumentInterval; - unsigned _revision; - QFuture _documentParser; - QString _cachedContents; + Internal::CppModelManager *m_modelManager; + QPointer m_textEditor; + QTimer *m_updateDocumentTimer; + int m_updateDocumentInterval; + unsigned m_revision; + QFuture m_documentParser; + + // content caching + mutable QString m_cachedContents; + mutable int m_cachedContentsEditorRevision; + + QTimer *m_updateEditorTimer; + EditorUpdates m_editorUpdates; + + QMutex m_diagnosticsMutex; + QHash > m_allDiagnostics; + + // Semantic info: + bool m_initialized; + mutable QMutex m_lastSemanticInfoLock; + SemanticInfo m_lastSemanticInfo; + QFuture m_futureSemanticInfo; + + // Highlighting: + unsigned m_lastHighlightRevision; + QFuture m_highlighter; + QScopedPointer m_highlightingSupport; }; -} // namespace Internal } // namespace CppTools #endif // CPPTOOLSEDITORSUPPORT_H -- cgit v1.2.1