diff --git a/src/tools/clangbackend/ipcsource/clangipcserver.cpp b/src/tools/clangbackend/ipcsource/clangipcserver.cpp index 7165ed24a51..ac04f932030 100644 --- a/src/tools/clangbackend/ipcsource/clangipcserver.cpp +++ b/src/tools/clangbackend/ipcsource/clangipcserver.cpp @@ -193,6 +193,8 @@ void ClangIpcServer::registerProjectPartsForEditor(const RegisterProjectPartsFor try { projects.createOrUpdate(message.projectContainers()); + translationUnits.setTranslationUnitsDirtyIfProjectPartChanged(); + sendDocumentAnnotationsTimer.start(0); } catch (const std::exception &exception) { qWarning() << "Error in ClangIpcServer::registerProjectPartsForEditor:" << exception.what(); } diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp b/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp index 5df086781ff..4954cd79048 100644 --- a/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp +++ b/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp @@ -276,13 +276,16 @@ const QSet &TranslationUnit::dependedFilePaths() const return d->dependedFilePaths; } +void TranslationUnit::setDirtyIfProjectPartIsOutdated() +{ + if (projectPartIsOutdated()) + setDirty(); +} + void TranslationUnit::setDirtyIfDependencyIsMet(const Utf8String &filePath) { - if (d->dependedFilePaths.contains(filePath) && isMainFileAndExistsOrIsOtherFile(filePath)) { - d->needsToBeReparsed = true; - d->hasNewDiagnostics = true; - d->hasNewHighlightingInformations = true; - } + if (d->dependedFilePaths.contains(filePath) && isMainFileAndExistsOrIsOtherFile(filePath)) + setDirty(); } SourceLocation TranslationUnit::sourceLocationAt(uint line, uint column) const @@ -369,6 +372,13 @@ bool TranslationUnit::projectPartIsOutdated() const return d->projectPart.lastChangeTimePoint() >= d->lastProjectPartChangeTimePoint; } +void TranslationUnit::setDirty() +{ + d->needsToBeReparsed = true; + d->hasNewDiagnostics = true; + d->hasNewHighlightingInformations = true; +} + bool TranslationUnit::isMainFileAndExistsOrIsOtherFile(const Utf8String &filePath) const { if (filePath == d->filePath) diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunit.h b/src/tools/clangbackend/ipcsource/clangtranslationunit.h index 61d58c804cd..016067dc369 100644 --- a/src/tools/clangbackend/ipcsource/clangtranslationunit.h +++ b/src/tools/clangbackend/ipcsource/clangtranslationunit.h @@ -120,6 +120,7 @@ public: const QSet &dependedFilePaths() const; + void setDirtyIfProjectPartIsOutdated(); void setDirtyIfDependencyIsMet(const Utf8String &filePath); CommandLineArguments commandLineArguments() const; @@ -139,6 +140,7 @@ public: SkippedSourceRanges skippedSourceRanges() const; private: + void setDirty(); void checkIfNull() const; void checkIfFileExists() const; void updateLastProjectPartChangeTimePoint() const; diff --git a/src/tools/clangbackend/ipcsource/projectpart.h b/src/tools/clangbackend/ipcsource/projectpart.h index 7272fd0a89e..6904ba35fdf 100644 --- a/src/tools/clangbackend/ipcsource/projectpart.h +++ b/src/tools/clangbackend/ipcsource/projectpart.h @@ -31,11 +31,12 @@ #ifndef CLANGBACKEND_PROJECT_H #define CLANGBACKEND_PROJECT_H +#include + #include #include #include -class Utf8String; class Utf8StringVector; namespace ClangBackEnd { @@ -48,7 +49,7 @@ using time_point = std::chrono::steady_clock::time_point; class ProjectPart { public: - ProjectPart(const Utf8String &projectPartId); + ProjectPart(const Utf8String &projectPartId = Utf8String()); ProjectPart(const Utf8String &projectPartId, std::initializer_list arguments); ProjectPart(const ProjectPartContainer &projectContainer); diff --git a/src/tools/clangbackend/ipcsource/translationunits.cpp b/src/tools/clangbackend/ipcsource/translationunits.cpp index 885eabaefae..ad84e0a3797 100644 --- a/src/tools/clangbackend/ipcsource/translationunits.cpp +++ b/src/tools/clangbackend/ipcsource/translationunits.cpp @@ -170,6 +170,12 @@ void TranslationUnits::updateTranslationUnitsWithChangedDependencies(const QVect updateTranslationUnitsWithChangedDependency(fileContainer.filePath()); } +void TranslationUnits::setTranslationUnitsDirtyIfProjectPartChanged() +{ + for (auto &translationUnit : translationUnits_) + translationUnit.setDirtyIfProjectPartIsOutdated(); +} + DocumentAnnotationsSendState TranslationUnits::sendDocumentAnnotations() { auto documentAnnotationsSendState = sendDocumentAnnotationsForCurrentEditor(); diff --git a/src/tools/clangbackend/ipcsource/translationunits.h b/src/tools/clangbackend/ipcsource/translationunits.h index 49ed36e7e29..28a1cb7b766 100644 --- a/src/tools/clangbackend/ipcsource/translationunits.h +++ b/src/tools/clangbackend/ipcsource/translationunits.h @@ -83,6 +83,7 @@ public: void updateTranslationUnitsWithChangedDependency(const Utf8String &filePath); void updateTranslationUnitsWithChangedDependencies(const QVector &fileContainers); + void setTranslationUnitsDirtyIfProjectPartChanged(); DocumentAnnotationsSendState sendDocumentAnnotationsForCurrentEditor(); DocumentAnnotationsSendState sendDocumentAnnotationsForVisibleEditors(); diff --git a/tests/unit/unittest/translationunitstest.cpp b/tests/unit/unittest/translationunitstest.cpp index 32414739674..3e4b9d9cf94 100644 --- a/tests/unit/unittest/translationunitstest.cpp +++ b/tests/unit/unittest/translationunitstest.cpp @@ -57,6 +57,7 @@ using ClangBackEnd::TranslationUnit; using ClangBackEnd::UnsavedFiles; using ClangBackEnd::ProjectPart; +using ClangBackEnd::ProjectPartContainer; using ClangBackEnd::DiagnosticsChangedMessage; using ClangBackEnd::HighlightingChangedMessage; using ClangBackEnd::DocumentAnnotationsSendState; @@ -483,9 +484,24 @@ TEST_F(TranslationUnits, SendDocumentAnnotationsOnlyOnceForVisibleEditor) sendAllDocumentAnnotationsForVisibleEditors(); } +TEST_F(TranslationUnits, SendDocumentAnnotationsAfterProjectPartChange) +{ + translationUnits.create({fileContainer, headerContainer}); + auto fileTranslationUnit = translationUnits.translationUnit(fileContainer); + fileTranslationUnit.setIsVisibleInEditor(true); + fileTranslationUnit.diagnostics(); // Reset + fileTranslationUnit.highlightingInformations(); // Reset + projects.createOrUpdate({ProjectPartContainer(projectPartId, {Utf8StringLiteral("-DNEW")})}); + translationUnits.setTranslationUnitsDirtyIfProjectPartChanged(); + + EXPECT_CALL(mockSendDocumentAnnotationsCallback, sendDocumentAnnotations()).Times(1); + + sendAllDocumentAnnotationsForVisibleEditors(); +} + void TranslationUnits::SetUp() { - projects.createOrUpdate({ClangBackEnd::ProjectPartContainer(projectPartId)}); + projects.createOrUpdate({ProjectPartContainer(projectPartId)}); auto callback = [&] (const DiagnosticsChangedMessage &, const HighlightingChangedMessage &) { mockSendDocumentAnnotationsCallback.sendDocumentAnnotations(); diff --git a/tests/unit/unittest/translationunittest.cpp b/tests/unit/unittest/translationunittest.cpp index 24bdcdac101..579f71bd61f 100644 --- a/tests/unit/unittest/translationunittest.cpp +++ b/tests/unit/unittest/translationunittest.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -55,10 +56,11 @@ #include #include - +using ClangBackEnd::FileContainer; using ClangBackEnd::TranslationUnit; using ClangBackEnd::UnsavedFiles; using ClangBackEnd::ProjectPart; +using ClangBackEnd::ProjectPartContainer; using ClangBackEnd::TranslationUnits; using testing::IsNull; @@ -74,19 +76,18 @@ namespace { class TranslationUnit : public ::testing::Test { protected: + void SetUp() override; ::TranslationUnit createTemporaryTranslationUnit(); QByteArray readContentFromTranslationUnitFile() const; protected: ClangBackEnd::ProjectParts projects; - ProjectPart projectPart{Utf8StringLiteral("/path/to/projectfile")}; + Utf8String projectPartId{Utf8StringLiteral("/path/to/projectfile")}; + ProjectPart projectPart; Utf8String translationUnitFilePath = Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp"); ClangBackEnd::UnsavedFiles unsavedFiles; ClangBackEnd::TranslationUnits translationUnits{projects, unsavedFiles}; - ::TranslationUnit translationUnit{translationUnitFilePath, - projectPart, - Utf8StringVector(), - translationUnits}; + ::TranslationUnit translationUnit; }; TEST_F(TranslationUnit, DefaultTranslationUnitIsInvalid) @@ -338,6 +339,36 @@ TEST_F(TranslationUnit, HasNoNewHighlightingInformationsAfterGettingHighlighting ASSERT_FALSE(translationUnit.hasNewHighlightingInformations()); } +TEST_F(TranslationUnit, SetDirtyIfProjectPartIsOutdated) +{ + projects.createOrUpdate({ProjectPartContainer(projectPartId)}); + translationUnit.cxTranslationUnit(); + projects.createOrUpdate({ProjectPartContainer(projectPartId, {Utf8StringLiteral("-DNEW")})}); + + translationUnit.setDirtyIfProjectPartIsOutdated(); + + ASSERT_TRUE(translationUnit.isNeedingReparse()); +} + +TEST_F(TranslationUnit, SetNotDirtyIfProjectPartIsNotOutdated) +{ + translationUnit.cxTranslationUnit(); + + translationUnit.setDirtyIfProjectPartIsOutdated(); + + ASSERT_FALSE(translationUnit.isNeedingReparse()); +} + +void TranslationUnit::SetUp() +{ + projects.createOrUpdate({ProjectPartContainer(projectPartId)}); + projectPart = *projects.findProjectPart(projectPartId); + + const QVector fileContainer{FileContainer(translationUnitFilePath, projectPartId)}; + const auto createdTranslationUnits = translationUnits.create(fileContainer); + translationUnit = createdTranslationUnits.front(); +} + ::TranslationUnit TranslationUnit::createTemporaryTranslationUnit() { QTemporaryFile temporaryFile; @@ -348,7 +379,7 @@ TEST_F(TranslationUnit, HasNoNewHighlightingInformationsAfterGettingHighlighting Utf8StringVector(), translationUnits); -return translationUnit; + return translationUnit; } QByteArray TranslationUnit::readContentFromTranslationUnitFile() const