summaryrefslogtreecommitdiff
path: root/src/plugins/cpptools/cpptoolseditorsupport.h
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2013-04-17 10:58:20 +0200
committerNikolai Kosjar <nikolai.kosjar@digia.com>2013-04-26 12:47:06 +0200
commit0c27b276584691f05e3efc88c95014f5bb5c3fa6 (patch)
treeaf65cf9dc162e0579d721bf27875d01b41e406f0 /src/plugins/cpptools/cpptoolseditorsupport.h
parente8d59fb76f6c59d8a0dd1e9d6cbdcb4bcfb3c9f0 (diff)
downloadqt-creator-0c27b276584691f05e3efc88c95014f5bb5c3fa6.tar.gz
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 <nikolai.kosjar@digia.com>
Diffstat (limited to 'src/plugins/cpptools/cpptoolseditorsupport.h')
-rw-r--r--src/plugins/cpptools/cpptoolseditorsupport.h151
1 files changed, 121 insertions, 30 deletions
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 <cplusplus/CppDocument.h>
+
+#include <QFuture>
#include <QObject>
#include <QPointer>
-#include <QFuture>
-
-QT_BEGIN_NAMESPACE
-class QTimer;
-QT_END_NAMESPACE
+#include <QTimer>
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<CPlusPlus::Document::DiagnosticMessage> &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<TextEditor::HighlightingResult>, 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<QTextEdit::ExtraSelection> selections;
+ QList<BlockRange> 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<void> &future,
+ SemanticInfo::Source source);
+
private:
- enum { UPDATE_DOCUMENT_DEFAULT_INTERVAL = 150 };
-
- CppModelManager *_modelManager;
- QPointer<TextEditor::ITextEditor> _textEditor;
- QTimer *_updateDocumentTimer;
- int _updateDocumentInterval;
- unsigned _revision;
- QFuture<void> _documentParser;
- QString _cachedContents;
+ Internal::CppModelManager *m_modelManager;
+ QPointer<TextEditor::BaseTextEditor> m_textEditor;
+ QTimer *m_updateDocumentTimer;
+ int m_updateDocumentInterval;
+ unsigned m_revision;
+ QFuture<void> m_documentParser;
+
+ // content caching
+ mutable QString m_cachedContents;
+ mutable int m_cachedContentsEditorRevision;
+
+ QTimer *m_updateEditorTimer;
+ EditorUpdates m_editorUpdates;
+
+ QMutex m_diagnosticsMutex;
+ QHash<QString, QList<CPlusPlus::Document::DiagnosticMessage> > m_allDiagnostics;
+
+ // Semantic info:
+ bool m_initialized;
+ mutable QMutex m_lastSemanticInfoLock;
+ SemanticInfo m_lastSemanticInfo;
+ QFuture<void> m_futureSemanticInfo;
+
+ // Highlighting:
+ unsigned m_lastHighlightRevision;
+ QFuture<TextEditor::HighlightingResult> m_highlighter;
+ QScopedPointer<CppTools::CppHighlightingSupport> m_highlightingSupport;
};
-} // namespace Internal
} // namespace CppTools
#endif // CPPTOOLSEDITORSUPPORT_H