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>
This commit is contained in:
Christian Kandeler
2022-02-08 11:49:37 +01:00
parent 959e2b0124
commit 6ede8b3bc0
6 changed files with 90 additions and 3 deletions

View File

@@ -1142,6 +1142,7 @@ public:
std::unordered_map<TextDocument *, CppEditor::SemanticHighlighter *> highlighters; std::unordered_map<TextDocument *, CppEditor::SemanticHighlighter *> highlighters;
QHash<TextDocument *, QPair<QList<ExpandedSemanticToken>, int>> previousTokens; 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, // The ranges of symbols referring to virtual functions, with document version,
// as extracted by the highlighting procedure. // as extracted by the highlighting procedure.
@@ -1468,6 +1469,7 @@ void ClangdClient::handleDocumentClosed(TextDocument *doc)
d->astCache.remove(doc); d->astCache.remove(doc);
d->previousTokens.remove(doc); d->previousTokens.remove(doc);
d->virtualRanges.remove(doc); d->virtualRanges.remove(doc);
d->parserConfigs.remove(doc->filePath());
} }
QTextCursor ClangdClient::adjustedCursorForHighlighting(const QTextCursor &cursor, 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) void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Location> &locations)
{ {
const auto refData = runningFindUsages.find(key); const auto refData = runningFindUsages.find(key);

View File

@@ -25,6 +25,7 @@
#pragma once #pragma once
#include <cppeditor/baseeditordocumentparser.h>
#include <cppeditor/cppcodemodelsettings.h> #include <cppeditor/cppcodemodelsettings.h>
#include <cppeditor/refactoringengineinterface.h> #include <cppeditor/refactoringengineinterface.h>
#include <languageclient/client.h> #include <languageclient/client.h>
@@ -88,6 +89,9 @@ public:
static void handleUiHeaderChange(const QString &fileName); static void handleUiHeaderChange(const QString &fileName);
void updateParserConfig(const Utils::FilePath &filePath,
const CppEditor::BaseEditorDocumentParser::Configuration &config);
signals: signals:
void indexingFinished(); void indexingFinished();
void foundReferences(const QList<Core::SearchResultItem> &items); void foundReferences(const QList<Core::SearchResultItem> &items);

View File

@@ -328,6 +328,12 @@ void ClangEditorDocumentProcessor::setParserConfig(
{ {
m_parser->setConfiguration(config); m_parser->setConfiguration(config);
m_builtinProcessor.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) static bool isCursorOnIdentifier(const QTextCursor &textCursor)

View File

@@ -91,6 +91,7 @@ public:
void editorDocumentTimerRestarted() override; void editorDocumentTimerRestarted() override;
void setParserConfig(const CppEditor::BaseEditorDocumentParser::Configuration &config) override; void setParserConfig(const CppEditor::BaseEditorDocumentParser::Configuration &config) override;
CppEditor::BaseEditorDocumentParser::Configuration parserConfig() const;
QFuture<CppEditor::CursorInfo> cursorInfo(const CppEditor::CursorInfoParams &params) override; QFuture<CppEditor::CursorInfo> cursorInfo(const CppEditor::CursorInfoParams &params) override;
QFuture<CppEditor::CursorInfo> requestLocalReferences(const QTextCursor &cursor) override; QFuture<CppEditor::CursorInfo> requestLocalReferences(const QTextCursor &cursor) override;
@@ -115,6 +116,8 @@ public:
signals: signals:
void tokenInfosUpdated(); void tokenInfosUpdated();
void parserConfigChanged(const Utils::FilePath &filePath,
const CppEditor::BaseEditorDocumentParser::Configuration &config);
private: private:
void onParserFinished(); void onParserFinished();

View File

@@ -217,7 +217,15 @@ bool ClangModelManagerSupport::supportsLocalUses(const TextEditor::TextDocument
CppEditor::BaseEditorDocumentProcessor *ClangModelManagerSupport::createEditorDocumentProcessor( CppEditor::BaseEditorDocumentProcessor *ClangModelManagerSupport::createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) 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) void ClangModelManagerSupport::onCurrentEditorChanged(Core::IEditor *editor)
@@ -233,6 +241,8 @@ void ClangModelManagerSupport::onCurrentEditorChanged(Core::IEditor *editor)
if (auto processor = ClangEditorDocumentProcessor::get(filePath.toString())) { if (auto processor = ClangEditorDocumentProcessor::get(filePath.toString())) {
processor->semanticRehighlight(); processor->semanticRehighlight();
processor->generateTaskHubIssues(); processor->generateTaskHubIssues();
if (const auto client = clientForFile(filePath))
client->updateParserConfig(filePath, processor->parserConfig());
} }
} }
@@ -342,16 +352,38 @@ void ClangModelManagerSupport::updateLanguageClient(
if (!newProjectInfo || *newProjectInfo != *projectInfo) if (!newProjectInfo || *newProjectInfo != *projectInfo)
return; 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. // Acquaint the client with all open C++ documents for this project.
bool hasDocuments = false; bool hasDocuments = false;
for (TextEditor::BaseTextEditor * const editor : allCppEditors()) { for (TextEditor::BaseTextEditor * const editor : allCppEditors()) {
if (!project->isKnownFile(editor->textDocument()->filePath())) const Utils::FilePath filePath = editor->textDocument()->filePath();
if (!project->isKnownFile(filePath))
continue; continue;
LanguageClientManager::openDocumentWithClient(editor->textDocument(), client); LanguageClientManager::openDocumentWithClient(editor->textDocument(), client);
ClangEditorDocumentProcessor::clearTextMarks(editor->textDocument()->filePath()); ClangEditorDocumentProcessor::clearTextMarks(filePath);
hasDocuments = true; hasDocuments = true;
} }
if (client->state() == Client::Initialized)
updateParserConfig();
else
connect(client, &Client::initialized, client, updateParserConfig);
connect(CppModelManager::instance(), &CppModelManager::projectPartsUpdated,
client, updateParserConfig);
if (hasDocuments) if (hasDocuments)
return; return;

View File

@@ -50,6 +50,13 @@ public:
bool usePrecompiledHeaders = false; bool usePrecompiledHeaders = false;
QByteArray editorDefines; QByteArray editorDefines;
QString preferredProjectPartId; QString preferredProjectPartId;
bool operator==(const Configuration &other)
{
return usePrecompiledHeaders == other.usePrecompiledHeaders
&& editorDefines == other.editorDefines
&& preferredProjectPartId == other.preferredProjectPartId;
}
}; };
struct UpdateParams { struct UpdateParams {