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>
This commit is contained in:
Erik Verbruggen
2013-04-17 10:58:20 +02:00
committed by Nikolai Kosjar
parent e8d59fb76f
commit 0c27b27658
11 changed files with 641 additions and 640 deletions

View File

@@ -38,6 +38,7 @@
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/icore.h>
#include <cpptools/cpptoolseditorsupport.h>
#include <cpptools/cpptoolsplugin.h>
#include <cpptools/cpptoolsconstants.h>
#include <cpptools/cppchecksymbols.h>
@@ -176,64 +177,6 @@ private:
CPlusPlus::OverviewModel *m_sourceModel;
};
class FunctionDefinitionUnderCursor: protected ASTVisitor
{
unsigned _line;
unsigned _column;
DeclarationAST *_functionDefinition;
public:
FunctionDefinitionUnderCursor(TranslationUnit *translationUnit)
: ASTVisitor(translationUnit),
_line(0), _column(0)
{ }
DeclarationAST *operator()(AST *ast, unsigned line, unsigned column)
{
_functionDefinition = 0;
_line = line;
_column = column;
accept(ast);
return _functionDefinition;
}
protected:
virtual bool preVisit(AST *ast)
{
if (_functionDefinition)
return false;
else if (FunctionDefinitionAST *def = ast->asFunctionDefinition()) {
return checkDeclaration(def);
}
else if (ObjCMethodDeclarationAST *method = ast->asObjCMethodDeclaration()) {
if (method->function_body)
return checkDeclaration(method);
}
return true;
}
private:
bool checkDeclaration(DeclarationAST *ast)
{
unsigned startLine, startColumn;
unsigned endLine, endColumn;
getTokenStartPosition(ast->firstToken(), &startLine, &startColumn);
getTokenEndPosition(ast->lastToken() - 1, &endLine, &endColumn);
if (_line > startLine || (_line == startLine && _column >= startColumn)) {
if (_line < endLine || (_line == endLine && _column < endColumn)) {
_functionDefinition = ast;
return false;
}
}
return true;
}
};
class FindFunctionDefinitions: protected SymbolVisitor
{
const Name *_declarationName;
@@ -573,14 +516,9 @@ CPPEditorWidget::CPPEditorWidget(QWidget *parent)
, m_objcEnabled(false)
, m_commentsSettings(CppTools::CppToolsSettings::instance()->commentsSettings())
, m_completionSupport(0)
, m_highlightingSupport(0)
{
m_initialized = false;
qRegisterMetaType<SemanticInfo>("CppTools::SemanticInfo");
m_semanticHighlighter = new SemanticHighlighter(this);
m_semanticHighlighter->start();
setParenthesesMatchingEnabled(true);
setMarksVisible(true);
setCodeFoldingSupported(true);
@@ -591,10 +529,15 @@ CPPEditorWidget::CPPEditorWidget(QWidget *parent)
m_modelManager = CppModelManagerInterface::instance();
if (m_modelManager) {
connect(m_modelManager, SIGNAL(documentUpdated(CPlusPlus::Document::Ptr)),
this, SLOT(onDocumentUpdated(CPlusPlus::Document::Ptr)));
CppEditorSupport *editorSupport = m_modelManager->cppEditorSupport(editor());
connect(editorSupport, SIGNAL(documentUpdated()),
this, SLOT(onDocumentUpdated()));
connect(editorSupport, SIGNAL(semanticInfoUpdated(CppTools::SemanticInfo)),
this, SLOT(updateSemanticInfo(CppTools::SemanticInfo)));
connect(editorSupport, SIGNAL(highlighterStarted(QFuture<TextEditor::HighlightingResult>, unsigned)),
this, SLOT(highlighterStarted(QFuture<TextEditor::HighlightingResult>, unsigned)));
m_completionSupport = m_modelManager->completionSupport(editor());
m_highlightingSupport = m_modelManager->highlightingSupport(editor());
}
m_highlightRevision = 0;
@@ -620,16 +563,12 @@ CPPEditorWidget::CPPEditorWidget(QWidget *parent)
CPPEditorWidget::~CPPEditorWidget()
{
m_semanticHighlighter->abort();
m_semanticHighlighter->wait();
++numberOfClosedEditors;
if (numberOfClosedEditors == 5) {
m_modelManager->GC();
numberOfClosedEditors = 0;
}
delete m_highlightingSupport;
delete m_completionSupport;
}
@@ -710,9 +649,6 @@ void CPPEditorWidget::createToolBar(CPPEditor *editor)
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateUses()));
connect(this, SIGNAL(textChanged()), this, SLOT(updateUses()));
connect(m_semanticHighlighter, SIGNAL(changed(CppTools::SemanticInfo)),
this, SLOT(updateSemanticInfo(CppTools::SemanticInfo)));
editor->insertExtraToolBarWidget(TextEditor::BaseTextEditor::Left, m_outlineCombo);
}
@@ -829,23 +765,10 @@ void CPPEditorWidget::abortRename()
semanticRehighlight(/* force = */ true);
}
void CPPEditorWidget::onDocumentUpdated(Document::Ptr doc)
/// \brief Called by \c CppEditorSupport when the document corresponding to the
/// file in this editor is updated.
void CPPEditorWidget::onDocumentUpdated()
{
if (doc->fileName() != editorDocument()->fileName())
return;
if (doc->editorRevision() != editorRevision())
return;
if (! m_initialized ||
(Core::EditorManager::currentEditor() == editor()
&& (!m_lastSemanticInfo.doc
|| !m_lastSemanticInfo.doc->translationUnit()->ast()
|| m_lastSemanticInfo.doc->fileName() != editorDocument()->fileName()))) {
m_initialized = true;
semanticRehighlight(/* force = */ true);
}
m_updateOutlineTimer->start();
}
@@ -1018,7 +941,8 @@ void CPPEditorWidget::markSymbols(const QTextCursor &tc, const SemanticInfo &inf
void CPPEditorWidget::renameSymbolUnderCursor()
{
updateSemanticInfo(m_semanticHighlighter->semanticInfo(currentSource()));
CppEditorSupport *edSup = m_modelManager->cppEditorSupport(editor());
updateSemanticInfo(edSup->recalculateSemanticInfo(/* emitSignalWhenFinished = */ false));
abortRename();
QTextCursor c = textCursor();
@@ -1246,7 +1170,7 @@ void CPPEditorWidget::finishHighlightSymbolUsages()
if (m_modelManager)
m_modelManager->setExtraDiagnostics(m_lastSemanticInfo.doc->fileName(),
CppTools::CppModelManagerInterface::CppSemanticsDiagnostic,
QLatin1String("CppEditor.SemanticsDiagnostics"),
m_lastSemanticInfo.doc->diagnosticMessages());
}
@@ -2051,7 +1975,15 @@ bool CPPEditorWidget::openCppEditorAt(const Link &link, bool inNextSplit)
void CPPEditorWidget::semanticRehighlight(bool force)
{
m_semanticHighlighter->rehighlight(currentSource(force));
m_modelManager->cppEditorSupport(editor())->recalculateSemanticInfoDetached(force);
}
void CPPEditorWidget::highlighterStarted(QFuture<TextEditor::HighlightingResult> highlighter,
unsigned revision)
{
m_highlighter = highlighter;
m_highlightRevision = revision;
m_highlightWatcher.setFuture(m_highlighter);
}
void CPPEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo)
@@ -2062,7 +1994,6 @@ void CPPEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo)
return;
}
const SemanticInfo previousSemanticInfo = m_lastSemanticInfo;
m_lastSemanticInfo = semanticInfo; // update the semantic info
int line = 0, column = 0;
@@ -2103,20 +2034,6 @@ void CPPEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo)
}
}
if (m_lastSemanticInfo.forced || previousSemanticInfo.revision != semanticInfo.revision) {
m_highlighter.cancel();
if (! semanticHighlighterDisabled && semanticInfo.doc) {
if (isVisible()) {
if (m_highlightingSupport) {
m_highlighter = m_highlightingSupport->highlightingFuture(semanticInfo.doc, semanticInfo.snapshot);
m_highlightRevision = semanticInfo.revision;
m_highlightWatcher.setFuture(m_highlighter);
}
}
}
}
setExtraSelections(UnusedSymbolSelection, unusedSelections);
if (! m_renameSelections.isEmpty())
@@ -2131,129 +2048,6 @@ void CPPEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo)
updateFunctionDeclDefLink();
}
SemanticHighlighter::Source CPPEditorWidget::currentSource(bool force)
{
int line = 0, column = 0;
convertPosition(position(), &line, &column);
const Snapshot snapshot = m_modelManager->snapshot();
const QString fileName = editorDocument()->fileName();
QString code;
if (force || m_lastSemanticInfo.revision != editorRevision())
code = toPlainText(); // get the source code only when needed.
const unsigned revision = editorRevision();
SemanticHighlighter::Source source(snapshot, fileName, code,
line, column, revision);
source.force = force;
return source;
}
SemanticHighlighter::SemanticHighlighter(QObject *parent)
: QThread(parent),
m_done(false)
{
}
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)
{
SemanticInfo semanticInfo;
semanticInfo.revision = m_lastSemanticInfo.revision;
semanticInfo.forced = source.force;
m_mutex.lock();
if (! source.force
&& m_lastSemanticInfo.revision == source.revision
&& m_lastSemanticInfo.doc
&& m_lastSemanticInfo.doc->translationUnit()->ast()
&& m_lastSemanticInfo.doc->fileName() == source.fileName) {
semanticInfo.snapshot = m_lastSemanticInfo.snapshot; // ### TODO: use the new snapshot.
semanticInfo.doc = m_lastSemanticInfo.doc;
}
m_mutex.unlock();
if (! semanticInfo.doc) {
semanticInfo.snapshot = source.snapshot;
if (source.snapshot.contains(source.fileName)) {
Document::Ptr doc = source.snapshot.preprocessedDocument(source.code, source.fileName);
doc->control()->setTopLevelDeclarationProcessor(this);
doc->check();
semanticInfo.doc = doc;
}
}
if (semanticInfo.doc) {
TranslationUnit *translationUnit = semanticInfo.doc->translationUnit();
AST * ast = translationUnit->ast();
FunctionDefinitionUnderCursor functionDefinitionUnderCursor(semanticInfo.doc->translationUnit());
DeclarationAST *currentFunctionDefinition = functionDefinitionUnderCursor(ast, source.line, source.column);
const LocalSymbols useTable(semanticInfo.doc, currentFunctionDefinition);
semanticInfo.revision = source.revision;
semanticInfo.localUses = useTable.uses;
}
return semanticInfo;
}
QModelIndex CPPEditorWidget::indexForPosition(int line, int column, const QModelIndex &rootIndex) const
{
QModelIndex lastIndex = rootIndex;