diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp index f4d76506cef..b71eaf0d76d 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp @@ -382,19 +382,50 @@ void IpcCommunicator::updateUnsavedFileFromCppEditorDocument(const QString &file 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, const QByteArray &contents, uint documentRevision) { const QString projectPartId = Utils::projectPartIdForFile(filePath); - const bool hasUnsavedContent = true; - // TODO: Send new only if changed - registerTranslationUnitsForEditor({{filePath, - projectPartId, - Utf8String::fromByteArray(contents), - hasUnsavedContent, - documentRevision}}); + if (documentHasChanged(filePath, projectPartId)) { + const bool hasUnsavedContent = true; + + registerTranslationUnitsForEditor({{filePath, + projectPartId, + Utf8String::fromByteArray(contents), + hasUnsavedContent, + documentRevision}}); + + setLastSentDocumentRevision(filePath, projectPartId, documentRevision); + } } void IpcCommunicator::updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision) @@ -412,8 +443,23 @@ void IpcCommunicator::updateUnsavedFile(const QString &filePath, const QByteArra void IpcCommunicator::requestDiagnostics(const FileContainer &fileContainer) { - registerTranslationUnitsForEditor({fileContainer}); - m_ipcSender->requestDiagnostics({fileContainer}); + if (documentHasChanged(fileContainer.filePath(), fileContainer.projectPartId())) { + registerTranslationUnitsForEditor({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) diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.h b/src/plugins/clangcodemodel/clangbackendipcintegration.h index 401cc59bccd..9c0a938538d 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.h +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.h @@ -137,6 +137,7 @@ public: void updateTranslationUnit(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 updateChangeContentStartPosition(const QString &filePath, int position); public: // for tests IpcSenderInterface *setIpcSender(IpcSenderInterface *ipcSender); @@ -159,6 +160,7 @@ private: void onEditorAboutToClose(Core::IEditor *editor); void onCoreAboutToClose(); +private: IpcReceiver m_ipcReceiver; ClangBackEnd::ConnectionClient m_connection; QScopedPointer m_ipcSender; diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp index 1fb68e0397e..de810d83bfb 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp @@ -35,12 +35,15 @@ #include "clangassistproposalmodel.h" #include "clangcompletionassistprocessor.h" #include "clangcompletioncontextanalyzer.h" +#include "clangeditordocumentprocessor.h" #include "clangfunctionhintmodel.h" #include "clangutils.h" #include "completionchunkstotextconverter.h" #include +#include + #include #include #include @@ -680,6 +683,51 @@ void ClangCompletionAssistProcessor::sendFileContent(const QString &projectPartI info.isDocumentModified, 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, const QByteArray &customFileContent) @@ -689,8 +737,13 @@ void ClangCompletionAssistProcessor::sendCompletionRequest(int position, ++column; const QString filePath = m_interface->fileName(); - const QString projectPartId = Utils::projectPartIdForFile(filePath); - sendFileContent(projectPartId, customFileContent); + const QString projectPartId = projectPartIdForEditorDocument(filePath); + + if (shouldSendDocumentForCompletion(filePath, projectPartId, position)) { + sendFileContent(projectPartId, customFileContent); + setLastCompletionPositionAndDocumentRevision(filePath, projectPartId, position); + } + m_interface->ipcCommunicator().completeCode(this, filePath, uint(line), diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 3d148f74562..cf75b428261 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -119,7 +119,7 @@ void ModelManagerSupportClang::connectTextDocumentToTranslationUnit(TextEditor:: Qt::UniqueConnection); // Handle changes from e.g. refactoring actions - connect(textDocument, &TextEditor::TextDocument::contentsChanged, + connect(textDocument, &TextEditor::TextDocument::contentsChangedWithPosition, this, &ModelManagerSupportClang::onCppDocumentContentsChangedOnTranslationUnit, Qt::UniqueConnection); } @@ -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(sender()); + + m_ipcCommunicator.updateChangeContentStartPosition(document->filePath().toString(), + position); m_ipcCommunicator.updateTranslationUnitIfNotCurrentDocument(document); } diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h index de621dc15b2..0e1f40510c7 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h @@ -67,7 +67,9 @@ private: void onEditorOpened(Core::IEditor *editor); void onCurrentEditorChanged(Core::IEditor *newCurrent); void onCppDocumentReloadFinishedOnTranslationUnit(bool success); - void onCppDocumentContentsChangedOnTranslationUnit(); + void onCppDocumentContentsChangedOnTranslationUnit(int position, + int charsRemoved, + int charsAdded); void onCppDocumentReloadFinishedOnUnsavedFile(bool success); void onCppDocumentContentsChangedOnUnsavedFile(); diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp index 0f7c29ff895..c89bb6bf43c 100644 --- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp +++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp @@ -512,6 +512,8 @@ public: bool succeeded() const { return m_editor && m_backendIsNotified; } bool waitUntilBackendIsNotified(int timeout = 10000); + bool waitUntilProjectPartChanged(const QString &newProjectPartId, int timeout = 10000); + bool waitUntil(const std::function &condition, int timeout); TextEditor::BaseTextEditor *editor() const { return m_editor; } private: @@ -536,12 +538,37 @@ OpenEditorAtCursorPosition::~OpenEditorAtCursorPosition() Core::EditorManager::closeEditor(m_editor, /* askAboutModifiedEditors= */ false); } + + 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(); + + 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 &condition, int timeout) +{ QTime time; time.start(); @@ -549,8 +576,7 @@ bool OpenEditorAtCursorPosition::waitUntilBackendIsNotified(int timeout) if (time.elapsed() > timeout) return false; - const auto *processor = ClangEditorDocumentProcessor::get(filePath); - if (processor && processor->projectPart()) + if (condition()) return true; QCoreApplication::processEvents(); @@ -968,6 +994,8 @@ void ClangCodeCompletionTest::testChangingProjectDependentCompletion() _("#define PROJECT_CONFIGURATION_1\n"), /* testOnlyForCleanedProjects= */ true); QVERIFY(projectLoader.load()); + openEditor.waitUntilProjectPartChanged(QLatin1String("myproject.project")); + proposal = completionResults(openEditor.editor()); QVERIFY(hasItem(proposal, "projectConfiguration1")); @@ -1045,6 +1073,8 @@ void ClangCodeCompletionTest::testUnsavedFilesTrackingByModifyingIncludedFileInN 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); CppTools::Tests::TemporaryDir temporaryDir; diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro index a97e2499073..61a249026e0 100644 --- a/src/plugins/cpptools/cpptools.pro +++ b/src/plugins/cpptools/cpptools.pro @@ -64,7 +64,8 @@ HEADERS += \ stringtable.h \ symbolfinder.h \ symbolsfindfilter.h \ - typehierarchybuilder.h + typehierarchybuilder.h \ + senddocumenttracker.h SOURCES += \ abstracteditorsupport.cpp \ @@ -126,7 +127,8 @@ SOURCES += \ stringtable.cpp \ symbolfinder.cpp \ symbolsfindfilter.cpp \ - typehierarchybuilder.cpp + typehierarchybuilder.cpp \ + senddocumenttracker.cpp FORMS += \ completionsettingspage.ui \ diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs index f5ffb85f46e..065ea0e4c11 100644 --- a/src/plugins/cpptools/cpptools.qbs +++ b/src/plugins/cpptools/cpptools.qbs @@ -84,6 +84,7 @@ QtcPlugin { "insertionpointlocator.cpp", "insertionpointlocator.h", "searchsymbols.cpp", "searchsymbols.h", "semantichighlighter.cpp", "semantichighlighter.h", + "senddocumenttracker.cpp", "senddocumenttracker.h", "stringtable.cpp", "stringtable.h", "symbolfinder.cpp", "symbolfinder.h", "symbolsfindfilter.cpp", "symbolsfindfilter.h", diff --git a/src/plugins/cpptools/cpptoolsunittestfiles.pri b/src/plugins/cpptools/cpptoolsunittestfiles.pri new file mode 100644 index 00000000000..6e0ab0d990c --- /dev/null +++ b/src/plugins/cpptools/cpptoolsunittestfiles.pri @@ -0,0 +1,3 @@ +HEADERS += $$PWD/senddocumenttracker.h + +SOURCES += $$PWD/senddocumenttracker.cpp diff --git a/src/plugins/cpptools/editordocumenthandle.cpp b/src/plugins/cpptools/editordocumenthandle.cpp index abf70ac9da3..07d91a0b8fe 100644 --- a/src/plugins/cpptools/editordocumenthandle.cpp +++ b/src/plugins/cpptools/editordocumenthandle.cpp @@ -58,4 +58,9 @@ void CppEditorDocumentHandle::setNeedsRefresh(bool needsRefresh) m_needsRefresh = needsRefresh; } +SendDocumentTracker &CppEditorDocumentHandle::sendTracker(const QString &projectPartId) +{ + return m_documentRevisionManagements[projectPartId]; +} + } // namespace CppTools diff --git a/src/plugins/cpptools/editordocumenthandle.h b/src/plugins/cpptools/editordocumenthandle.h index 2801f8c4e20..e4343bce3b7 100644 --- a/src/plugins/cpptools/editordocumenthandle.h +++ b/src/plugins/cpptools/editordocumenthandle.h @@ -32,6 +32,10 @@ #define EDITORDOCUMENTHANDLE_H #include "cpptools_global.h" +#include "senddocumenttracker.h" + +#include +#include namespace CppTools { class BaseEditorDocumentProcessor; @@ -55,7 +59,10 @@ public: virtual void resetProcessor() = 0; + SendDocumentTracker &sendTracker(const QString &projectPartId); + private: + QMap m_documentRevisionManagements; bool m_needsRefresh; }; diff --git a/src/plugins/cpptools/senddocumenttracker.cpp b/src/plugins/cpptools/senddocumenttracker.cpp new file mode 100644 index 00000000000..d594d1d82db --- /dev/null +++ b/src/plugins/cpptools/senddocumenttracker.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** 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 + +namespace CppTools { + +void SendDocumentTracker::setLastSentRevision(int revision) +{ + m_lastSentRevision = revision; + m_contentChangeStartPosition = std::numeric_limits::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 diff --git a/src/plugins/cpptools/senddocumenttracker.h b/src/plugins/cpptools/senddocumenttracker.h new file mode 100644 index 00000000000..ba4532d6a79 --- /dev/null +++ b/src/plugins/cpptools/senddocumenttracker.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** 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 + +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::max(); +}; + +} // namespace CppTools + +#endif // CPPTOOLS_SENDDOCUMENTTRACKER_H diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index dc3d7b4d522..cc28f20dc5a 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -236,7 +236,10 @@ TextDocument::TextDocument(Id id) 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 QTextOption opt = d->m_document.defaultTextOption(); diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h index 987e1bcdffe..e33af2300e7 100644 --- a/src/plugins/texteditor/textdocument.h +++ b/src/plugins/texteditor/textdocument.h @@ -144,6 +144,7 @@ signals: void aboutToOpen(const QString &fileName, const QString &realFileName); void openFinishedSuccessfully(); void contentsChanged(); + void contentsChangedWithPosition(int position, int charsRemoved, int charsAdded); void tabSettingsChanged(); void fontSettingsChanged(); diff --git a/tests/unit/unittest/creator_dependency.pri b/tests/unit/unittest/creator_dependency.pri index 0ad6f2e2c69..bb0a12ca022 100644 --- a/tests/unit/unittest/creator_dependency.pri +++ b/tests/unit/unittest/creator_dependency.pri @@ -2,6 +2,7 @@ include(../../../src/libs/sqlite/sqlite-lib.pri) include(../../../src/libs/clangbackendipc/clangbackendipc-lib.pri) include(../../../src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri) include(../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri) +include(../../../src/plugins/cpptools/cpptoolsunittestfiles.pri) include(cplusplus.pri) INCLUDEPATH += \ diff --git a/tests/unit/unittest/senddocumenttrackertest.cpp b/tests/unit/unittest/senddocumenttrackertest.cpp new file mode 100644 index 00000000000..daf6b0083bb --- /dev/null +++ b/tests/unit/unittest/senddocumenttrackertest.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** 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 + +#include +#include +#include +#include "gtest-qt-printing.h" + +using CppTools::SendDocumentTracker; +using testing::PrintToString; + +namespace { + +MATCHER_P2(HasValues, lastSentRevision, lastCompletionPosition, + std::string(negation ? "isn't" : "is") + + " DocumentRevisionManagement with last sent revision "+ PrintToString(lastSentRevision) + + " , last completion position " + PrintToString(lastCompletionPosition)) +{ + return arg.lastSentRevision() == lastSentRevision + && arg.lastCompletionPosition() == lastCompletionPosition; +} + +class SendDocumentTracker : public testing::Test +{ +protected: + ::SendDocumentTracker tracker; +}; + +TEST_F(SendDocumentTracker, DefaultLastSentRevision) +{ + ASSERT_THAT(tracker, HasValues(-1, -1)); +} + +TEST_F(SendDocumentTracker, SetRevision) +{ + tracker.setLastSentRevision(46); + + ASSERT_THAT(tracker, HasValues(46, -1)); +} + +TEST_F(SendDocumentTracker, SetLastCompletionPosition) +{ + tracker.setLastCompletionPosition(33); + + ASSERT_THAT(tracker, HasValues(-1, 33)); +} + +TEST_F(SendDocumentTracker, ApplyContentChange) +{ + tracker.setLastSentRevision(46); + tracker.setLastCompletionPosition(33); + + tracker.applyContentChange(10); + + ASSERT_THAT(tracker, HasValues(46, -1)); +} + +TEST_F(SendDocumentTracker, DontSendCompletionIfPositionIsEqual) +{ + tracker.setLastCompletionPosition(33); + + ASSERT_FALSE(tracker.shouldSendCompletion(33)); +} + +TEST_F(SendDocumentTracker, SendCompletionIfPositionIsDifferent) +{ + tracker.setLastSentRevision(46); + tracker.setLastCompletionPosition(33); + + ASSERT_TRUE(tracker.shouldSendCompletion(22)); +} + +TEST_F(SendDocumentTracker, SendCompletionIfChangeIsBeforeCompletionPositionAndPositionIsEqual) +{ + tracker.setLastSentRevision(46); + tracker.setLastCompletionPosition(33); + + tracker.applyContentChange(10); + + ASSERT_TRUE(tracker.shouldSendCompletion(33)); +} + +TEST_F(SendDocumentTracker, DontSendCompletionIfChangeIsAfterCompletionPositionAndPositionIsEqual) +{ + tracker.setLastSentRevision(46); + tracker.setLastCompletionPosition(33); + + tracker.applyContentChange(40); + + ASSERT_FALSE(tracker.shouldSendCompletion(33)); +} + +TEST_F(SendDocumentTracker, DontSendRevisionIfRevisionIsEqual) +{ + tracker.setLastSentRevision(46); + + ASSERT_FALSE(tracker.shouldSendRevision(46)); +} + +TEST_F(SendDocumentTracker, SendRevisionIfRevisionIsDifferent) +{ + tracker.setLastSentRevision(46); + + ASSERT_TRUE(tracker.shouldSendRevision(21)); +} + +TEST_F(SendDocumentTracker, DontSendIfRevisionIsDifferentAndCompletionPositionIsEqualAndNoContentChange) +{ + tracker.setLastSentRevision(46); + tracker.setLastCompletionPosition(33); + + ASSERT_FALSE(tracker.shouldSendRevisionWithCompletionPosition(21, 33)); +} + +TEST_F(SendDocumentTracker, DontSendIfRevisionIsDifferentAndCompletionPositionIsDifferentAndNoContentChange) +{ + tracker.setLastSentRevision(46); + tracker.setLastCompletionPosition(33); + + ASSERT_FALSE(tracker.shouldSendRevisionWithCompletionPosition(21, 44)); +} + +TEST_F(SendDocumentTracker, DontSendIfRevisionIsEqualAndCompletionPositionIsDifferentAndNoContentChange) +{ + tracker.setLastSentRevision(46); + tracker.setLastCompletionPosition(33); + + ASSERT_FALSE(tracker.shouldSendRevisionWithCompletionPosition(46,44)); +} + +TEST_F(SendDocumentTracker, SendIfChangeIsBeforeCompletionAndPositionIsEqualAndRevisionIsDifferent) +{ + tracker.setLastSentRevision(46); + tracker.setLastCompletionPosition(33); + + tracker.applyContentChange(10); + + ASSERT_TRUE(tracker.shouldSendRevisionWithCompletionPosition(45, 33)); +} + +TEST_F(SendDocumentTracker, DontSendIfChangeIsAfterCompletionPositionAndRevisionIsDifferent) +{ + tracker.setLastSentRevision(46); + tracker.setLastCompletionPosition(50); + + tracker.applyContentChange(40); + + ASSERT_FALSE(tracker.shouldSendRevisionWithCompletionPosition(45, 36)); +} + +TEST_F(SendDocumentTracker, SendIfChangeIsBeforeCompletionPositionAndRevisionIsDifferent) +{ + tracker.setLastSentRevision(46); + tracker.setLastCompletionPosition(50); + + tracker.applyContentChange(30); + + ASSERT_TRUE(tracker.shouldSendRevisionWithCompletionPosition(45, 36)); +} + +TEST_F(SendDocumentTracker, ResetChangedContentStartPositionIfLastRevisionIsSet) +{ + tracker.setLastSentRevision(46); + tracker.setLastCompletionPosition(50); + tracker.applyContentChange(30); + + tracker.setLastSentRevision(47); + + ASSERT_FALSE(tracker.shouldSendRevisionWithCompletionPosition(45, 36)); +} + +} diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index baedfa5df5d..ef5b91733b6 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -50,7 +50,8 @@ SOURCES += \ translationunitstest.cpp \ translationunittest.cpp \ unsavedfilestest.cpp \ - utf8test.cpp + utf8test.cpp \ + senddocumenttrackertest.cpp HEADERS += \ gtest-qt-printing.h \