ClangCodeModel: Support setting additional preprocessor directives

... for a document.
This was only ever implemented for the built-in code model.

Fixes: QTCREATORBUG-20423
Change-Id: Ia99d0136e9995a5626058ad06173ea077be024d8
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2022-09-08 15:27:55 +02:00
parent fbd4775f89
commit f7efefb6d4
7 changed files with 54 additions and 35 deletions

View File

@@ -335,7 +335,7 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
= CppEditor::ClangdSettings(d->settings).clangdIncludePath(); = CppEditor::ClangdSettings(d->settings).clangdIncludePath();
CppEditor::CompilerOptionsBuilder optionsBuilder = clangOptionsBuilder( CppEditor::CompilerOptionsBuilder optionsBuilder = clangOptionsBuilder(
*CppEditor::CppModelManager::instance()->fallbackProjectPart(), *CppEditor::CppModelManager::instance()->fallbackProjectPart(),
warningsConfigForProject(nullptr), includeDir); warningsConfigForProject(nullptr), includeDir, {});
const CppEditor::UsePrecompiledHeaders usePch = CppEditor::getPchUsage(); const CppEditor::UsePrecompiledHeaders usePch = CppEditor::getPchUsage();
const QJsonArray projectPartOptions = fullProjectPartOptions( const QJsonArray projectPartOptions = fullProjectPartOptions(
optionsBuilder, globalClangOptions()); optionsBuilder, globalClangOptions());
@@ -714,23 +714,26 @@ void ClangdClient::handleUiHeaderChange(const QString &fileName)
void ClangdClient::updateParserConfig(const Utils::FilePath &filePath, void ClangdClient::updateParserConfig(const Utils::FilePath &filePath,
const CppEditor::BaseEditorDocumentParser::Configuration &config) const CppEditor::BaseEditorDocumentParser::Configuration &config)
{ {
if (config.preferredProjectPartId.isEmpty()) // TODO: Also handle usePrecompiledHeaders?
return; const auto projectPart = !config.preferredProjectPartId.isEmpty()
? CppEditor::CppModelManager::instance()->projectPartForId(
CppEditor::BaseEditorDocumentParser::Configuration &cachedConfig = d->parserConfigs[filePath]; config.preferredProjectPartId)
if (cachedConfig == config) : projectPartForFile(filePath.toString());
return;
cachedConfig = config;
// TODO: Also handle editorDefines (and usePrecompiledHeaders?)
const auto projectPart = CppEditor::CppModelManager::instance()
->projectPartForId(config.preferredProjectPartId);
if (!projectPart) if (!projectPart)
return; return;
CppEditor::BaseEditorDocumentParser::Configuration fullConfig = config;
fullConfig.preferredProjectPartId = projectPart->id();
CppEditor::BaseEditorDocumentParser::Configuration &cachedConfig = d->parserConfigs[filePath];
if (cachedConfig == fullConfig)
return;
cachedConfig = fullConfig;
QJsonObject cdbChanges; QJsonObject cdbChanges;
const Utils::FilePath includeDir = CppEditor::ClangdSettings(d->settings).clangdIncludePath(); const Utils::FilePath includeDir = CppEditor::ClangdSettings(d->settings).clangdIncludePath();
CppEditor::CompilerOptionsBuilder optionsBuilder = clangOptionsBuilder( CppEditor::CompilerOptionsBuilder optionsBuilder = clangOptionsBuilder(
*projectPart, warningsConfigForProject(project()), includeDir); *projectPart, warningsConfigForProject(project()), includeDir,
ProjectExplorer::Macro::toMacros(config.editorDefines));
const CppEditor::ProjectFile file(filePath.toString(), const CppEditor::ProjectFile file(filePath.toString(),
CppEditor::ProjectFile::classify(filePath.toString())); CppEditor::ProjectFile::classify(filePath.toString()));
const QJsonArray projectPartOptions = fullProjectPartOptions( const QJsonArray projectPartOptions = fullProjectPartOptions(
@@ -742,6 +745,7 @@ void ClangdClient::updateParserConfig(const Utils::FilePath &filePath,
DidChangeConfigurationParams configChangeParams; DidChangeConfigurationParams configChangeParams;
configChangeParams.setSettings(settings); configChangeParams.setSettings(settings);
sendMessage(DidChangeConfigurationNotification(configChangeParams)); sendMessage(DidChangeConfigurationNotification(configChangeParams));
emit configChanged();
} }
void ClangdClient::switchIssuePaneEntries(const Utils::FilePath &filePath) void ClangdClient::switchIssuePaneEntries(const Utils::FilePath &filePath)

View File

@@ -114,6 +114,7 @@ signals:
const Utils::FilePath &file); const Utils::FilePath &file);
void proposalReady(TextEditor::IAssistProposal *proposal); void proposalReady(TextEditor::IAssistProposal *proposal);
void textMarkCreated(const Utils::FilePath &file); void textMarkCreated(const Utils::FilePath &file);
void configChanged();
private: private:
void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams &params) override; void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams &params) override;

View File

