From 95e8afabba0ee66e5fe36514b2f27bf0d4f28dc2 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 12 Nov 2021 11:33:07 +0100 Subject: [PATCH] ClangCodeModel: Handle UI header updates with clangd We need to manually refresh the documents that include the generated header, as clangd does not know about it. Change-Id: I8c4303ac029bbb56c01aa99b7950dcc651701678 Reviewed-by: David Schulz --- src/plugins/clangcodemodel/clangdclient.cpp | 24 +++++++++++++++++++ src/plugins/clangcodemodel/clangdclient.h | 2 ++ .../clangmodelmanagersupport.cpp | 2 ++ 3 files changed, 28 insertions(+) diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 32996f6d015..7d034f7aac3 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -1539,6 +1539,30 @@ QString ClangdClient::displayNameFromDocumentSymbol(SymbolKind kind, const QStri } } +// Force re-parse of all open files that include the changed ui header. +// Otherwise, we potentially have stale diagnostics. +void ClangdClient::handleUiHeaderChange(const QString &fileName) +{ + const QRegularExpression includeRex("#include.*" + fileName + R"([>"])"); + const QVector &allClients = LanguageClientManager::clients(); + for (Client * const client : allClients) { + if (!client->reachable() || !qobject_cast(client)) + continue; + for (IDocument * const doc : DocumentModel::openedDocuments()) { + const auto textDoc = qobject_cast(doc); + if (!textDoc || !client->documentOpen(textDoc)) + continue; + const QTextCursor includePos = textDoc->document()->find(includeRex); + if (includePos.isNull()) + continue; + qCDebug(clangdLog) << "updating" << textDoc->filePath() << "due to change in UI header" + << fileName; + client->documentContentsChanged(textDoc, 0, 0, 0); + break; // No sane project includes the same UI header twice. + } + } +} + void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList &locations) { const auto refData = runningFindUsages.find(key); diff --git a/src/plugins/clangcodemodel/clangdclient.h b/src/plugins/clangcodemodel/clangdclient.h index 580168c3e33..de898696ec0 100644 --- a/src/plugins/clangcodemodel/clangdclient.h +++ b/src/plugins/clangcodemodel/clangdclient.h @@ -86,6 +86,8 @@ public: static QString displayNameFromDocumentSymbol(LanguageServerProtocol::SymbolKind kind, const QString &name, const QString &detail); + static void handleUiHeaderChange(const QString &fileName); + signals: void indexingFinished(); void foundReferences(const QList &items); diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 3bd9d2640f6..371fb224524 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -608,6 +608,7 @@ void ClangModelManagerSupport::onAbstractEditorSupportContentsUpdated(const QStr const QString mappedPath = m_uiHeaderOnDiskManager.write(filePath, content); m_communicator.unsavedFilesUpdated(mappedPath, content, 0); + ClangdClient::handleUiHeaderChange(Utils::FilePath::fromString(filePath).fileName()); } void ClangModelManagerSupport::onAbstractEditorSupportRemoved(const QString &filePath) @@ -618,6 +619,7 @@ void ClangModelManagerSupport::onAbstractEditorSupportRemoved(const QString &fil const QString mappedPath = m_uiHeaderOnDiskManager.remove(filePath); const QString projectPartId = projectPartIdForFile(filePath); m_communicator.unsavedFilesRemoved({{mappedPath, projectPartId}}); + ClangdClient::handleUiHeaderChange(Utils::FilePath::fromString(filePath).fileName()); } }