diff --git a/src/plugins/clangcodemodel/clangeditordocumentparser.cpp b/src/plugins/clangcodemodel/clangeditordocumentparser.cpp index 23922355145..1d76245dc85 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentparser.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentparser.cpp @@ -42,7 +42,8 @@ void ClangEditorDocumentParser::updateImpl(const QFutureInterface &, state_.projectPart = determineProjectPart(filePath(), configuration(), state_, - updateParams.activeProject); + updateParams.activeProject, + updateParams.hasActiveProjectChanged); setState(state_); } diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 84534d6ae85..33f944db50d 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -119,7 +119,7 @@ void ClangEditorDocumentProcessor::runImpl( m_parserWatcher.setFuture(future); // Run builtin processor - m_builtinProcessor.run(); + m_builtinProcessor.runImpl(updateParams); } void ClangEditorDocumentProcessor::recalculateSemanticInfoDetached(bool force) diff --git a/src/plugins/cpptools/baseeditordocumentparser.cpp b/src/plugins/cpptools/baseeditordocumentparser.cpp index 30f16fb9cf9..f346e054155 100644 --- a/src/plugins/cpptools/baseeditordocumentparser.cpp +++ b/src/plugins/cpptools/baseeditordocumentparser.cpp @@ -121,7 +121,8 @@ ProjectPart::Ptr BaseEditorDocumentParser::determineProjectPart( const QString &filePath, const Configuration &config, const State &state, - const ProjectExplorer::Project *activeProject) + const ProjectExplorer::Project *activeProject, + bool hasActiveProjectChanged) { Internal::ProjectPartChooser chooser; chooser.setFallbackProjectPart([](){ @@ -139,7 +140,8 @@ ProjectPart::Ptr BaseEditorDocumentParser::determineProjectPart( state.projectPart, config.manuallySetProjectPart, config.stickToPreviousProjectPart, - activeProject); + activeProject, + hasActiveProjectChanged); } } // namespace CppTools diff --git a/src/plugins/cpptools/baseeditordocumentparser.h b/src/plugins/cpptools/baseeditordocumentparser.h index d41b0ed08f4..11f76fa67d2 100644 --- a/src/plugins/cpptools/baseeditordocumentparser.h +++ b/src/plugins/cpptools/baseeditordocumentparser.h @@ -54,14 +54,17 @@ public: struct UpdateParams { UpdateParams(const WorkingCopy &workingCopy, - const ProjectExplorer::Project *activeProject) + const ProjectExplorer::Project *activeProject, + bool hasActiveProjectChanged) : workingCopy(workingCopy) , activeProject(activeProject) + , hasActiveProjectChanged(hasActiveProjectChanged) { } WorkingCopy workingCopy; const ProjectExplorer::Project *activeProject = nullptr; + bool hasActiveProjectChanged = false; }; public: @@ -88,7 +91,8 @@ protected: static ProjectPart::Ptr determineProjectPart(const QString &filePath, const Configuration &config, const State &state, - const ProjectExplorer::Project *activeProject); + const ProjectExplorer::Project *activeProject, + bool hasActiveProjectChanged); mutable QMutex m_stateAndConfigurationMutex; diff --git a/src/plugins/cpptools/baseeditordocumentprocessor.cpp b/src/plugins/cpptools/baseeditordocumentprocessor.cpp index 2051136133d..bf68bc1c4ea 100644 --- a/src/plugins/cpptools/baseeditordocumentprocessor.cpp +++ b/src/plugins/cpptools/baseeditordocumentprocessor.cpp @@ -53,10 +53,11 @@ BaseEditorDocumentProcessor::~BaseEditorDocumentProcessor() { } -void BaseEditorDocumentProcessor::run() +void BaseEditorDocumentProcessor::run(bool hasActiveProjectChanged) { runImpl({CppModelManager::instance()->workingCopy(), - ProjectExplorer::SessionManager::startupProject()}); + ProjectExplorer::SessionManager::startupProject(), + hasActiveProjectChanged}); } TextEditor::QuickFixOperations diff --git a/src/plugins/cpptools/baseeditordocumentprocessor.h b/src/plugins/cpptools/baseeditordocumentprocessor.h index cd190137fba..f6fbba5011d 100644 --- a/src/plugins/cpptools/baseeditordocumentprocessor.h +++ b/src/plugins/cpptools/baseeditordocumentprocessor.h @@ -54,7 +54,7 @@ public: BaseEditorDocumentProcessor(QTextDocument *textDocument, const QString &filePath); virtual ~BaseEditorDocumentProcessor(); - void run(); + void run(bool hasActiveProjectChanged = false); virtual void semanticRehighlight() = 0; virtual void recalculateSemanticInfoDetached(bool force) = 0; virtual CppTools::SemanticInfo recalculateSemanticInfo() = 0; diff --git a/src/plugins/cpptools/builtineditordocumentparser.cpp b/src/plugins/cpptools/builtineditordocumentparser.cpp index 4edbbc491b5..77700e2cdfe 100644 --- a/src/plugins/cpptools/builtineditordocumentparser.cpp +++ b/src/plugins/cpptools/builtineditordocumentparser.cpp @@ -80,7 +80,8 @@ void BuiltinEditorDocumentParser::updateImpl(const QFutureInterface &futur baseState.projectPart = determineProjectPart(filePath(), baseConfig, baseState, - updateParams.activeProject); + updateParams.activeProject, + updateParams.hasActiveProjectChanged); if (state.forceSnapshotInvalidation) { invalidateSnapshot = true; diff --git a/src/plugins/cpptools/builtinindexingsupport.cpp b/src/plugins/cpptools/builtinindexingsupport.cpp index 5dc0d692e88..c4360f5fd79 100644 --- a/src/plugins/cpptools/builtinindexingsupport.cpp +++ b/src/plugins/cpptools/builtinindexingsupport.cpp @@ -158,7 +158,7 @@ void indexFindErrors(QFutureInterface &future, const ParseParams params) // Parse the file as precisely as possible BuiltinEditorDocumentParser parser(file); parser.setReleaseSourceAndAST(false); - parser.update({CppModelManager::instance()->workingCopy(), nullptr}); + parser.update({CppModelManager::instance()->workingCopy(), nullptr, false}); CPlusPlus::Document::Ptr document = parser.document(); QTC_ASSERT(document, return); diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp index 231c3c8a5bd..73800a094da 100644 --- a/src/plugins/cpptools/cppcompletionassist.cpp +++ b/src/plugins/cpptools/cppcompletionassist.cpp @@ -2122,7 +2122,7 @@ void CppCompletionAssistInterface::getCppSpecifics() const m_gotCppSpecifics = true; if (m_parser) { - m_parser->update({CppTools::CppModelManager::instance()->workingCopy(), nullptr}); + m_parser->update({CppTools::CppModelManager::instance()->workingCopy(), nullptr, false}); m_snapshot = m_parser->snapshot(); m_headerPaths = m_parser->headerPaths(); } diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 890fe2b1a7c..330501d3b3e 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -338,6 +338,8 @@ CppModelManager::CppModelManager(QObject *parent) this, &CppModelManager::onAboutToRemoveProject); connect(sessionManager, &ProjectExplorer::SessionManager::aboutToLoadSession, this, &CppModelManager::onAboutToLoadSession); + connect(sessionManager, &ProjectExplorer::SessionManager::startupProjectChanged, + this, &CppModelManager::onActiveProjectChanged); connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged, this, &CppModelManager::onCurrentEditorChanged); @@ -791,7 +793,7 @@ void CppModelManager::watchForCanceledProjectIndexer(QFuture future, watcher->setFuture(future); } -void CppModelManager::updateCppEditorDocuments() const +void CppModelManager::updateCppEditorDocuments(bool hasActiveProjectChanged) const { // Refresh visible documents QSet visibleCppEditorDocuments; @@ -800,7 +802,7 @@ void CppModelManager::updateCppEditorDocuments() const const QString filePath = document->filePath().toString(); if (CppEditorDocumentHandle *theCppEditorDocument = cppEditorDocument(filePath)) { visibleCppEditorDocuments.insert(document); - theCppEditorDocument->processor()->run(); + theCppEditorDocument->processor()->run(hasActiveProjectChanged); } } } @@ -811,8 +813,12 @@ void CppModelManager::updateCppEditorDocuments() const invisibleCppEditorDocuments.subtract(visibleCppEditorDocuments); foreach (Core::IDocument *document, invisibleCppEditorDocuments) { const QString filePath = document->filePath().toString(); - if (CppEditorDocumentHandle *theCppEditorDocument = cppEditorDocument(filePath)) - theCppEditorDocument->setNeedsRefresh(true); + if (CppEditorDocumentHandle *theCppEditorDocument = cppEditorDocument(filePath)) { + const CppEditorDocumentHandle::RefreshReason refreshReason = hasActiveProjectChanged + ? CppEditorDocumentHandle::ActiveProjectChange + : CppEditorDocumentHandle::Usual; + theCppEditorDocument->setRefreshReason(refreshReason); + } } } @@ -1038,6 +1044,11 @@ void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project) delayedGC(); } +void CppModelManager::onActiveProjectChanged(ProjectExplorer::Project *) +{ + updateCppEditorDocuments(true); +} + void CppModelManager::onSourceFilesRefreshed() const { if (BuiltinIndexingSupport::isFindErrorsIndexingActive()) { @@ -1053,9 +1064,13 @@ void CppModelManager::onCurrentEditorChanged(Core::IEditor *editor) const QString filePath = editor->document()->filePath().toString(); if (CppEditorDocumentHandle *theCppEditorDocument = cppEditorDocument(filePath)) { - if (theCppEditorDocument->needsRefresh()) { - theCppEditorDocument->setNeedsRefresh(false); - theCppEditorDocument->processor()->run(); + const CppEditorDocumentHandle::RefreshReason refreshReason + = theCppEditorDocument->refreshReason(); + if (refreshReason != CppEditorDocumentHandle::None) { + theCppEditorDocument->setRefreshReason(CppEditorDocumentHandle::None); + const bool hasActiveProjectChanged + = refreshReason == CppEditorDocumentHandle::ActiveProjectChange; + theCppEditorDocument->processor()->run(hasActiveProjectChanged); } } } diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index 8be30cd5ff0..4ce1ceed6cb 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -88,7 +88,7 @@ public: QFuture updateSourceFiles(const QSet &sourceFiles, ProgressNotificationMode mode = ReservedProgressNotification); - void updateCppEditorDocuments() const; + void updateCppEditorDocuments(bool hasActiveProjectChanged = false) const; WorkingCopy workingCopy() const; QByteArray codeModelConfiguration() const; @@ -203,6 +203,7 @@ private: void renameIncludes(const QString &oldFileName, const QString &newFileName); void onProjectAdded(ProjectExplorer::Project *project); void onAboutToRemoveProject(ProjectExplorer::Project *project); + void onActiveProjectChanged(ProjectExplorer::Project *project); void onSourceFilesRefreshed() const; void onCurrentEditorChanged(Core::IEditor *editor); void onCoreAboutToClose(); diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp index 56f4ff1f50d..d5f0b2fc090 100644 --- a/src/plugins/cpptools/cppmodelmanager_test.cpp +++ b/src/plugins/cpptools/cppmodelmanager_test.cpp @@ -877,7 +877,7 @@ void CppToolsPlugin::test_modelmanager_precompiled_headers() BaseEditorDocumentParser::Configuration config = parser->configuration(); config.usePrecompiledHeaders = true; parser->setConfiguration(config); - parser->update({CppModelManager::instance()->workingCopy(), nullptr}); + parser->update({CppModelManager::instance()->workingCopy(), nullptr, false}); // Check if defines from pch are considered Document::Ptr document = mm->document(fileName); @@ -955,7 +955,7 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor() BaseEditorDocumentParser::Configuration config = parser->configuration(); config.editorDefines = editorDefines.toUtf8(); parser->setConfiguration(config); - parser->update({CppModelManager::instance()->workingCopy(), nullptr}); + parser->update({CppModelManager::instance()->workingCopy(), nullptr, false}); Document::Ptr doc = mm->document(main1File); QCOMPARE(nameOfFirstDeclaration(doc), firstDeclarationName); diff --git a/src/plugins/cpptools/cppprojectpartchooser.cpp b/src/plugins/cpptools/cppprojectpartchooser.cpp index 0fb20f4750c..11e4ad01f25 100644 --- a/src/plugins/cpptools/cppprojectpartchooser.cpp +++ b/src/plugins/cpptools/cppprojectpartchooser.cpp @@ -43,7 +43,8 @@ ProjectPart::Ptr ProjectPartChooser::choose(const QString &filePath, const ProjectPart::Ptr ¤tProjectPart, const ProjectPart::Ptr &manuallySetProjectPart, bool stickToPreviousProjectPart, - const ProjectExplorer::Project *activeProject) const + const ProjectExplorer::Project *activeProject, + bool projectHasChanged) const { QTC_CHECK(m_projectPartsForFile); QTC_CHECK(m_projectPartsFromDependenciesForFile); @@ -69,8 +70,7 @@ ProjectPart::Ptr ProjectPartChooser::choose(const QString &filePath, else projectPart = selectFromActiveProject(projectParts, activeProject); } else { - if (!projectParts.contains(projectPart)) - // Apparently the project file changed, so update our project part. + if (projectHasChanged || !projectParts.contains(projectPart)) projectPart = selectFromActiveProject(projectParts, activeProject); } diff --git a/src/plugins/cpptools/cppprojectpartchooser.h b/src/plugins/cpptools/cppprojectpartchooser.h index fb26c3270d5..1ad6da10af5 100644 --- a/src/plugins/cpptools/cppprojectpartchooser.h +++ b/src/plugins/cpptools/cppprojectpartchooser.h @@ -51,7 +51,8 @@ public: const ProjectPart::Ptr ¤tProjectPart, const ProjectPart::Ptr &manuallySetProjectPart, bool stickToPreviousProjectPart, - const ProjectExplorer::Project *activeProject) const; + const ProjectExplorer::Project *activeProject, + bool projectHasChanged) const; private: FallBackProjectPart m_fallbackProjectPart; diff --git a/src/plugins/cpptools/editordocumenthandle.cpp b/src/plugins/cpptools/editordocumenthandle.cpp index 9fb74fa89d4..9d999b4bec4 100644 --- a/src/plugins/cpptools/editordocumenthandle.cpp +++ b/src/plugins/cpptools/editordocumenthandle.cpp @@ -34,28 +34,23 @@ namespace CppTools { C++ editor document. */ -CppEditorDocumentHandle::CppEditorDocumentHandle() - : m_needsRefresh(false) -{ -} - CppEditorDocumentHandle::~CppEditorDocumentHandle() { } -bool CppEditorDocumentHandle::needsRefresh() const -{ - return m_needsRefresh; -} - -void CppEditorDocumentHandle::setNeedsRefresh(bool needsRefresh) -{ - m_needsRefresh = needsRefresh; -} - SendDocumentTracker &CppEditorDocumentHandle::sendTracker() { return m_sendTracker; } +CppEditorDocumentHandle::RefreshReason CppEditorDocumentHandle::refreshReason() const +{ + return m_refreshReason; +} + +void CppEditorDocumentHandle::setRefreshReason(const RefreshReason &refreshReason) +{ + m_refreshReason = refreshReason; +} + } // namespace CppTools diff --git a/src/plugins/cpptools/editordocumenthandle.h b/src/plugins/cpptools/editordocumenthandle.h index 2e7d4784c34..16b69ab751f 100644 --- a/src/plugins/cpptools/editordocumenthandle.h +++ b/src/plugins/cpptools/editordocumenthandle.h @@ -36,11 +36,15 @@ class BaseEditorDocumentProcessor; class CPPTOOLS_EXPORT CppEditorDocumentHandle { public: - CppEditorDocumentHandle(); virtual ~CppEditorDocumentHandle(); - bool needsRefresh() const; - void setNeedsRefresh(bool needsRefresh); + enum RefreshReason { + None, + Usual, // e.g. project configuration change or change of editor contents + ActiveProjectChange + }; + RefreshReason refreshReason() const; + void setRefreshReason(const RefreshReason &refreshReason); // For the Working Copy virtual QString filePath() const = 0; @@ -56,7 +60,7 @@ public: private: SendDocumentTracker m_sendTracker; - bool m_needsRefresh; + RefreshReason m_refreshReason = None; }; } // namespace CppTools diff --git a/tests/unit/unittest/cppprojectpartchooser-test.cpp b/tests/unit/unittest/cppprojectpartchooser-test.cpp index 528f773c3ac..fd1456a038d 100644 --- a/tests/unit/unittest/cppprojectpartchooser-test.cpp +++ b/tests/unit/unittest/cppprojectpartchooser-test.cpp @@ -49,6 +49,7 @@ protected: ProjectPart::Ptr manuallySetProjectPart; bool stickToPreviousProjectPart = false; const ProjectExplorer::Project *activeProject = nullptr; + bool projectHasChanged = false; ::ProjectPartChooser chooser; QList projectPartsForFile; @@ -100,6 +101,21 @@ TEST_F(ProjectPartChooser, ForMultipleFromDependenciesChooseFromActiveProject) ASSERT_THAT(chosen, Eq(secondProjectPart)); } +TEST_F(ProjectPartChooser, ForMultipleCheckIfActiveProjectChanged) +{ + const QList projectParts = createProjectPartsWithDifferentProjects(); + const ProjectPart::Ptr firstProjectPart = projectParts.at(0); + const ProjectPart::Ptr secondProjectPart = projectParts.at(1); + projectPartsForFile += projectParts; + currentProjectPart = firstProjectPart; + activeProject = secondProjectPart->project; + projectHasChanged = true; + + const ProjectPart::Ptr chosen = choose(); + + ASSERT_THAT(chosen, Eq(secondProjectPart)); +} + TEST_F(ProjectPartChooser, IfProjectIsGoneStickToPrevious) // Built-in Code Model { stickToPreviousProjectPart = true; @@ -167,7 +183,8 @@ const ProjectPart::Ptr ProjectPartChooser::choose() const currentProjectPart, manuallySetProjectPart, stickToPreviousProjectPart, - activeProject); + activeProject, + projectHasChanged); } QList ProjectPartChooser::createProjectPartsWithDifferentProjects()