forked from qt-creator/qt-creator
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:
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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)
|
||||||
|
@@ -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 ¶ms) override;
|
QFuture<CppEditor::CursorInfo> cursorInfo(const CppEditor::CursorInfoParams ¶ms) 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();
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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 {
|
||||||
|
Reference in New Issue
Block a user