diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2024-02-08 15:00:55 +0100 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2024-02-12 11:38:57 +0000 |
commit | 1af555ad09be169bebc7525e4bb7e10ad4de271d (patch) | |
tree | e43a799ae9c08947c65d4983551dc853d0174d4c | |
parent | 7a055a2f0ad7bd99eb5629f8ce6dfa5ae7a27080 (diff) |
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>
-rw-r--r-- | src/plugins/clangcodemodel/clangmodelmanagersupport.cpp | 21 | ||||
-rw-r--r-- | src/plugins/coreplugin/coreplugin.cpp | 4 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppcodemodelsettings.cpp | 32 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppcodemodelsettings.h | 34 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppcodemodelsettingspage.cpp | 53 |
5 files changed, 120 insertions, 24 deletions
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 53d0e6f378..3c3fc18c91 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -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 (const Target * const target = project->activeTarget()) { - if (const BuildConfiguration * const bc = target->activeBuildConfiguration()) - return bc->buildDirectory() / dirName; + if (!project) + return ClangdSettings::instance().sessionIndexPath(*globalMacroExpander()); + if (const Target *const target = project->activeTarget()) { + 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; diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp index 49ca2fec8a..2ff53a68d0 100644 --- a/src/plugins/coreplugin/coreplugin.cpp +++ b/src/plugins/coreplugin/coreplugin.cpp @@ -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)."), diff --git a/src/plugins/cppeditor/cppcodemodelsettings.cpp b/src/plugins/cppeditor/cppcodemodelsettings.cpp index db6231cfe9..1c294af415 100644 --- a/src/plugins/cppeditor/cppcodemodelsettings.cpp +++ b/src/plugins/cppeditor/cppcodemodelsettings.cpp @@ -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( diff --git a/src/plugins/cppeditor/cppcodemodelsettings.h b/src/plugins/cppeditor/cppcodemodelsettings.h index b4f8ac7269..df0b81d9ca 100644 --- a/src/plugins/cppeditor/cppcodemodelsettings.h +++ b/src/plugins/cppeditor/cppcodemodelsettings.h @@ -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,34 +124,37 @@ 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; - static constexpr auto DefaultWorkerThreadLimit = 0; - static constexpr auto DefaultDocumentUpdateThreshold = 500; - static constexpr auto DefaultSizeThresholdInKb = 1024ll; - static constexpr auto DefaultUseClangd = true; - static constexpr auto DefaultIndexingPriority = ClangdSettings::IndexingPriority::Low; - static constexpr auto DefaultHeaderSourceSwitchMode = HeaderSourceSwitchMode::Both; - 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; + 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; + static constexpr auto DefaultUseClangd = true; + static constexpr auto DefaultIndexingPriority = ClangdSettings::IndexingPriority::Low; + static constexpr auto DefaultHeaderSourceSwitchMode = HeaderSourceSwitchMode::Both; + static constexpr auto DefaultCompletionRankingModel = CompletionRankingModel::Default; + static constexpr auto DefaultAutoIncludeHeaders = false; + static constexpr auto DefaultSizeThresholdEnabled = false; }; 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; } diff --git a/src/plugins/cppeditor/cppcodemodelsettingspage.cpp b/src/plugins/cppeditor/cppcodemodelsettingspage.cpp index bc47a78c9d..b4a19ccaae 100644 --- a/src/plugins/cppeditor/cppcodemodelsettingspage.cpp +++ b/src/plugins/cppeditor/cppcodemodelsettingspage.cpp @@ -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: |