diff --git a/src/tools/clangbackend/ipcsource/clangipcserver.cpp b/src/tools/clangbackend/ipcsource/clangipcserver.cpp index 5376fc81ef1..4438ba023b9 100644 --- a/src/tools/clangbackend/ipcsource/clangipcserver.cpp +++ b/src/tools/clangbackend/ipcsource/clangipcserver.cpp @@ -63,6 +63,12 @@ ClangIpcServer::ClangIpcServer() { client()->diagnosticsChanged(message); }); + + sendDiagnosticsTimer.setInterval(2000); + sendDiagnosticsTimer.setSingleShot(true); + QObject::connect(&sendDiagnosticsTimer, + &QTimer::timeout, + [this] () { translationUnits.sendChangedDiagnostics(); }); } void ClangIpcServer::end() @@ -79,6 +85,7 @@ void ClangIpcServer::registerTranslationUnitsForCodeCompletion(const ClangBackEn if (newerFileContainers.size() > 0) { unsavedFiles.createOrUpdate(newerFileContainers); translationUnits.createOrUpdate(newerFileContainers); + sendDiagnosticsTimer.start(); } } catch (const ProjectPartDoNotExistException &exception) { client()->projectPartsDoNotExist(ProjectPartsDoNotExistMessage(exception.projectPartIds())); diff --git a/src/tools/clangbackend/ipcsource/clangipcserver.h b/src/tools/clangbackend/ipcsource/clangipcserver.h index 1716ade4630..5e4b6ef172a 100644 --- a/src/tools/clangbackend/ipcsource/clangipcserver.h +++ b/src/tools/clangbackend/ipcsource/clangipcserver.h @@ -62,6 +62,7 @@ private: ProjectParts projects; UnsavedFiles unsavedFiles; TranslationUnits translationUnits; + QTimer sendDiagnosticsTimer; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/translationunit.cpp b/src/tools/clangbackend/ipcsource/translationunit.cpp index 6501be75e61..eb5e265b8bd 100644 --- a/src/tools/clangbackend/ipcsource/translationunit.cpp +++ b/src/tools/clangbackend/ipcsource/translationunit.cpp @@ -70,6 +70,7 @@ public: CXIndex index = nullptr; uint documentRevision = 0; bool needsToBeReparsed = false; + bool hasNewDiagnostics = false; }; TranslationUnitData::TranslationUnitData(const Utf8String &filePath, @@ -190,10 +191,17 @@ bool TranslationUnit::isNeedingReparse() const return d->needsToBeReparsed; } +bool TranslationUnit::hasNewDiagnostics() const +{ + return d->hasNewDiagnostics; +} + DiagnosticSet TranslationUnit::diagnostics() const { reparseTranslationUnitIfFilesAreChanged(); + d->hasNewDiagnostics = false; + return DiagnosticSet(clang_getDiagnosticSetFromTU(cxTranslationUnit())); } @@ -204,10 +212,12 @@ const QSet &TranslationUnit::dependedFilePaths() const return d->dependedFilePaths; } -void TranslationUnit::updateIsNeedingReparseIfDependencyIsMet(const Utf8String &filePath) +void TranslationUnit::setDirtyIfDependencyIsMet(const Utf8String &filePath) { - if (d->dependedFilePaths.contains(filePath)) + if (d->dependedFilePaths.contains(filePath)) { d->needsToBeReparsed = true; + d->hasNewDiagnostics = true; + } } void TranslationUnit::checkIfNull() const diff --git a/src/tools/clangbackend/ipcsource/translationunit.h b/src/tools/clangbackend/ipcsource/translationunit.h index e02cd347f29..768654e0bee 100644 --- a/src/tools/clangbackend/ipcsource/translationunit.h +++ b/src/tools/clangbackend/ipcsource/translationunit.h @@ -97,12 +97,13 @@ public: const time_point &lastProjectPartChangeTimePoint() const; bool isNeedingReparse() const; + bool hasNewDiagnostics() const; DiagnosticSet diagnostics() const; const QSet &dependedFilePaths() const; - void updateIsNeedingReparseIfDependencyIsMet(const Utf8String &filePath); + void setDirtyIfDependencyIsMet(const Utf8String &filePath); private: void checkIfNull() const; diff --git a/src/tools/clangbackend/ipcsource/translationunits.cpp b/src/tools/clangbackend/ipcsource/translationunits.cpp index cc0147da73a..c0ec3a67e6c 100644 --- a/src/tools/clangbackend/ipcsource/translationunits.cpp +++ b/src/tools/clangbackend/ipcsource/translationunits.cpp @@ -64,8 +64,6 @@ void TranslationUnits::createOrUpdate(const QVector &fileContaine createOrUpdateTranslationUnit(fileContainer); updateTranslationUnitsWithChangedDependencies(fileContainer.filePath()); } - - sendChangedDiagnostics(); } static bool removeFromFileContainer(QVector &fileContainers, const TranslationUnit &translationUnit) @@ -132,14 +130,14 @@ void TranslationUnits::addWatchedFiles(QSet &filePaths) void TranslationUnits::updateTranslationUnitsWithChangedDependencies(const Utf8String &filePath) { for (auto &translationUnit : translationUnits_) - translationUnit.updateIsNeedingReparseIfDependencyIsMet(filePath); + translationUnit.setDirtyIfDependencyIsMet(filePath); } void TranslationUnits::sendChangedDiagnostics() { for (const auto &translationUnit : translationUnits_) { - if (translationUnit.isNeedingReparse()) - sendDiagnosticChangedMessage(translationUnit); + if (translationUnit.hasNewDiagnostics()) + sendDiagnosticChangedMessage(translationUnit); } } diff --git a/tests/unit/unittest/translationunittest.cpp b/tests/unit/unittest/translationunittest.cpp index f1247ade7fe..8eab8b1fe0c 100644 --- a/tests/unit/unittest/translationunittest.cpp +++ b/tests/unit/unittest/translationunittest.cpp @@ -28,6 +28,7 @@ ** ****************************************************************************/ +#include #include #include #include @@ -179,7 +180,7 @@ TEST_F(TranslationUnit, NoNeedForReparsingForIndependendFile) { translationUnit.cxTranslationUnit(); - translationUnit.updateIsNeedingReparseIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/otherfiles.h")); + translationUnit.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/otherfiles.h")); ASSERT_FALSE(translationUnit.isNeedingReparse()); } @@ -188,7 +189,7 @@ TEST_F(TranslationUnit, NeedsReparsingForDependendFile) { translationUnit.cxTranslationUnit(); - translationUnit.updateIsNeedingReparseIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h")); + translationUnit.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h")); ASSERT_TRUE(translationUnit.isNeedingReparse()); } @@ -197,21 +198,58 @@ TEST_F(TranslationUnit, NeedsReparsingForMainFile) { translationUnit.cxTranslationUnit(); - translationUnit.updateIsNeedingReparseIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp")); + translationUnit.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp")); ASSERT_TRUE(translationUnit.isNeedingReparse()); } -TEST_F(TranslationUnit, NeedsNoReparsingForDependendFileAfterReparsing) +TEST_F(TranslationUnit, NeedsNoReparsingAfterReparsing) { translationUnit.cxTranslationUnit(); - translationUnit.updateIsNeedingReparseIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h")); + translationUnit.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h")); translationUnit.cxTranslationUnit(); ASSERT_FALSE(translationUnit.isNeedingReparse()); } +TEST_F(TranslationUnit, HasNoNewDiagnosticsForIndependendFile) +{ + translationUnit.cxTranslationUnit(); + + translationUnit.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/otherfiles.h")); + + ASSERT_FALSE(translationUnit.hasNewDiagnostics()); +} + +TEST_F(TranslationUnit, HasNewDiagnosticsForDependendFile) +{ + translationUnit.cxTranslationUnit(); + + translationUnit.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h")); + + ASSERT_TRUE(translationUnit.hasNewDiagnostics()); +} + +TEST_F(TranslationUnit, HasNewDiagnosticsForMainFile) +{ + translationUnit.cxTranslationUnit(); + + translationUnit.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp")); + + ASSERT_TRUE(translationUnit.hasNewDiagnostics()); +} + +TEST_F(TranslationUnit, HasNoNewDiagnosticsAfterGettingDiagnostics) +{ + translationUnit.cxTranslationUnit(); + translationUnit.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp")); + + translationUnit.diagnostics(); + + ASSERT_FALSE(translationUnit.hasNewDiagnostics()); +} + //TEST_F(TranslationUnit, ThrowParseErrorForWrongArguments) //{ // ProjectPart project(Utf8StringLiteral("/path/to/projectfile"));