@@ -3,12 +3,10 @@
#include "clangeditordocumentprocessor.h" #include "clangeditordocumentprocessor.h"
#include "clangdiagnostictooltipwidget.h"
#include "clangfixitoperation.h"
#include "clangmodelmanagersupport.h" #include "clangmodelmanagersupport.h"
#include "clangutils.h"
#include <cppeditor/builtincursorinfo.h> #include <cppeditor/builtincursorinfo.h>
#include <cppeditor/builtineditordocumentparser.h>
#include <cppeditor/clangdiagnosticconfigsmodel.h> #include <cppeditor/clangdiagnosticconfigsmodel.h>
#include <cppeditor/compileroptionsbuilder.h> #include <cppeditor/compileroptionsbuilder.h>
#include <cppeditor/cppcodemodelsettings.h> #include <cppeditor/cppcodemodelsettings.h>
@@ -41,6 +39,11 @@ ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(TextEditor::TextDocum
{ {
connect(parser().data(), &CppEditor::BaseEditorDocumentParser::projectPartInfoUpdated, connect(parser().data(), &CppEditor::BaseEditorDocumentParser::projectPartInfoUpdated,
this, &BaseEditorDocumentProcessor::projectPartInfoUpdated); this, &BaseEditorDocumentProcessor::projectPartInfoUpdated);
connect(static_cast<CppEditor::BuiltinEditorDocumentParser *>(parser().data()),
&CppEditor::BuiltinEditorDocumentParser::finished,
this, [this] {
emit parserConfigChanged(Utils::FilePath::fromString(filePath()), parserConfig());
});
setSemanticHighlightingChecker([this] { setSemanticHighlightingChecker([this] {
return !ClangModelManagerSupport::clientForFile(m_document.filePath()); return !ClangModelManagerSupport::clientForFile(m_document.filePath());
}); });

View File

@@ -171,7 +171,7 @@ GenerateCompilationDbResult generateCompilationDB(QList<ProjectInfo::ConstPtr> p
QTC_ASSERT(projectInfo, continue); QTC_ASSERT(projectInfo, continue);
QStringList args; QStringList args;
const CompilerOptionsBuilder optionsBuilder = clangOptionsBuilder( const CompilerOptionsBuilder optionsBuilder = clangOptionsBuilder(
*projectPart, warningsConfig, clangIncludeDir); *projectPart, warningsConfig, clangIncludeDir, {});
QJsonArray ppOptions; QJsonArray ppOptions;
if (purpose == CompilationDbPurpose::Project) { if (purpose == CompilationDbPurpose::Project) {
args = projectPartArguments(*projectPart); args = projectPartArguments(*projectPart);
@@ -328,7 +328,8 @@ QString textUntilPreviousStatement(TextEditor::TextDocumentManipulatorInterface
CompilerOptionsBuilder clangOptionsBuilder(const ProjectPart &projectPart, CompilerOptionsBuilder clangOptionsBuilder(const ProjectPart &projectPart,
const ClangDiagnosticConfig &warningsConfig, const ClangDiagnosticConfig &warningsConfig,
const Utils::FilePath &clangIncludeDir) const FilePath &clangIncludeDir,
const Macros &extraMacros)
{ {
const auto useBuildSystemWarnings = warningsConfig.useBuildSystemWarnings() const auto useBuildSystemWarnings = warningsConfig.useBuildSystemWarnings()
? UseBuildSystemWarnings::Yes ? UseBuildSystemWarnings::Yes
@@ -336,7 +337,9 @@ CompilerOptionsBuilder clangOptionsBuilder(const ProjectPart &projectPart,
CompilerOptionsBuilder optionsBuilder(projectPart, UseSystemHeader::No, CompilerOptionsBuilder optionsBuilder(projectPart, UseSystemHeader::No,
UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseTweakedHeaderPaths::Yes, UseLanguageDefines::No,
useBuildSystemWarnings, clangIncludeDir); useBuildSystemWarnings, clangIncludeDir);
optionsBuilder.provideAdditionalMacros({ProjectExplorer::Macro("Q_CREATOR_RUN", "1")}); Macros fullMacroList = extraMacros;
fullMacroList += Macro("Q_CREATOR_RUN", "1");
optionsBuilder.provideAdditionalMacros(fullMacroList);
optionsBuilder.build(ProjectFile::Unclassified, UsePrecompiledHeaders::No); optionsBuilder.build(ProjectFile::Unclassified, UsePrecompiledHeaders::No);
optionsBuilder.add("-fmessage-length=0", /*gccOnlyOption=*/true); optionsBuilder.add("-fmessage-length=0", /*gccOnlyOption=*/true);
optionsBuilder.add("-fdiagnostics-show-note-include-stack", /*gccOnlyOption=*/true); optionsBuilder.add("-fdiagnostics-show-note-include-stack", /*gccOnlyOption=*/true);

View File

@@ -35,7 +35,8 @@ const QStringList globalClangOptions();
CppEditor::CompilerOptionsBuilder clangOptionsBuilder( CppEditor::CompilerOptionsBuilder clangOptionsBuilder(
const CppEditor::ProjectPart &projectPart, const CppEditor::ProjectPart &projectPart,
const CppEditor::ClangDiagnosticConfig &warningsConfig, const CppEditor::ClangDiagnosticConfig &warningsConfig,
const Utils::FilePath &clangIncludeDir); const Utils::FilePath &clangIncludeDir,
const ProjectExplorer::Macros &extraMacros);
QJsonArray projectPartOptions(const CppEditor::CompilerOptionsBuilder &optionsBuilder); QJsonArray projectPartOptions(const CppEditor::CompilerOptionsBuilder &optionsBuilder);
QJsonArray fullProjectPartOptions(const CppEditor::CompilerOptionsBuilder &optionsBuilder, QJsonArray fullProjectPartOptions(const CppEditor::CompilerOptionsBuilder &optionsBuilder,
const QStringList &projectOptions); const QStringList &projectOptions);

View File

@@ -20,6 +20,7 @@
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <texteditor/codeassist/assistproposaliteminterface.h> #include <texteditor/codeassist/assistproposaliteminterface.h>
#include <texteditor/codeassist/textdocumentmanipulatorinterface.h> #include <texteditor/codeassist/textdocumentmanipulatorinterface.h>
#include <texteditor/textmark.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/environment.h> #include <utils/environment.h>
#include <utils/filepath.h> #include <utils/filepath.h>
@@ -2001,6 +2002,15 @@ ClangdTestExternalChanges::ClangdTestExternalChanges()
void ClangdTestExternalChanges::test() void ClangdTestExternalChanges::test()
{ {
ClangdClient * const oldClient = client();
QVERIFY(oldClient);
// Wait until things have settled.
while (true) {
if (!waitForSignalOrTimeout(oldClient, &ClangdClient::configChanged, timeOutInMs()))
break;
}
// Break a header file that is used, but not open in Creator. // Break a header file that is used, but not open in Creator.
// Neither we nor the server should notice, and no diagnostics should be shown for the // Neither we nor the server should notice, and no diagnostics should be shown for the
// source file that includes the now-broken header. // source file that includes the now-broken header.
@@ -2008,14 +2018,15 @@ void ClangdTestExternalChanges::test()
QVERIFY(header.open(QIODevice::WriteOnly)); QVERIFY(header.open(QIODevice::WriteOnly));
header.write("blubb"); header.write("blubb");
header.close(); header.close();
ClangdClient * const oldClient = client();
QVERIFY(oldClient);
waitForSignalOrTimeout(LanguageClientManager::instance(), waitForSignalOrTimeout(LanguageClientManager::instance(),
&LanguageClientManager::clientAdded, timeOutInMs()); &LanguageClientManager::clientAdded, timeOutInMs());
QCOMPARE(client(), oldClient); QCOMPARE(client(), oldClient);
QCOMPARE(client(), ClangModelManagerSupport::clientForProject(project())); QCOMPARE(client(), ClangModelManagerSupport::clientForProject(project()));
const TextDocument * const curDoc = document("main.cpp"); const TextDocument * const curDoc = document("main.cpp");
QVERIFY(curDoc); QVERIFY(curDoc);
if (!curDoc->marks().isEmpty())
for (const auto &m : curDoc->marks())
qDebug() << m->lineAnnotation();
QVERIFY(curDoc->marks().isEmpty()); QVERIFY(curDoc->marks().isEmpty());
// Now trigger an external change in an open, but not currently visible file and // Now trigger an external change in an open, but not currently visible file and

View File

@@ -507,8 +507,6 @@ void CppEditorWidget::finalizeInitialization()
// clang-format on // clang-format on
// Toolbar: '#' Button // Toolbar: '#' Button
// TODO: Make "Additional Preprocessor Directives" also useful with Clang Code Model.
if (!d->m_modelManager->isClangCodeModelActive()) {
d->m_preprocessorButton = new QToolButton(this); d->m_preprocessorButton = new QToolButton(this);
d->m_preprocessorButton->setText(QLatin1String("#")); d->m_preprocessorButton->setText(QLatin1String("#"));
Command *cmd = ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG); Command *cmd = ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG);
@@ -517,9 +515,7 @@ void CppEditorWidget::finalizeInitialization()
updatePreprocessorButtonTooltip(); updatePreprocessorButtonTooltip();
connect(d->m_preprocessorButton, &QAbstractButton::clicked, connect(d->m_preprocessorButton, &QAbstractButton::clicked,
this, &CppEditorWidget::showPreProcessorWidget); this, &CppEditorWidget::showPreProcessorWidget);
insertExtraToolBarWidget(TextEditorWidget::Left, d->m_preprocessorButton); insertExtraToolBarWidget(TextEditorWidget::Left, d->m_preprocessorButton);
}
connect(this, &TextEditor::TextEditorWidget::toolbarOutlineChanged, connect(this, &TextEditor::TextEditorWidget::toolbarOutlineChanged,
this, &CppEditorWidget::handleOutlineChanged); this, &CppEditorWidget::handleOutlineChanged);