forked from qt-creator/qt-creator
ClangCodeModel: Let users configure the clangd index location
Fixes: QTCREATORBUG-27346 Change-Id: I9bc59f759682e70b761c0f22a011868008fc0360 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: hjk <hjk@qt.io> Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -45,6 +45,7 @@
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/async.h>
|
||||
#include <utils/infobar.h>
|
||||
#include <utils/macroexpander.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QApplication>
|
||||
@@ -472,17 +473,15 @@ void ClangModelManagerSupport::connectToWidgetsMarkContextMenuRequested(QWidget
|
||||
}
|
||||
}
|
||||
|
||||
static FilePath getJsonDbDir(const Project *project)
|
||||
static FilePath getJsonDbDir(Project *project)
|
||||
{
|
||||
static const QString dirName(".qtc_clangd");
|
||||
if (!project) {
|
||||
const QString sessionDirName = FileUtils::fileSystemFriendlyName(
|
||||
SessionManager::activeSession());
|
||||
return ICore::userResourcePath() / dirName / sessionDirName; // TODO: Make configurable?
|
||||
}
|
||||
if (!project)
|
||||
return ClangdSettings::instance().sessionIndexPath(*globalMacroExpander());
|
||||
if (const Target *const target = project->activeTarget()) {
|
||||
if (const BuildConfiguration * const bc = target->activeBuildConfiguration())
|
||||
return bc->buildDirectory() / dirName;
|
||||
if (const BuildConfiguration *const bc = target->activeBuildConfiguration()) {
|
||||
return ClangdSettings(ClangdProjectSettings(project).settings())
|
||||
.projectIndexPath(*bc->macroExpander());
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -696,7 +695,7 @@ ClangdClient *ClangModelManagerSupport::clientWithProject(const Project *project
|
||||
void ClangModelManagerSupport::updateStaleIndexEntries()
|
||||
{
|
||||
QHash<FilePath, QDateTime> lastModifiedCache;
|
||||
for (const Project * const project : ProjectManager::projects()) {
|
||||
for (Project * const project : ProjectManager::projects()) {
|
||||
const FilePath jsonDbDir = getJsonDbDir(project);
|
||||
if (jsonDbDir.isEmpty())
|
||||
continue;
|
||||
|
@@ -226,6 +226,10 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
|
||||
Tr::tr("The directory where %1 finds its pre-installed resources.")
|
||||
.arg(QGuiApplication::applicationDisplayName()),
|
||||
[] { return ICore::resourcePath().toString(); });
|
||||
expander->registerVariable("IDE:UserResourcePath",
|
||||
Tr::tr("The directory where %1 puts custom user data.")
|
||||
.arg(QGuiApplication::applicationDisplayName()),
|
||||
[] { return ICore::userResourcePath().toString(); });
|
||||
expander->registerPrefix("CurrentDate:", Tr::tr("The current date (QDate formatstring)."),
|
||||
[](const QString &fmt) { return QDate::currentDate().toString(fmt); });
|
||||
expander->registerPrefix("CurrentTime:", Tr::tr("The current time (QTime formatstring)."),
|
||||
|
@@ -15,10 +15,12 @@
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/macroexpander.h>
|
||||
#include <utils/process.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QHash>
|
||||
#include <QPair>
|
||||
#include <QSettings>
|
||||
@@ -45,6 +47,8 @@ static Key clangdSettingsKey() { return "ClangdSettings"; }
|
||||
static Key useClangdKey() { return "UseClangdV7"; }
|
||||
static Key clangdPathKey() { return "ClangdPath"; }
|
||||
static Key clangdIndexingKey() { return "ClangdIndexing"; }
|
||||
static Key clangdProjectIndexPathKey() { return "ClangdProjectIndexPath"; }
|
||||
static Key clangdSessionIndexPathKey() { return "ClangdSessionIndexPath"; }
|
||||
static Key clangdIndexingPriorityKey() { return "ClangdIndexingPriority"; }
|
||||
static Key clangdHeaderSourceSwitchModeKey() { return "ClangdHeaderSourceSwitchMode"; }
|
||||
static Key clangdCompletionRankingModelKey() { return "ClangdCompletionRankingModel"; }
|
||||
@@ -248,6 +252,16 @@ QString ClangdSettings::rankingModelToDisplayString(CompletionRankingModel model
|
||||
QTC_ASSERT(false, return {});
|
||||
}
|
||||
|
||||
QString ClangdSettings::defaultProjectIndexPathTemplate()
|
||||
{
|
||||
return QDir::toNativeSeparators("%{BuildConfig:BuildDirectory:FilePath}/.qtc_clangd");
|
||||
}
|
||||
|
||||
QString ClangdSettings::defaultSessionIndexPathTemplate()
|
||||
{
|
||||
return QDir::toNativeSeparators("%{IDE:UserResourcePath}/.qtc_clangd/%{Session:FileBaseName}");
|
||||
}
|
||||
|
||||
ClangdSettings &ClangdSettings::instance()
|
||||
{
|
||||
static ClangdSettings settings;
|
||||
@@ -318,6 +332,16 @@ FilePath ClangdSettings::clangdFilePath() const
|
||||
return fallbackClangdFilePath();
|
||||
}
|
||||
|
||||
FilePath ClangdSettings::projectIndexPath(const Utils::MacroExpander &expander) const
|
||||
{
|
||||
return FilePath::fromUserInput(expander.expand(m_data.projectIndexPathTemplate));
|
||||
}
|
||||
|
||||
FilePath ClangdSettings::sessionIndexPath(const Utils::MacroExpander &expander) const
|
||||
{
|
||||
return FilePath::fromUserInput(expander.expand(m_data.sessionIndexPathTemplate));
|
||||
}
|
||||
|
||||
bool ClangdSettings::sizeIsOkay(const Utils::FilePath &fp) const
|
||||
{
|
||||
return !sizeThresholdEnabled() || sizeThresholdInKb() * 1024 >= fp.fileSize();
|
||||
@@ -559,6 +583,10 @@ Store ClangdSettings::Data::toMap() const
|
||||
map.insertValueWithDefault(clangdIndexingPriorityKey(),
|
||||
int(indexingPriority),
|
||||
int(DefaultIndexingPriority));
|
||||
map.insertValueWithDefault(clangdProjectIndexPathKey(), projectIndexPathTemplate,
|
||||
defaultProjectIndexPathTemplate());
|
||||
map.insertValueWithDefault(clangdSessionIndexPathKey(), sessionIndexPathTemplate,
|
||||
defaultSessionIndexPathTemplate());
|
||||
|
||||
map.insertValueWithDefault(clangdHeaderSourceSwitchModeKey(),
|
||||
int(headerSourceSwitchMode),
|
||||
@@ -610,6 +638,10 @@ void ClangdSettings::Data::fromMap(const Store &map)
|
||||
const auto it = map.find(clangdIndexingKey());
|
||||
if (it != map.end() && !it->toBool())
|
||||
indexingPriority = IndexingPriority::Off;
|
||||
projectIndexPathTemplate
|
||||
= map.value(clangdProjectIndexPathKey(), defaultProjectIndexPathTemplate()).toString();
|
||||
sessionIndexPathTemplate
|
||||
= map.value(clangdSessionIndexPathKey(), defaultSessionIndexPathTemplate()).toString();
|
||||
headerSourceSwitchMode = HeaderSourceSwitchMode(
|
||||
map.value(clangdHeaderSourceSwitchModeKey(), int(DefaultHeaderSourceSwitchMode)).toInt());
|
||||
completionRankingModel = CompletionRankingModel(
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include <QVersionNumber>
|
||||
|
||||
namespace ProjectExplorer { class Project; }
|
||||
namespace Utils { class MacroExpander; }
|
||||
|
||||
namespace CppEditor {
|
||||
|
||||
@@ -92,6 +93,8 @@ public:
|
||||
static QString headerSourceSwitchModeToDisplayString(HeaderSourceSwitchMode mode);
|
||||
static QString rankingModelToCmdLineString(CompletionRankingModel model);
|
||||
static QString rankingModelToDisplayString(CompletionRankingModel model);
|
||||
static QString defaultProjectIndexPathTemplate();
|
||||
static QString defaultSessionIndexPathTemplate();
|
||||
|
||||
class CPPEDITOR_EXPORT Data
|
||||
{
|
||||
@@ -103,6 +106,8 @@ public:
|
||||
{
|
||||
return s1.useClangd == s2.useClangd
|
||||
&& s1.executableFilePath == s2.executableFilePath
|
||||
&& s1.projectIndexPathTemplate == s2.projectIndexPathTemplate
|
||||
&& s1.sessionIndexPathTemplate == s2.sessionIndexPathTemplate
|
||||
&& s1.sessionsWithOneClangd == s2.sessionsWithOneClangd
|
||||
&& s1.customDiagnosticConfigs == s2.customDiagnosticConfigs
|
||||
&& s1.diagnosticConfigId == s2.diagnosticConfigId
|
||||
@@ -119,13 +124,28 @@ public:
|
||||
}
|
||||
friend bool operator!=(const Data &s1, const Data &s2) { return !(s1 == s2); }
|
||||
|
||||
static int defaultCompletionResults();
|
||||
|
||||
Utils::FilePath executableFilePath;
|
||||
QStringList sessionsWithOneClangd;
|
||||
ClangDiagnosticConfigs customDiagnosticConfigs;
|
||||
Utils::Id diagnosticConfigId;
|
||||
|
||||
int workerThreadLimit = DefaultWorkerThreadLimit;
|
||||
int documentUpdateThreshold = DefaultDocumentUpdateThreshold;
|
||||
qint64 sizeThresholdInKb = DefaultSizeThresholdInKb;
|
||||
bool useClangd = DefaultUseClangd;
|
||||
IndexingPriority indexingPriority = DefaultIndexingPriority;
|
||||
QString projectIndexPathTemplate = defaultProjectIndexPathTemplate();
|
||||
QString sessionIndexPathTemplate = defaultSessionIndexPathTemplate();
|
||||
HeaderSourceSwitchMode headerSourceSwitchMode = DefaultHeaderSourceSwitchMode;
|
||||
CompletionRankingModel completionRankingModel = DefaultCompletionRankingModel;
|
||||
bool autoIncludeHeaders = DefaultAutoIncludeHeaders;
|
||||
bool sizeThresholdEnabled = DefaultSizeThresholdEnabled;
|
||||
bool haveCheckedHardwareReqirements = false;
|
||||
int completionResults = defaultCompletionResults();
|
||||
|
||||
private:
|
||||
static int defaultCompletionResults();
|
||||
|
||||
static constexpr auto DefaultWorkerThreadLimit = 0;
|
||||
static constexpr auto DefaultDocumentUpdateThreshold = 500;
|
||||
static constexpr auto DefaultSizeThresholdInKb = 1024ll;
|
||||
@@ -135,18 +155,6 @@ public:
|
||||
static constexpr auto DefaultCompletionRankingModel = CompletionRankingModel::Default;
|
||||
static constexpr auto DefaultAutoIncludeHeaders = false;
|
||||
static constexpr auto DefaultSizeThresholdEnabled = false;
|
||||
|
||||
int workerThreadLimit = DefaultWorkerThreadLimit;
|
||||
int documentUpdateThreshold = DefaultDocumentUpdateThreshold;
|
||||
qint64 sizeThresholdInKb = DefaultSizeThresholdInKb;
|
||||
bool useClangd = DefaultUseClangd;
|
||||
IndexingPriority indexingPriority = DefaultIndexingPriority;
|
||||
HeaderSourceSwitchMode headerSourceSwitchMode = DefaultHeaderSourceSwitchMode;
|
||||
CompletionRankingModel completionRankingModel = DefaultCompletionRankingModel;
|
||||
bool autoIncludeHeaders = DefaultAutoIncludeHeaders;
|
||||
bool sizeThresholdEnabled = DefaultSizeThresholdEnabled;
|
||||
bool haveCheckedHardwareReqirements = false;
|
||||
int completionResults = defaultCompletionResults();
|
||||
};
|
||||
|
||||
ClangdSettings(const Data &data) : m_data(data) {}
|
||||
@@ -163,6 +171,8 @@ public:
|
||||
static void setCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs);
|
||||
Utils::FilePath clangdFilePath() const;
|
||||
IndexingPriority indexingPriority() const { return m_data.indexingPriority; }
|
||||
Utils::FilePath projectIndexPath(const Utils::MacroExpander &expander) const;
|
||||
Utils::FilePath sessionIndexPath(const Utils::MacroExpander &expander) const;
|
||||
HeaderSourceSwitchMode headerSourceSwitchMode() const { return m_data.headerSourceSwitchMode; }
|
||||
CompletionRankingModel completionRankingModel() const { return m_data.completionRankingModel; }
|
||||
bool autoIncludeHeaders() const { return m_data.autoIncludeHeaders; }
|
||||
|
@@ -18,11 +18,13 @@
|
||||
#include <projectexplorer/projectsettingswidget.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/fancylineedit.h>
|
||||
#include <utils/infolabel.h>
|
||||
#include <utils/itemviews.h>
|
||||
#include <utils/layoutbuilder.h>
|
||||
#include <utils/pathchooser.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/variablechooser.h>
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
@@ -36,6 +38,7 @@
|
||||
#include <QStringListModel>
|
||||
#include <QTextBlock>
|
||||
#include <QTextStream>
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
#include <QVersionNumber>
|
||||
|
||||
@@ -220,6 +223,8 @@ signals:
|
||||
private:
|
||||
QCheckBox m_useClangdCheckBox;
|
||||
QComboBox m_indexingComboBox;
|
||||
Utils::FancyLineEdit m_projectIndexPathTemplateLineEdit;
|
||||
Utils::FancyLineEdit m_sessionIndexPathTemplateLineEdit;
|
||||
QComboBox m_headerSourceSwitchComboBox;
|
||||
QComboBox m_completionRankingModelComboBox;
|
||||
QCheckBox m_autoIncludeHeadersCheckBox;
|
||||
@@ -249,6 +254,12 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
|
||||
"cores unused.</p>"
|
||||
"<p>Normal Priority: Reduced priority compared to interactive work.</p>"
|
||||
"<p>Low Priority: Same priority as other clangd work.</p>");
|
||||
const QString projectIndexPathToolTip = Tr::tr(
|
||||
"The location of the per-project clangd index.<p>"
|
||||
"This is also where the compile_commands.json file will go.");
|
||||
const QString sessionIndexPathToolTip = Tr::tr(
|
||||
"The location of the per-session clangd index.<p>"
|
||||
"This is also where the compile_commands.json file will go.");
|
||||
const QString headerSourceSwitchToolTip = Tr::tr(
|
||||
"<p>The C/C++ backend to use for switching between header and source files.</p>"
|
||||
"<p>While the clangd implementation has more capabilities than the built-in "
|
||||
@@ -296,6 +307,8 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
|
||||
m_indexingComboBox.setCurrentIndex(m_indexingComboBox.count() - 1);
|
||||
}
|
||||
m_indexingComboBox.setToolTip(indexingToolTip);
|
||||
m_projectIndexPathTemplateLineEdit.setText(settings.data().projectIndexPathTemplate);
|
||||
m_sessionIndexPathTemplateLineEdit.setText(settings.data().sessionIndexPathTemplate);
|
||||
using SwitchMode = ClangdSettings::HeaderSourceSwitchMode;
|
||||
for (SwitchMode mode : {SwitchMode::BuiltinOnly, SwitchMode::ClangdOnly, SwitchMode::Both}) {
|
||||
m_headerSourceSwitchComboBox.addItem(
|
||||
@@ -360,6 +373,33 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
|
||||
indexingPriorityLabel->setToolTip(indexingToolTip);
|
||||
formLayout->addRow(indexingPriorityLabel, indexingPriorityLayout);
|
||||
|
||||
for (const auto &[text, edit, toolTip, defaultValue] :
|
||||
{std::make_tuple(Tr::tr("Per-project index location:"),
|
||||
&m_projectIndexPathTemplateLineEdit,
|
||||
projectIndexPathToolTip,
|
||||
ClangdSettings::defaultProjectIndexPathTemplate()),
|
||||
std::make_tuple(Tr::tr("Per-session index location:"),
|
||||
&m_sessionIndexPathTemplateLineEdit,
|
||||
sessionIndexPathToolTip,
|
||||
ClangdSettings::defaultSessionIndexPathTemplate())}) {
|
||||
if (isForProject && edit == &m_sessionIndexPathTemplateLineEdit)
|
||||
continue;
|
||||
|
||||
const auto chooser = new Utils::VariableChooser(edit);
|
||||
chooser->addSupportedWidget(edit);
|
||||
chooser->addMacroExpanderProvider([] { return Utils::globalMacroExpander(); });
|
||||
|
||||
const auto resetButton = new QPushButton(Tr::tr("Reset"));
|
||||
connect(resetButton, &QPushButton::clicked, [e = edit, v = defaultValue] { e->setText(v); });
|
||||
const auto layout = new QHBoxLayout;
|
||||
const auto label = new QLabel(text);
|
||||
label->setToolTip(toolTip);
|
||||
edit->setToolTip(toolTip);
|
||||
layout->addWidget(edit);
|
||||
layout->addWidget(resetButton);
|
||||
formLayout->addRow(label, layout);
|
||||
}
|
||||
|
||||
const auto headerSourceSwitchLayout = new QHBoxLayout;
|
||||
headerSourceSwitchLayout->addWidget(&m_headerSourceSwitchComboBox);
|
||||
headerSourceSwitchLayout->addStretch(1);
|
||||
@@ -530,6 +570,10 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
|
||||
this, &ClangdSettingsWidget::settingsDataChanged);
|
||||
connect(&m_indexingComboBox, &QComboBox::currentIndexChanged,
|
||||
this, &ClangdSettingsWidget::settingsDataChanged);
|
||||
connect(&m_projectIndexPathTemplateLineEdit, &QLineEdit::textChanged,
|
||||
this, &ClangdSettingsWidget::settingsDataChanged);
|
||||
connect(&m_sessionIndexPathTemplateLineEdit, &QLineEdit::textChanged,
|
||||
this, &ClangdSettingsWidget::settingsDataChanged);
|
||||
connect(&m_headerSourceSwitchComboBox, &QComboBox::currentIndexChanged,
|
||||
this, &ClangdSettingsWidget::settingsDataChanged);
|
||||
connect(&m_completionRankingModelComboBox, &QComboBox::currentIndexChanged,
|
||||
@@ -559,6 +603,8 @@ ClangdSettings::Data ClangdSettingsWidget::settingsData() const
|
||||
data.executableFilePath = m_clangdChooser.filePath();
|
||||
data.indexingPriority = ClangdSettings::IndexingPriority(
|
||||
m_indexingComboBox.currentData().toInt());
|
||||
data.projectIndexPathTemplate = m_projectIndexPathTemplateLineEdit.text();
|
||||
data.sessionIndexPathTemplate = m_sessionIndexPathTemplateLineEdit.text();
|
||||
data.headerSourceSwitchMode = ClangdSettings::HeaderSourceSwitchMode(
|
||||
m_headerSourceSwitchComboBox.currentData().toInt());
|
||||
data.completionRankingModel = ClangdSettings::CompletionRankingModel(
|
||||
@@ -641,9 +687,14 @@ public:
|
||||
m_settings.setSettings(m_widget.settingsData());
|
||||
});
|
||||
|
||||
connect(&m_widget, &ClangdSettingsWidget::settingsDataChanged, this, [this] {
|
||||
const auto timer = new QTimer(this);
|
||||
timer->setSingleShot(true);
|
||||
timer->setInterval(5000);
|
||||
connect(timer, &QTimer::timeout, this, [this] {
|
||||
m_settings.setSettings(m_widget.settingsData());
|
||||
});
|
||||
connect(&m_widget, &ClangdSettingsWidget::settingsDataChanged,
|
||||
timer, qOverload<>(&QTimer::start));
|
||||
}
|
||||
|
||||
private:
|
||||
|
Reference in New Issue
Block a user