From a1b78d42348bef01090ff9b39c7eeb713f432f47 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 3 Nov 2023 09:46:50 +0100 Subject: [PATCH] ClangCodeModel: Fix shadow document handling Our approach was not fully thought through: When we got informed of a file getting created by an ExtraCompiler, we would make it known to the first client that came along and then forget about it. This means that e.g. a source file including a UI header would parse fine with the first client that opened it, but after switching the build configuration or possibly even just touching the project file, the UI header would not be found anymore. Fix this by keeping the information about generated files around and attaching them to every newly initialized client. Note that this state should probably be kept somewhere more central. Change-Id: Ib1d8cca9258d1962513d8d463f5d16f9ff91a048 Reviewed-by: David Schulz --- .../clangmodelmanagersupport.cpp | 28 ++++++++----------- .../clangcodemodel/clangmodelmanagersupport.h | 2 +- src/plugins/languageclient/client.cpp | 2 ++ 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index e117e6b36f1..a25ceef0ff5 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -553,17 +553,15 @@ void ClangModelManagerSupport::updateLanguageClient(Project *project) hasDocuments = true; } - for (auto it = m_queuedShadowDocuments.begin(); it != m_queuedShadowDocuments.end();) { - if (fileIsProjectBuildArtifact(client, it.key())) { - if (it.value().isEmpty()) - client->removeShadowDocument(it.key()); - else - client->setShadowDocument(it.key(), it.value()); - ClangdClient::handleUiHeaderChange(it.key().fileName()); - it = m_queuedShadowDocuments.erase(it); - } else { - ++it; - } + for (auto it = m_potentialShadowDocuments.begin(); + it != m_potentialShadowDocuments.end(); ++it) { + if (!fileIsProjectBuildArtifact(client, it.key())) + continue; + if (it.value().isEmpty()) + client->removeShadowDocument(it.key()); + else + client->setShadowDocument(it.key(), it.value()); + ClangdClient::handleUiHeaderChange(it.key().fileName()); } updateParserConfig(client); @@ -799,10 +797,8 @@ void ClangModelManagerSupport::onAbstractEditorSupportContentsUpdated(const QStr if (Client * const client = clientForGeneratedFile(fp)) { client->setShadowDocument(fp, stringContent); ClangdClient::handleUiHeaderChange(fp.fileName()); - QTC_CHECK(m_queuedShadowDocuments.remove(fp) == 0); - } else { - m_queuedShadowDocuments.insert(fp, stringContent); } + m_potentialShadowDocuments.insert(fp, stringContent); } void ClangModelManagerSupport::onAbstractEditorSupportRemoved(const QString &filePath) @@ -813,10 +809,8 @@ void ClangModelManagerSupport::onAbstractEditorSupportRemoved(const QString &fil if (Client * const client = clientForGeneratedFile(fp)) { client->removeShadowDocument(fp); ClangdClient::handleUiHeaderChange(fp.fileName()); - QTC_CHECK(m_queuedShadowDocuments.remove(fp) == 0); - } else { - m_queuedShadowDocuments.insert(fp, {}); } + m_potentialShadowDocuments.remove(fp); } void addFixItsActionsToMenu(QMenu *menu, const TextEditor::QuickFixOperations &fixItOperations) diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h index 8121b9967a9..cc361127836 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h @@ -96,7 +96,7 @@ private: Utils::FutureSynchronizer m_generatorSynchronizer; QList> m_clientsToRestart; QTimer * const m_clientRestartTimer; - QHash m_queuedShadowDocuments; + QHash m_potentialShadowDocuments; }; } // namespace Internal diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index 7583b065988..976704fed5b 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -1058,6 +1058,8 @@ void Client::setShadowDocument(const Utils::FilePath &filePath, const QString &c if (shadowIt == d->m_shadowDocuments.end()) { shadowIt = d->m_shadowDocuments.insert(filePath, {content, {}}); } else { + if (shadowIt.value().first == content) + return; shadowIt.value().first = content; if (!shadowIt.value().second.isEmpty()) { VersionedTextDocumentIdentifier docId(hostPathToServerUri(filePath));