Files
qt-creator/src/plugins/cpptools/cpptoolseditorsupport.h
Nikolai Kosjar ea55d627d7 CppTools: Start to use editor document
This is only a small refactoring step towards a editor-free
CppEditorSupport.

Left are m_editor references that need to be addressed.

No functional change.

Change-Id: I9fc7b0abfe88f5b9a6ce3f57a5c4a922ae953ddf
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
2014-06-12 17:03:07 +02:00

253 lines
9.4 KiB
C++

/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CPPTOOLSEDITORSUPPORT_H
#define CPPTOOLSEDITORSUPPORT_H
#include "cpphighlightingsupport.h"
#include "cppmodelmanager.h"
#include "cppsemanticinfo.h"
#include "cppsnapshotupdater.h"
#include <cplusplus/Control.h>
#include <cplusplus/CppDocument.h>
#include <QFuture>
#include <QObject>
#include <QPointer>
#include <QSharedPointer>
#include <QTimer>
namespace CPlusPlus {
class AST;
class DeclarationAST;
} // namespace CPlusPlus
namespace TextEditor {
class BaseTextEditor;
class ITextMark;
} // namespace TextEditor
namespace CppTools {
class CppCompletionAssistProvider;
/**
* \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 document 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
typedef TextEditor::BlockRange BlockRange;
public:
CppEditorSupport(Internal::CppModelManager *modelManager, TextEditor::BaseTextEditor *textEditor);
virtual ~CppEditorSupport();
QString fileName() const;
QByteArray contents() const;
unsigned editorRevision() const;
void setExtraDiagnostics(const QString &key,
const QList<CPlusPlus::Document::DiagnosticMessage> &messages);
void setIfdefedOutBlocks(const QList<BlockRange> &ifdefedOutBlocks);
/// True after the document was parsed/updated for the first time
/// and the first semantic info calculation was started.
bool initialized();
/// Retrieve the semantic info, which will get recalculated on the current
/// thread if it is outdate. Will not emit the semanticInfoUpdated() signal.
SemanticInfo recalculateSemanticInfo();
CPlusPlus::Document::Ptr lastSemanticInfoDocument() const;
enum ForceReason {
NoForce,
ForceDueToInvalidSemanticInfo,
ForceDueEditorRequest
};
/// Recalculates the semantic info in a future, and will emit the
/// semanticInfoUpdated() signal when finished.
/// Requires that initialized() is true.
/// \param forceReason the reason to force, if any
void recalculateSemanticInfoDetached(ForceReason forceReason);
CppCompletionAssistProvider *completionAssistProvider() const;
QSharedPointer<SnapshotUpdater> snapshotUpdater();
/// Checks whether the document is (re)parsed or about to be (re)parsed.
bool isUpdatingDocument();
signals:
void documentUpdated();
void diagnosticsChanged();
void semanticInfoUpdated(CppTools::SemanticInfo);
void highlighterStarted(QFuture<TextEditor::HighlightingResult> *, unsigned revision);
private slots:
void onMimeTypeChanged();
void onAboutToReload();
void onReloadFinished();
void updateDocument();
void updateDocumentNow();
void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
void startHighlighting(ForceReason forceReason = NoForce);
void onDiagnosticsChanged();
void updateEditor();
void updateEditorNow();
void onCurrentEditorChanged();
void releaseResources();
private:
struct EditorUpdates {
EditorUpdates()
: revision(-1)
{}
int revision;
QList<QTextEdit::ExtraSelection> selections;
QList<BlockRange> ifdefedOutBlocks;
};
enum {
UpdateDocumentDefaultInterval = 150,
UpdateEditorInterval = 300,
EditorHiddenGCTimeout = 2 * 60 * 1000 // 2 minutes
};
private:
class FuturizedTopLevelDeclarationProcessor: public CPlusPlus::TopLevelDeclarationProcessor
{
public:
FuturizedTopLevelDeclarationProcessor(QFutureInterface<void> &future): m_future(future) {}
bool processDeclaration(CPlusPlus::DeclarationAST *) { return !isCanceled(); }
bool isCanceled() { return m_future.isCanceled(); }
private:
QFutureInterface<void> m_future;
};
SemanticInfo::Source currentSource(bool force);
SemanticInfo recalculateSemanticInfoNow(const SemanticInfo::Source &source,
bool emitSignalWhenFinished,
FuturizedTopLevelDeclarationProcessor *processor = 0);
void recalculateSemanticInfoDetached_helper(QFutureInterface<void> &future,
SemanticInfo::Source source);
bool isSemanticInfoValid() const;
SemanticInfo semanticInfo() const;
void setSemanticInfo(const SemanticInfo &semanticInfo, bool emitSignal = true);
QSharedPointer<SnapshotUpdater> snapshotUpdater_internal() const;
void setSnapshotUpdater_internal(const QSharedPointer<SnapshotUpdater> &updater);
private:
Internal::CppModelManager *m_modelManager;
QPointer<TextEditor::BaseTextEditor> m_textEditor;
TextEditor::BaseTextDocument *m_editorDocument;
QTimer *m_updateDocumentTimer;
int m_updateDocumentInterval;
unsigned m_revision;
QFuture<void> m_documentParser;
QTimer *m_editorGCTimer;
bool m_editorVisible;
// content caching
mutable QMutex m_cachedContentsLock;
mutable QByteArray m_cachedContents;
mutable int m_cachedContentsEditorRevision;
bool m_fileIsBeingReloaded;
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;
mutable QMutex m_snapshotUpdaterLock;
QSharedPointer<SnapshotUpdater> m_snapshotUpdater;
// Highlighting:
unsigned m_lastHighlightRevision;
bool m_lastHighlightOnCompleteSemanticInfo;
QFuture<TextEditor::HighlightingResult> m_highlighter;
QScopedPointer<CppTools::CppHighlightingSupport> m_highlightingSupport;
// Completion:
CppCompletionAssistProvider *m_completionAssistProvider;
};
} // namespace CppTools
#endif // CPPTOOLSEDITORSUPPORT_H