Commit b412eb81 authored by Marco Bubke's avatar Marco Bubke

Clang: Add revision and completion management

Reparsing a document is expensive so we should avoid it by all means. In
this patch we prevent that the same document is send again. It isn't send
too in advance of a code completion if there was no changes before the
the completion position.

Change-Id: I0bb786ba1d4e7ce08611a518cb32f8cf8f4d0037
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@theqtcompany.com>
parent 803cca40
...@@ -382,19 +382,50 @@ void IpcCommunicator::updateUnsavedFileFromCppEditorDocument(const QString &file ...@@ -382,19 +382,50 @@ void IpcCommunicator::updateUnsavedFileFromCppEditorDocument(const QString &file
updateUnsavedFile(filePath, document->contents(), document->revision()); updateUnsavedFile(filePath, document->contents(), document->revision());
} }
namespace {
CppTools::CppEditorDocumentHandle *cppDocument(const QString &filePath)
{
return CppTools::CppModelManager::instance()->cppEditorDocument(filePath);
}
bool documentHasChanged(const QString &filePath, const QString &projectPartId)
{
auto *document = cppDocument(filePath);
if (document)
return document->sendTracker(projectPartId).shouldSendRevision(document->revision());
return true;
}
void setLastSentDocumentRevision(const QString &filePath,
const QString &projectPartId,
uint revision)
{
auto *document = cppDocument(filePath);
if (document)
document->sendTracker(projectPartId).setLastSentRevision(int(revision));
}
}
void IpcCommunicator::updateTranslationUnit(const QString &filePath, void IpcCommunicator::updateTranslationUnit(const QString &filePath,
const QByteArray &contents, const QByteArray &contents,
uint documentRevision) uint documentRevision)
{ {
const QString projectPartId = Utils::projectPartIdForFile(filePath); const QString projectPartId = Utils::projectPartIdForFile(filePath);
if (documentHasChanged(filePath, projectPartId)) {
const bool hasUnsavedContent = true; const bool hasUnsavedContent = true;
// TODO: Send new only if changed
registerTranslationUnitsForEditor({{filePath, registerTranslationUnitsForEditor({{filePath,
projectPartId, projectPartId,
Utf8String::fromByteArray(contents), Utf8String::fromByteArray(contents),
hasUnsavedContent, hasUnsavedContent,
documentRevision}}); documentRevision}});
setLastSentDocumentRevision(filePath, projectPartId, documentRevision);
}
} }
void IpcCommunicator::updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision) void IpcCommunicator::updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision)
...@@ -412,8 +443,23 @@ void IpcCommunicator::updateUnsavedFile(const QString &filePath, const QByteArra ...@@ -412,8 +443,23 @@ void IpcCommunicator::updateUnsavedFile(const QString &filePath, const QByteArra
void IpcCommunicator::requestDiagnostics(const FileContainer &fileContainer) void IpcCommunicator::requestDiagnostics(const FileContainer &fileContainer)
{ {
if (documentHasChanged(fileContainer.filePath(), fileContainer.projectPartId())) {
registerTranslationUnitsForEditor({fileContainer}); registerTranslationUnitsForEditor({fileContainer});
m_ipcSender->requestDiagnostics({fileContainer}); m_ipcSender->requestDiagnostics({fileContainer});
setLastSentDocumentRevision(fileContainer.filePath(),
fileContainer.projectPartId(),
fileContainer.documentRevision());
}
}
void IpcCommunicator::updateChangeContentStartPosition(const QString &filePath, int position)
{
auto *document = cppDocument(filePath);
if (document) {
const QString projectPartId = Utils::projectPartIdForFile(filePath);
document->sendTracker(projectPartId).applyContentChange(position);
}
} }
void IpcCommunicator::updateTranslationUnitIfNotCurrentDocument(Core::IDocument *document) void IpcCommunicator::updateTranslationUnitIfNotCurrentDocument(Core::IDocument *document)
......
...@@ -137,6 +137,7 @@ public: ...@@ -137,6 +137,7 @@ public:
void updateTranslationUnit(const QString &filePath, const QByteArray &contents, uint documentRevision); void updateTranslationUnit(const QString &filePath, const QByteArray &contents, uint documentRevision);
void updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision); void updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision);
void requestDiagnostics(const ClangBackEnd::FileContainer &fileContainer); void requestDiagnostics(const ClangBackEnd::FileContainer &fileContainer);
void updateChangeContentStartPosition(const QString &filePath, int position);
public: // for tests public: // for tests
IpcSenderInterface *setIpcSender(IpcSenderInterface *ipcSender); IpcSenderInterface *setIpcSender(IpcSenderInterface *ipcSender);
...@@ -159,6 +160,7 @@ private: ...@@ -159,6 +160,7 @@ private:
void onEditorAboutToClose(Core::IEditor *editor); void onEditorAboutToClose(Core::IEditor *editor);
void onCoreAboutToClose(); void onCoreAboutToClose();
private:
IpcReceiver m_ipcReceiver; IpcReceiver m_ipcReceiver;
ClangBackEnd::ConnectionClient m_connection; ClangBackEnd::ConnectionClient m_connection;
QScopedPointer<IpcSenderInterface> m_ipcSender; QScopedPointer<IpcSenderInterface> m_ipcSender;
......
...@@ -35,12 +35,15 @@ ...@@ -35,12 +35,15 @@
#include "clangassistproposalmodel.h" #include "clangassistproposalmodel.h"
#include "clangcompletionassistprocessor.h" #include "clangcompletionassistprocessor.h"
#include "clangcompletioncontextanalyzer.h" #include "clangcompletioncontextanalyzer.h"
#include "clangeditordocumentprocessor.h"
#include "clangfunctionhintmodel.h" #include "clangfunctionhintmodel.h"
#include "clangutils.h" #include "clangutils.h"
#include "completionchunkstotextconverter.h" #include "completionchunkstotextconverter.h"
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <cpptools/editordocumenthandle.h>
#include <texteditor/codeassist/assistproposalitem.h> #include <texteditor/codeassist/assistproposalitem.h>
#include <texteditor/codeassist/functionhintproposal.h> #include <texteditor/codeassist/functionhintproposal.h>
#include <texteditor/codeassist/ifunctionhintproposalmodel.h> #include <texteditor/codeassist/ifunctionhintproposalmodel.h>
...@@ -680,6 +683,51 @@ void ClangCompletionAssistProcessor::sendFileContent(const QString &projectPartI ...@@ -680,6 +683,51 @@ void ClangCompletionAssistProcessor::sendFileContent(const QString &projectPartI
info.isDocumentModified, info.isDocumentModified,
uint(m_interface->textDocument()->revision())}}); uint(m_interface->textDocument()->revision())}});
} }
namespace {
CppTools::CppEditorDocumentHandle *cppDocument(const QString &filePath)
{
return CppTools::CppModelManager::instance()->cppEditorDocument(filePath);
}
bool shouldSendDocumentForCompletion(const QString &filePath,
const QString &projectPartId,
int completionPosition)
{
auto *document = cppDocument(filePath);
if (document) {
auto &sendTracker = document->sendTracker(projectPartId);
return sendTracker.shouldSendRevisionWithCompletionPosition(document->revision(),
completionPosition);
}
return true;
}
void setLastCompletionPositionAndDocumentRevision(const QString &filePath,
const QString &projectPartId,
int completionPosition)
{
auto *document = cppDocument(filePath);
if (document) {
document->sendTracker(projectPartId).setLastCompletionPosition(completionPosition);
document->sendTracker(projectPartId).setLastSentRevision(document->revision());
}
}
QString projectPartIdForEditorDocument(const QString &filePath)
{
auto projectPart = ClangEditorDocumentProcessor::get(filePath)->projectPart();
QString projectPartId;
if (projectPart)
projectPartId = projectPart->id();
return projectPartId;
}
}
void ClangCompletionAssistProcessor::sendCompletionRequest(int position, void ClangCompletionAssistProcessor::sendCompletionRequest(int position,
const QByteArray &customFileContent) const QByteArray &customFileContent)
...@@ -689,8 +737,13 @@ void ClangCompletionAssistProcessor::sendCompletionRequest(int position, ...@@ -689,8 +737,13 @@ void ClangCompletionAssistProcessor::sendCompletionRequest(int position,
++column; ++column;
const QString filePath = m_interface->fileName(); const QString filePath = m_interface->fileName();
const QString projectPartId = Utils::projectPartIdForFile(filePath); const QString projectPartId = projectPartIdForEditorDocument(filePath);
if (shouldSendDocumentForCompletion(filePath, projectPartId, position)) {
sendFileContent(projectPartId, customFileContent); sendFileContent(projectPartId, customFileContent);
setLastCompletionPositionAndDocumentRevision(filePath, projectPartId, position);
}
m_interface->ipcCommunicator().completeCode(this, m_interface->ipcCommunicator().completeCode(this,
filePath, filePath,
uint(line), uint(line),
......
...@@ -119,7 +119,7 @@ void ModelManagerSupportClang::connectTextDocumentToTranslationUnit(TextEditor:: ...@@ -119,7 +119,7 @@ void ModelManagerSupportClang::connectTextDocumentToTranslationUnit(TextEditor::
Qt::UniqueConnection); Qt::UniqueConnection);
// Handle changes from e.g. refactoring actions // Handle changes from e.g. refactoring actions
connect(textDocument, &TextEditor::TextDocument::contentsChanged, connect(textDocument, &TextEditor::TextDocument::contentsChangedWithPosition,
this, &ModelManagerSupportClang::onCppDocumentContentsChangedOnTranslationUnit, this, &ModelManagerSupportClang::onCppDocumentContentsChangedOnTranslationUnit,
Qt::UniqueConnection); Qt::UniqueConnection);
} }
...@@ -162,9 +162,14 @@ void ModelManagerSupportClang::onCppDocumentReloadFinishedOnTranslationUnit(bool ...@@ -162,9 +162,14 @@ void ModelManagerSupportClang::onCppDocumentReloadFinishedOnTranslationUnit(bool
} }
} }
void ModelManagerSupportClang::onCppDocumentContentsChangedOnTranslationUnit() void ModelManagerSupportClang::onCppDocumentContentsChangedOnTranslationUnit(int position,
int /*charsRemoved*/,
int /*charsAdded*/)
{ {
Core::IDocument *document = qobject_cast<Core::IDocument *>(sender()); Core::IDocument *document = qobject_cast<Core::IDocument *>(sender());
m_ipcCommunicator.updateChangeContentStartPosition(document->filePath().toString(),
position);
m_ipcCommunicator.updateTranslationUnitIfNotCurrentDocument(document); m_ipcCommunicator.updateTranslationUnitIfNotCurrentDocument(document);
} }
......
...@@ -67,7 +67,9 @@ private: ...@@ -67,7 +67,9 @@ private:
void onEditorOpened(Core::IEditor *editor); void onEditorOpened(Core::IEditor *editor);
void onCurrentEditorChanged(Core::IEditor *newCurrent); void onCurrentEditorChanged(Core::IEditor *newCurrent);
void onCppDocumentReloadFinishedOnTranslationUnit(bool success); void onCppDocumentReloadFinishedOnTranslationUnit(bool success);
void onCppDocumentContentsChangedOnTranslationUnit(); void onCppDocumentContentsChangedOnTranslationUnit(int position,
int charsRemoved,
int charsAdded);
void onCppDocumentReloadFinishedOnUnsavedFile(bool success); void onCppDocumentReloadFinishedOnUnsavedFile(bool success);
void onCppDocumentContentsChangedOnUnsavedFile(); void onCppDocumentContentsChangedOnUnsavedFile();
......
...@@ -512,6 +512,8 @@ public: ...@@ -512,6 +512,8 @@ public:
bool succeeded() const { return m_editor && m_backendIsNotified; } bool succeeded() const { return m_editor && m_backendIsNotified; }
bool waitUntilBackendIsNotified(int timeout = 10000); bool waitUntilBackendIsNotified(int timeout = 10000);
bool waitUntilProjectPartChanged(const QString &newProjectPartId, int timeout = 10000);
bool waitUntil(const std::function<bool()> &condition, int timeout);
TextEditor::BaseTextEditor *editor() const { return m_editor; } TextEditor::BaseTextEditor *editor() const { return m_editor; }
private: private:
...@@ -536,12 +538,37 @@ OpenEditorAtCursorPosition::~OpenEditorAtCursorPosition() ...@@ -536,12 +538,37 @@ OpenEditorAtCursorPosition::~OpenEditorAtCursorPosition()
Core::EditorManager::closeEditor(m_editor, /* askAboutModifiedEditors= */ false); Core::EditorManager::closeEditor(m_editor, /* askAboutModifiedEditors= */ false);
} }
bool OpenEditorAtCursorPosition::waitUntilBackendIsNotified(int timeout) bool OpenEditorAtCursorPosition::waitUntilBackendIsNotified(int timeout)
{ {
QTC_ASSERT(m_editor, return false); const QString filePath = m_editor->document()->filePath().toString();
auto condition = [filePath] () {
const auto *processor = ClangEditorDocumentProcessor::get(filePath);
return processor && processor->projectPart();
};
return waitUntil(condition, timeout);
}
bool OpenEditorAtCursorPosition::waitUntilProjectPartChanged(const QString &newProjectPartId,
int timeout)
{
const QString filePath = m_editor->document()->filePath().toString(); const QString filePath = m_editor->document()->filePath().toString();
auto condition = [newProjectPartId, filePath] () {
const auto *processor = ClangEditorDocumentProcessor::get(filePath);
return processor
&& processor->projectPart()
&& processor->projectPart()->id() == newProjectPartId;
};
return waitUntil(condition, timeout);
}
bool OpenEditorAtCursorPosition::waitUntil(const std::function<bool ()> &condition, int timeout)
{
QTime time; QTime time;
time.start(); time.start();
...@@ -549,8 +576,7 @@ bool OpenEditorAtCursorPosition::waitUntilBackendIsNotified(int timeout) ...@@ -549,8 +576,7 @@ bool OpenEditorAtCursorPosition::waitUntilBackendIsNotified(int timeout)
if (time.elapsed() > timeout) if (time.elapsed() > timeout)
return false; return false;
const auto *processor = ClangEditorDocumentProcessor::get(filePath); if (condition())
if (processor && processor->projectPart())
return true; return true;
QCoreApplication::processEvents(); QCoreApplication::processEvents();
...@@ -968,6 +994,8 @@ void ClangCodeCompletionTest::testChangingProjectDependentCompletion() ...@@ -968,6 +994,8 @@ void ClangCodeCompletionTest::testChangingProjectDependentCompletion()
_("#define PROJECT_CONFIGURATION_1\n"), _("#define PROJECT_CONFIGURATION_1\n"),
/* testOnlyForCleanedProjects= */ true); /* testOnlyForCleanedProjects= */ true);
QVERIFY(projectLoader.load()); QVERIFY(projectLoader.load());
openEditor.waitUntilProjectPartChanged(QLatin1String("myproject.project"));
proposal = completionResults(openEditor.editor()); proposal = completionResults(openEditor.editor());
QVERIFY(hasItem(proposal, "projectConfiguration1")); QVERIFY(hasItem(proposal, "projectConfiguration1"));
...@@ -1045,6 +1073,8 @@ void ClangCodeCompletionTest::testUnsavedFilesTrackingByModifyingIncludedFileInN ...@@ -1045,6 +1073,8 @@ void ClangCodeCompletionTest::testUnsavedFilesTrackingByModifyingIncludedFileInN
void ClangCodeCompletionTest::testUnsavedFilesTrackingByModifyingIncludedFileExternally() void ClangCodeCompletionTest::testUnsavedFilesTrackingByModifyingIncludedFileExternally()
{ {
QSKIP("The file system watcher is doing it in backend process but we wait not long enough");
ChangeDocumentReloadSetting reloadSettingsChanger(Core::IDocument::ReloadUnmodified); ChangeDocumentReloadSetting reloadSettingsChanger(Core::IDocument::ReloadUnmodified);
CppTools::Tests::TemporaryDir temporaryDir; CppTools::Tests::TemporaryDir temporaryDir;
......
...@@ -64,7 +64,8 @@ HEADERS += \ ...@@ -64,7 +64,8 @@ HEADERS += \
stringtable.h \ stringtable.h \
symbolfinder.h \ symbolfinder.h \
symbolsfindfilter.h \ symbolsfindfilter.h \
typehierarchybuilder.h typehierarchybuilder.h \
senddocumenttracker.h
SOURCES += \ SOURCES += \
abstracteditorsupport.cpp \ abstracteditorsupport.cpp \
...@@ -126,7 +127,8 @@ SOURCES += \ ...@@ -126,7 +127,8 @@ SOURCES += \
stringtable.cpp \ stringtable.cpp \
symbolfinder.cpp \ symbolfinder.cpp \
symbolsfindfilter.cpp \ symbolsfindfilter.cpp \
typehierarchybuilder.cpp typehierarchybuilder.cpp \
senddocumenttracker.cpp
FORMS += \ FORMS += \
completionsettingspage.ui \ completionsettingspage.ui \
......
...@@ -84,6 +84,7 @@ QtcPlugin { ...@@ -84,6 +84,7 @@ QtcPlugin {
"insertionpointlocator.cpp", "insertionpointlocator.h", "insertionpointlocator.cpp", "insertionpointlocator.h",
"searchsymbols.cpp", "searchsymbols.h", "searchsymbols.cpp", "searchsymbols.h",
"semantichighlighter.cpp", "semantichighlighter.h", "semantichighlighter.cpp", "semantichighlighter.h",
"senddocumenttracker.cpp", "senddocumenttracker.h",
"stringtable.cpp", "stringtable.h", "stringtable.cpp", "stringtable.h",
"symbolfinder.cpp", "symbolfinder.h", "symbolfinder.cpp", "symbolfinder.h",
"symbolsfindfilter.cpp", "symbolsfindfilter.h", "symbolsfindfilter.cpp", "symbolsfindfilter.h",
......
HEADERS += $$PWD/senddocumenttracker.h
SOURCES += $$PWD/senddocumenttracker.cpp
...@@ -58,4 +58,9 @@ void CppEditorDocumentHandle::setNeedsRefresh(bool needsRefresh) ...@@ -58,4 +58,9 @@ void CppEditorDocumentHandle::setNeedsRefresh(bool needsRefresh)
m_needsRefresh = needsRefresh; m_needsRefresh = needsRefresh;
} }
SendDocumentTracker &CppEditorDocumentHandle::sendTracker(const QString &projectPartId)
{
return m_documentRevisionManagements[projectPartId];
}
} // namespace CppTools } // namespace CppTools
...@@ -32,6 +32,10 @@ ...@@ -32,6 +32,10 @@
#define EDITORDOCUMENTHANDLE_H #define EDITORDOCUMENTHANDLE_H
#include "cpptools_global.h" #include "cpptools_global.h"
#include "senddocumenttracker.h"
#include <QMap>
#include <QString>
namespace CppTools { namespace CppTools {
class BaseEditorDocumentProcessor; class BaseEditorDocumentProcessor;
...@@ -55,7 +59,10 @@ public: ...@@ -55,7 +59,10 @@ public:
virtual void resetProcessor() = 0; virtual void resetProcessor() = 0;
SendDocumentTracker &sendTracker(const QString &projectPartId);
private: private:
QMap<QString, SendDocumentTracker> m_documentRevisionManagements;
bool m_needsRefresh; bool m_needsRefresh;
}; };
......
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** 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 The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "senddocumenttracker.h"
#include <algorithm>
namespace CppTools {
void SendDocumentTracker::setLastSentRevision(int revision)
{
m_lastSentRevision = revision;
m_contentChangeStartPosition = std::numeric_limits<int>::max();
}
int SendDocumentTracker::lastSentRevision() const
{
return m_lastSentRevision;
}
void SendDocumentTracker::setLastCompletionPosition(int lastCompletionPosition)
{
m_lastCompletionPosition = lastCompletionPosition;
}
int SendDocumentTracker::lastCompletionPosition() const
{
return m_lastCompletionPosition;
}
void SendDocumentTracker::applyContentChange(int startPosition)
{
if (startPosition < m_lastCompletionPosition)
m_lastCompletionPosition = -1;
m_contentChangeStartPosition = std::min(startPosition, m_contentChangeStartPosition);
}
bool SendDocumentTracker::shouldSendCompletion(int newCompletionPosition) const
{
return m_lastCompletionPosition != newCompletionPosition;
}
bool SendDocumentTracker::shouldSendRevision(uint newRevision) const
{
return m_lastSentRevision != int(newRevision);
}
bool SendDocumentTracker::shouldSendRevisionWithCompletionPosition(int newRevision, int newCompletionPosition) const
{
if (shouldSendRevision(newRevision))
return changedBeforeCompletionPosition(newCompletionPosition);
return false;
}
bool SendDocumentTracker::changedBeforeCompletionPosition(int newCompletionPosition) const
{
return m_contentChangeStartPosition < newCompletionPosition;
}
} // namespace CppTools
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** 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 The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CPPTOOLS_SENDDOCUMENTTRACKER_H
#define CPPTOOLS_SENDDOCUMENTTRACKER_H
#include "cpptools_global.h"
#include <limits>
namespace CppTools {
class CPPTOOLS_EXPORT SendDocumentTracker
{
public:
void setLastSentRevision(int lastSentRevision);
int lastSentRevision() const;
void setLastCompletionPosition(int lastCompletionPosition);
int lastCompletionPosition() const;
void applyContentChange(int startPosition);
bool shouldSendCompletion(int newCompletionPosition) const;
bool shouldSendRevision(uint newRevision) const;
bool shouldSendRevisionWithCompletionPosition(int newRevision, int newCompletionPosition) const;
private:
bool changedBeforeCompletionPosition(int newCompletionPosition) const;
private:
int m_lastSentRevision = -1;
int m_lastCompletionPosition = -1;
int m_contentChangeStartPosition = std::numeric_limits<int>::max();
};
} // namespace CppTools
#endif // CPPTOOLS_SENDDOCUMENTTRACKER_H
...@@ -236,7 +236,10 @@ TextDocument::TextDocument(Id id) ...@@ -236,7 +236,10 @@ TextDocument::TextDocument(Id id)
emit changed(); emit changed();
}); });
QObject::connect(&d->m_document, &QTextDocument::contentsChanged, this, &TextDocument::contentsChanged); connect(&d->m_document, &QTextDocument::contentsChanged,
this, &TextDocument::contentsChanged);
connect(&d->m_document, &QTextDocument::contentsChange,
this, &TextDocument::contentsChangedWithPosition);
// set new document layout // set new document layout
QTextOption opt = d->m_document.defaultTextOption(); QTextOption opt = d->m_document.defaultTextOption();
......
...@@ -144,6 +144,7 @@ signals: ...@@ -144,6 +144,7 @@ signals:
void aboutToOpen(const QString &fileName, const QString &realFileName); void aboutToOpen(const QString &fileName, const QString &realFileName);
void openFinishedSuccessfully(); void openFinishedSuccessfully();
void contentsChanged(); void contentsChanged();
void contentsChangedWithPosition(int position, int charsRemoved, int charsAdded);
void tabSettingsChanged(); void tabSettingsChanged();
void fontSettingsChanged(); void fontSettingsChanged();
......
...@@ -2,6 +2,7 @@ include(../../../src/libs/sqlite/sqlite-lib.pri) ...@@ -2,6 +2,7 @@ include(../../../src/libs/sqlite/sqlite-lib.pri)
include(../../../src/libs/clangbackendipc/clangbackendipc-lib.pri) include(../../../src/libs/clangbackendipc/clangbackendipc-lib.pri)
include(../../../src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri) include(../../../src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri)
include(../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri) include(../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri)
include(../../../src/plugins/cpptools/cpptoolsunittestfiles.pri)
include(cplusplus.pri) include(cplusplus.pri)
INCLUDEPATH += \ INCLUDEPATH += \
......
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** 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 The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and