diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2023-05-17 13:45:56 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2023-05-17 13:52:40 +0000 |
commit | aa5ddaf4122cc95b7d475fd1ab3d899ef3c0c062 (patch) | |
tree | c45d96481629462e25574ac60e8b583241ae3b16 | |
parent | 5abb1959c5883ddd74c0ddbba477a4e22881b2a8 (diff) | |
download | qt-creator-aa5ddaf4122cc95b7d475fd1ab3d899ef3c0c062.tar.gz |
ClangCodeModel: Let user decide how to do the header/source switch
While clangd's AST matching can find source files at any location, it also
has a number of annoying bugs that break the functionality for some
users. This patch brings back the previous "try built-in first" logic, but
also lets users choose their preferred backend.
Task-number: QTCREATORBUG-29175
Change-Id: I6b854ed05652e6468509e5748a83a8f9bf76fc20
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
-rw-r--r-- | src/plugins/clangcodemodel/clangmodelmanagersupport.cpp | 22 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppcodemodelsettings.cpp | 16 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppcodemodelsettings.h | 5 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppcodemodelsettingspage.cpp | 27 |
4 files changed, 66 insertions, 4 deletions
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 1dd66db3cd..8aea72ce0e 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -352,10 +352,24 @@ void ClangModelManagerSupport::findUsages(const CursorInEditor &cursor) const void ClangModelManagerSupport::switchHeaderSource(const FilePath &filePath, bool inNextSplit) { - if (ClangdClient * const client = clientForFile(filePath)) - client->switchHeaderSource(filePath, inNextSplit); - else - CppModelManager::switchHeaderSource(inNextSplit, CppModelManager::Backend::Builtin); + if (ClangdClient * const client = clientForFile(filePath)) { + switch (ClangdProjectSettings(client->project()).settings().headerSourceSwitchMode) { + case ClangdSettings::HeaderSourceSwitchMode::BuiltinOnly: + CppModelManager::switchHeaderSource(inNextSplit, CppModelManager::Backend::Builtin); + return; + case ClangdSettings::HeaderSourceSwitchMode::ClangdOnly: + client->switchHeaderSource(filePath, inNextSplit); + return; + case ClangdSettings::HeaderSourceSwitchMode::Both: + const FilePath otherFile = correspondingHeaderOrSource(filePath); + if (!otherFile.isEmpty()) + openEditor(otherFile, inNextSplit); + else + client->switchHeaderSource(filePath, inNextSplit); + return; + } + } + CppModelManager::switchHeaderSource(inNextSplit, CppModelManager::Backend::Builtin); } void ClangModelManagerSupport::checkUnused(const Link &link, SearchResult *search, diff --git a/src/plugins/cppeditor/cppcodemodelsettings.cpp b/src/plugins/cppeditor/cppcodemodelsettings.cpp index 5919a97b84..2f4fdffab2 100644 --- a/src/plugins/cppeditor/cppcodemodelsettings.cpp +++ b/src/plugins/cppeditor/cppcodemodelsettings.cpp @@ -64,6 +64,9 @@ static QString useClangdKey() { return QLatin1String("UseClangdV7"); } static QString clangdPathKey() { return QLatin1String("ClangdPath"); } static QString clangdIndexingKey() { return QLatin1String("ClangdIndexing"); } static QString clangdIndexingPriorityKey() { return QLatin1String("ClangdIndexingPriority"); } +static QString clangdHeaderSourceSwitchModeKey() { + return QLatin1String("ClangdHeaderSourceSwitchMode"); +} static QString clangdHeaderInsertionKey() { return QLatin1String("ClangdHeaderInsertion"); } static QString clangdThreadLimitKey() { return QLatin1String("ClangdThreadLimit"); } static QString clangdDocumentThresholdKey() { return QLatin1String("ClangdDocumentThreshold"); } @@ -229,6 +232,16 @@ QString ClangdSettings::priorityToDisplayString(const IndexingPriority &priority return {}; } +QString ClangdSettings::headerSourceSwitchModeToDisplayString(HeaderSourceSwitchMode mode) +{ + switch (mode) { + case HeaderSourceSwitchMode::BuiltinOnly: return Tr::tr("Use Built-in Only"); + case HeaderSourceSwitchMode::ClangdOnly: return Tr::tr("Use Clangd Only"); + case HeaderSourceSwitchMode::Both: return Tr::tr("Try Both"); + } + return {}; +} + ClangdSettings &ClangdSettings::instance() { static ClangdSettings settings; @@ -528,6 +541,7 @@ QVariantMap ClangdSettings::Data::toMap() const : QString()); map.insert(clangdIndexingKey(), indexingPriority != IndexingPriority::Off); map.insert(clangdIndexingPriorityKey(), int(indexingPriority)); + map.insert(clangdHeaderSourceSwitchModeKey(), int(headerSourceSwitchMode)); map.insert(clangdHeaderInsertionKey(), autoIncludeHeaders); map.insert(clangdThreadLimitKey(), workerThreadLimit); map.insert(clangdDocumentThresholdKey(), documentUpdateThreshold); @@ -549,6 +563,8 @@ void ClangdSettings::Data::fromMap(const QVariantMap &map) const auto it = map.find(clangdIndexingKey()); if (it != map.end() && !it->toBool()) indexingPriority = IndexingPriority::Off; + headerSourceSwitchMode = HeaderSourceSwitchMode(map.value(clangdHeaderSourceSwitchModeKey(), + int(headerSourceSwitchMode)).toInt()); autoIncludeHeaders = map.value(clangdHeaderInsertionKey(), false).toBool(); workerThreadLimit = map.value(clangdThreadLimitKey(), 0).toInt(); documentUpdateThreshold = map.value(clangdDocumentThresholdKey(), 500).toInt(); diff --git a/src/plugins/cppeditor/cppcodemodelsettings.h b/src/plugins/cppeditor/cppcodemodelsettings.h index 7bfdc2e85e..c22fb88faa 100644 --- a/src/plugins/cppeditor/cppcodemodelsettings.h +++ b/src/plugins/cppeditor/cppcodemodelsettings.h @@ -84,9 +84,11 @@ class CPPEDITOR_EXPORT ClangdSettings : public QObject Q_OBJECT public: enum class IndexingPriority { Off, Background, Normal, Low, }; + enum class HeaderSourceSwitchMode { BuiltinOnly, ClangdOnly, Both }; static QString priorityToString(const IndexingPriority &priority); static QString priorityToDisplayString(const IndexingPriority &priority); + static QString headerSourceSwitchModeToDisplayString(HeaderSourceSwitchMode mode); class CPPEDITOR_EXPORT Data { @@ -103,6 +105,7 @@ public: && s1.diagnosticConfigId == s2.diagnosticConfigId && s1.workerThreadLimit == s2.workerThreadLimit && s1.indexingPriority == s2.indexingPriority + && s1.headerSourceSwitchMode == s2.headerSourceSwitchMode && s1.autoIncludeHeaders == s2.autoIncludeHeaders && s1.documentUpdateThreshold == s2.documentUpdateThreshold && s1.sizeThresholdEnabled == s2.sizeThresholdEnabled @@ -123,6 +126,7 @@ public: qint64 sizeThresholdInKb = 1024; bool useClangd = true; IndexingPriority indexingPriority = IndexingPriority::Low; + HeaderSourceSwitchMode headerSourceSwitchMode = HeaderSourceSwitchMode::Both; bool autoIncludeHeaders = false; bool sizeThresholdEnabled = false; bool haveCheckedHardwareReqirements = false; @@ -143,6 +147,7 @@ public: static void setCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs); Utils::FilePath clangdFilePath() const; IndexingPriority indexingPriority() const { return m_data.indexingPriority; } + HeaderSourceSwitchMode headerSourceSwitchMode() const { return m_data.headerSourceSwitchMode; } bool autoIncludeHeaders() const { return m_data.autoIncludeHeaders; } int workerThreadLimit() const { return m_data.workerThreadLimit; } int documentUpdateThreshold() const { return m_data.documentUpdateThreshold; } diff --git a/src/plugins/cppeditor/cppcodemodelsettingspage.cpp b/src/plugins/cppeditor/cppcodemodelsettingspage.cpp index 00224f5d90..88f5bf0de8 100644 --- a/src/plugins/cppeditor/cppcodemodelsettingspage.cpp +++ b/src/plugins/cppeditor/cppcodemodelsettingspage.cpp @@ -192,6 +192,7 @@ class ClangdSettingsWidget::Private public: QCheckBox useClangdCheckBox; QComboBox indexingComboBox; + QComboBox headerSourceSwitchComboBox; QCheckBox autoIncludeHeadersCheckBox; QCheckBox sizeThresholdCheckBox; QSpinBox threadLimitSpinBox; @@ -220,6 +221,12 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD "cores unused.</p>" "<p>Normal Priority: Reduced priority compared to interactive work.</p>" "Low Priority: Same priority as other clangd work."); + const QString headerSourceSwitchToolTip = Tr::tr( + "<p>Which C/C++ backend to use when switching between header and source file." + "<p>The clangd implementation has more capabilities, but also has some bugs not present " + "in the built-in variant." + "<p>When \"Try Both\" is selected, clangd will be employed only if the built-in variant " + "does not find anything."); const QString workerThreadsToolTip = Tr::tr( "Number of worker threads used by clangd. Background indexing also uses this many " "worker threads."); @@ -249,6 +256,15 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD d->indexingComboBox.setCurrentIndex(d->indexingComboBox.count() - 1); } d->indexingComboBox.setToolTip(indexingToolTip); + using SwitchMode = ClangdSettings::HeaderSourceSwitchMode; + for (SwitchMode mode : {SwitchMode::BuiltinOnly, SwitchMode::ClangdOnly, SwitchMode::Both}) { + d->headerSourceSwitchComboBox.addItem( + ClangdSettings::headerSourceSwitchModeToDisplayString(mode), int(mode)); + if (mode == settings.headerSourceSwitchMode()) + d->headerSourceSwitchComboBox.setCurrentIndex( + d->headerSourceSwitchComboBox.count() - 1); + } + d->headerSourceSwitchComboBox.setToolTip(headerSourceSwitchToolTip); d->autoIncludeHeadersCheckBox.setText(Tr::tr("Insert header files on completion")); d->autoIncludeHeadersCheckBox.setChecked(settings.autoIncludeHeaders()); d->autoIncludeHeadersCheckBox.setToolTip(autoIncludeToolTip); @@ -294,6 +310,13 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD indexingPriorityLabel->setToolTip(indexingToolTip); formLayout->addRow(indexingPriorityLabel, indexingPriorityLayout); + const auto headerSourceSwitchLayout = new QHBoxLayout; + headerSourceSwitchLayout->addWidget(&d->headerSourceSwitchComboBox); + headerSourceSwitchLayout->addStretch(1); + const auto headerSourceSwitchLabel = new QLabel(Tr::tr("Header/source switch mode:")); + headerSourceSwitchLabel->setToolTip(headerSourceSwitchToolTip); + formLayout->addRow(headerSourceSwitchLabel, headerSourceSwitchLayout); + const auto threadLimitLayout = new QHBoxLayout; threadLimitLayout->addWidget(&d->threadLimitSpinBox); threadLimitLayout->addStretch(1); @@ -449,6 +472,8 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD this, &ClangdSettingsWidget::settingsDataChanged); connect(&d->indexingComboBox, &QComboBox::currentIndexChanged, this, &ClangdSettingsWidget::settingsDataChanged); + connect(&d->headerSourceSwitchComboBox, &QComboBox::currentIndexChanged, + this, &ClangdSettingsWidget::settingsDataChanged); connect(&d->autoIncludeHeadersCheckBox, &QCheckBox::toggled, this, &ClangdSettingsWidget::settingsDataChanged); connect(&d->threadLimitSpinBox, &QSpinBox::valueChanged, @@ -479,6 +504,8 @@ ClangdSettings::Data ClangdSettingsWidget::settingsData() const data.executableFilePath = d->clangdChooser.filePath(); data.indexingPriority = ClangdSettings::IndexingPriority( d->indexingComboBox.currentData().toInt()); + data.headerSourceSwitchMode = ClangdSettings::HeaderSourceSwitchMode( + d->headerSourceSwitchComboBox.currentData().toInt()); data.autoIncludeHeaders = d->autoIncludeHeadersCheckBox.isChecked(); data.workerThreadLimit = d->threadLimitSpinBox.value(); data.documentUpdateThreshold = d->documentUpdateThreshold.value(); |