diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2022-02-08 11:49:37 +0100 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2022-02-10 12:58:30 +0000 |
commit | 6ede8b3bc0e96453e7c5725718b200cb8ac9b30f (patch) | |
tree | f50fa4dec3ebb5461b60b821ea071214ea68c888 | |
parent | 959e2b0124d5629f8a0703eb0f633e86fe89ebaf (diff) |
ClangCodeModel: Support parse contexts with clangd
Fixes: QTCREATORBUG-27009
Change-Id: I177db0658d545211b940623cae071db91e82ddb4
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: David Schulz <david.schulz@qt.io>
6 files changed, 90 insertions, 3 deletions
diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 48cb1bf13b..5988d04d40 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -1142,6 +1142,7 @@ public: std::unordered_map<TextDocument *, CppEditor::SemanticHighlighter *> highlighters; QHash<TextDocument *, QPair<QList<ExpandedSemanticToken>, int>> previousTokens; + QHash<Utils::FilePath, CppEditor::BaseEditorDocumentParser::Configuration> parserConfigs; // The ranges of symbols referring to virtual functions, with document version, // as extracted by the highlighting procedure. @@ -1468,6 +1469,7 @@ void ClangdClient::handleDocumentClosed(TextDocument *doc) d->astCache.remove(doc); d->previousTokens.remove(doc); d->virtualRanges.remove(doc); + d->parserConfigs.remove(doc->filePath()); } QTextCursor ClangdClient::adjustedCursorForHighlighting(const QTextCursor &cursor, @@ -1625,6 +1627,39 @@ void ClangdClient::handleUiHeaderChange(const QString &fileName) } } +void ClangdClient::updateParserConfig(const Utils::FilePath &filePath, + const CppEditor::BaseEditorDocumentParser::Configuration &config) +{ + if (config.preferredProjectPartId.isEmpty()) + return; + + CppEditor::BaseEditorDocumentParser::Configuration &cachedConfig = d->parserConfigs[filePath]; + if (cachedConfig == config) + return; + cachedConfig = config; + + // TODO: Also handle editorDefines (and usePrecompiledHeaders?) + const auto projectPart = CppEditor::CppModelManager::instance() + ->projectPartForId(config.preferredProjectPartId); + if (!projectPart) + return; + const CppEditor::ClangDiagnosticConfig projectWarnings = warningsConfigForProject(project()); + const QStringList projectOptions = optionsForProject(project()); + QJsonObject cdbChanges; + QStringList args = createClangOptions(*projectPart, filePath.toString(), projectWarnings, + projectOptions); + args.prepend("clang"); + args.append(filePath.toString()); + QJsonObject value; + value.insert("workingDirectory", filePath.parentDir().toString()); + value.insert("compilationCommand", QJsonArray::fromStringList(args)); + cdbChanges.insert(filePath.toUserOutput(), value); + const QJsonObject settings({qMakePair(QString("compilationDatabaseChanges"), cdbChanges)}); + DidChangeConfigurationParams configChangeParams; + configChangeParams.setSettings(settings); + sendContent(DidChangeConfigurationNotification(configChangeParams)); +} + void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Location> &locations) { const auto refData = runningFindUsages.find(key); diff --git a/src/plugins/clangcodemodel/clangdclient.h b/src/plugins/clangcodemodel/clangdclient.h index 92ca40d0ff..cc4b6aa71e 100644 --- a/src/plugins/clangcodemodel/clangdclient.h +++ b/src/plugins/clangcodemodel/clangdclient.h @@ -25,6 +25,7 @@ #pragma once +#include <cppeditor/baseeditordocumentparser.h> #include <cppeditor/cppcodemodelsettings.h> #include <cppeditor/refactoringengineinterface.h> #include <languageclient/client.h> @@ -88,6 +89,9 @@ public: static void handleUiHeaderChange(const QString &fileName); + void updateParserConfig(const Utils::FilePath &filePath, + const CppEditor::BaseEditorDocumentParser::Configuration &config); + signals: void indexingFinished(); void foundReferences(const QList<Core::SearchResultItem> &items); diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 2461120d9a..1b2027139f 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -328,6 +328,12 @@ void ClangEditorDocumentProcessor::setParserConfig( { m_parser->setConfiguration(config); m_builtinProcessor.parser()->setConfiguration(config); + emit parserConfigChanged(Utils::FilePath::fromString(filePath()), config); +} + +CppEditor::BaseEditorDocumentParser::Configuration ClangEditorDocumentProcessor::parserConfig() const +{ + return m_parser->configuration(); } static bool isCursorOnIdentifier(const QTextCursor &textCursor) diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h index 532c134b40..7111eee4c8 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h @@ -91,6 +91,7 @@ public: void editorDocumentTimerRestarted() override; void setParserConfig(const CppEditor::BaseEditorDocumentParser::Configuration &config) override; + CppEditor::BaseEditorDocumentParser::Configuration parserConfig() const; QFuture<CppEditor::CursorInfo> cursorInfo(const CppEditor::CursorInfoParams ¶ms) override; QFuture<CppEditor::CursorInfo> requestLocalReferences(const QTextCursor &cursor) override; @@ -115,6 +116,8 @@ public: signals: void tokenInfosUpdated(); + void parserConfigChanged(const Utils::FilePath &filePath, + const CppEditor::BaseEditorDocumentParser::Configuration &config); private: void onParserFinished(); diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 1d8a3f8af2..7ceb40011f 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -217,7 +217,15 @@ bool ClangModelManagerSupport::supportsLocalUses(const TextEditor::TextDocument CppEditor::BaseEditorDocumentProcessor *ClangModelManagerSupport::createEditorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) { - return new ClangEditorDocumentProcessor(m_communicator, baseTextDocument); + const auto processor = new ClangEditorDocumentProcessor(m_communicator, baseTextDocument); + const auto handleConfigChange = [this](const Utils::FilePath &fp, + const BaseEditorDocumentParser::Configuration &config) { + if (const auto client = clientForFile(fp)) + client->updateParserConfig(fp, config); + }; + connect(processor, &ClangEditorDocumentProcessor::parserConfigChanged, + this, handleConfigChange); + return processor; } void ClangModelManagerSupport::onCurrentEditorChanged(Core::IEditor *editor) @@ -233,6 +241,8 @@ void ClangModelManagerSupport::onCurrentEditorChanged(Core::IEditor *editor) if (auto processor = ClangEditorDocumentProcessor::get(filePath.toString())) { processor->semanticRehighlight(); processor->generateTaskHubIssues(); + if (const auto client = clientForFile(filePath)) + client->updateParserConfig(filePath, processor->parserConfig()); } } @@ -342,16 +352,38 @@ void ClangModelManagerSupport::updateLanguageClient( if (!newProjectInfo || *newProjectInfo != *projectInfo) return; + const auto updateParserConfig = [client] { + if (const auto editor = TextEditor::BaseTextEditor::currentTextEditor()) { + if (!client->documentOpen(editor->textDocument())) + return; + const Utils::FilePath filePath = editor->textDocument()->filePath(); + if (const auto processor = ClangEditorDocumentProcessor::get( + filePath.toString())) { + const CppEditor::BaseEditorDocumentParser::Configuration config + = processor->parserConfig(); + client->updateParserConfig(filePath, config); + } + } + }; + // Acquaint the client with all open C++ documents for this project. bool hasDocuments = false; for (TextEditor::BaseTextEditor * const editor : allCppEditors()) { - if (!project->isKnownFile(editor->textDocument()->filePath())) + const Utils::FilePath filePath = editor->textDocument()->filePath(); + if (!project->isKnownFile(filePath)) continue; LanguageClientManager::openDocumentWithClient(editor->textDocument(), client); - ClangEditorDocumentProcessor::clearTextMarks(editor->textDocument()->filePath()); + ClangEditorDocumentProcessor::clearTextMarks(filePath); hasDocuments = true; } + if (client->state() == Client::Initialized) + updateParserConfig(); + else + connect(client, &Client::initialized, client, updateParserConfig); + connect(CppModelManager::instance(), &CppModelManager::projectPartsUpdated, + client, updateParserConfig); + if (hasDocuments) return; diff --git a/src/plugins/cppeditor/baseeditordocumentparser.h b/src/plugins/cppeditor/baseeditordocumentparser.h index 2e10d56178..2f48058b8b 100644 --- a/src/plugins/cppeditor/baseeditordocumentparser.h +++ b/src/plugins/cppeditor/baseeditordocumentparser.h @@ -50,6 +50,13 @@ public: bool usePrecompiledHeaders = false; QByteArray editorDefines; QString preferredProjectPartId; + + bool operator==(const Configuration &other) + { + return usePrecompiledHeaders == other.usePrecompiledHeaders + && editorDefines == other.editorDefines + && preferredProjectPartId == other.preferredProjectPartId; + } }; struct UpdateParams { |