diff options
author | Orgad Shaneh <orgad.shaneh@audiocodes.com> | 2021-07-05 12:17:43 +0300 |
---|---|---|
committer | Orgad Shaneh <orgad.shaneh@audiocodes.com> | 2021-07-05 12:17:45 +0300 |
commit | 84839ee397c659c07dddb9459bc50e72cd083ab4 (patch) | |
tree | 81e3ae4ac0f414b049e0f0cb50c4fb2fced0ee0b /src/plugins/cpptools | |
parent | 32f46e55ed5297157d1abf499d70f6c0f08d34d7 (diff) | |
parent | 21115ae5118dafcf3ac9b7558761cd3925842236 (diff) |
Merge remote-tracking branch 'origin/5.0'
Change-Id: Ia018600fb257c9523fc9d15faa5bd8300840e3de
Diffstat (limited to 'src/plugins/cpptools')
18 files changed, 522 insertions, 92 deletions
diff --git a/src/plugins/cpptools/clangdiagnosticconfig.cpp b/src/plugins/cpptools/clangdiagnosticconfig.cpp index c31fc4f8ce..95ba5a7328 100644 --- a/src/plugins/cpptools/clangdiagnosticconfig.cpp +++ b/src/plugins/cpptools/clangdiagnosticconfig.cpp @@ -130,11 +130,26 @@ QString ClangDiagnosticConfig::clangTidyChecksAsJson() const { QString jsonString = "{Checks: '" + clangTidyChecks() + ",-clang-diagnostic-*', CheckOptions: ["; + + // The check is either listed verbatim or covered by the "<prefix>-*" pattern. + const auto checkIsEnabled = [this](const QString &check) { + for (QString subString = check; !subString.isEmpty(); + subString.chop(subString.length() - subString.lastIndexOf('-'))) { + const int idx = m_clangTidyChecks.indexOf(subString); + if (idx == -1) + continue; + if (idx > 0 && m_clangTidyChecks.at(idx - 1) == '-') + continue; + if (subString == check || QStringView(m_clangTidyChecks) + .mid(idx + subString.length()).startsWith(QLatin1String("-*"))) { + return true; + } + } + return false; + }; + for (auto it = m_tidyChecksOptions.cbegin(); it != m_tidyChecksOptions.cend(); ++it) { - const int idx = m_clangTidyChecks.indexOf(it.key()); - if (idx == -1) - continue; - if (idx > 0 && m_clangTidyChecks.at(idx - 1) == '-') + if (!checkIsEnabled(it.key())) continue; QString optionString; for (auto optIt = it.value().begin(); optIt != it.value().end(); ++optIt) { diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index 030d2b16cd..09291830b3 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -165,6 +165,11 @@ void CompilerOptionsBuilder::add(const QString &arg, bool gccOnlyOption) add(QStringList{arg}, gccOnlyOption); } +void CompilerOptionsBuilder::prepend(const QString &arg) +{ + m_options.prepend(arg); +} + void CompilerOptionsBuilder::add(const QStringList &args, bool gccOnlyOptions) { m_options.append((gccOnlyOptions && isClStyle()) ? clangArgsForCl(args) : args); diff --git a/src/plugins/cpptools/compileroptionsbuilder.h b/src/plugins/cpptools/compileroptionsbuilder.h index f81c515db0..c4d8589f17 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.h +++ b/src/plugins/cpptools/compileroptionsbuilder.h @@ -85,6 +85,7 @@ public: // Add custom options void add(const QString &arg, bool gccOnlyOption = false); + void prepend(const QString &arg); void add(const QStringList &args, bool gccOnlyOptions = false); virtual void addExtraOptions() {} diff --git a/src/plugins/cpptools/cppcodemodelsettings.cpp b/src/plugins/cpptools/cppcodemodelsettings.cpp index 5c5113d004..c7cfc2d0cb 100644 --- a/src/plugins/cpptools/cppcodemodelsettings.cpp +++ b/src/plugins/cpptools/cppcodemodelsettings.cpp @@ -29,6 +29,9 @@ #include "cpptoolsconstants.h" #include "cpptoolsreuse.h" +#include <coreplugin/icore.h> +#include <projectexplorer/project.h> + #include <utils/algorithm.h> #include <utils/qtcassert.h> @@ -61,8 +64,12 @@ static QString skipIndexingBigFilesKey() static QString indexerFileSizeLimitKey() { return QLatin1String(Constants::CPPTOOLS_INDEXER_FILE_SIZE_LIMIT); } +static QString clangdSettingsKey() { return QLatin1String("ClangdSettings"); } static QString useClangdKey() { return QLatin1String("UseClangd"); } static QString clangdPathKey() { return QLatin1String("ClangdPath"); } +static QString clangdIndexingKey() { return QLatin1String("ClangdIndexing"); } +static QString clangdThreadLimitKey() { return QLatin1String("ClangdThreadLimit"); } +static QString clangdUseGlobalSettingsKey() { return QLatin1String("useGlobalSettings"); } static FilePath g_defaultClangdFilePath; static FilePath fallbackClangdFilePath() @@ -172,9 +179,6 @@ void CppCodeModelSettings::fromSettings(QSettings *s) const QVariant indexerFileSizeLimit = s->value(indexerFileSizeLimitKey(), 5); setIndexerFileSizeLimitInMb(indexerFileSizeLimit.toInt()); - setUseClangd(s->value(useClangdKey(), false).toBool()); - setClangdFilePath(FilePath::fromString(s->value(clangdPathKey()).toString())); - s->endGroup(); if (write) @@ -198,8 +202,6 @@ void CppCodeModelSettings::toSettings(QSettings *s) s->setValue(interpretAmbiguousHeadersAsCHeadersKey(), interpretAmbigiousHeadersAsCHeaders()); s->setValue(skipIndexingBigFilesKey(), skipIndexingBigFiles()); s->setValue(indexerFileSizeLimitKey(), indexerFileSizeLimitInMb()); - s->setValue(useClangdKey(), useClangd()); - s->setValue(clangdPathKey(), m_clangdFilePath.toString()); s->endGroup(); @@ -300,14 +302,113 @@ void CppCodeModelSettings::setEnableLowerClazyLevels(bool yesno) m_enableLowerClazyLevels = yesno; } -void CppCodeModelSettings::setDefaultClangdPath(const Utils::FilePath &filePath) + +ClangdSettings &ClangdSettings::instance() +{ + static ClangdSettings settings; + return settings; +} + +void ClangdSettings::setDefaultClangdPath(const Utils::FilePath &filePath) { g_defaultClangdFilePath = filePath; } -FilePath CppCodeModelSettings::clangdFilePath() const +FilePath ClangdSettings::clangdFilePath() const { - if (!m_clangdFilePath.isEmpty()) - return m_clangdFilePath; + if (!m_data.executableFilePath.isEmpty()) + return m_data.executableFilePath; return fallbackClangdFilePath(); } + +void ClangdSettings::setData(const Data &data) +{ + if (this == &instance() && data != m_data) { + m_data = data; + saveSettings(); + emit changed(); + } +} + +void ClangdSettings::loadSettings() +{ + m_data.fromMap(Core::ICore::settings()->value(clangdSettingsKey()).toMap()); +} + +void ClangdSettings::saveSettings() +{ + Core::ICore::settings()->setValue(clangdSettingsKey(), m_data.toMap()); +} + +#ifdef WITH_TESTS +void ClangdSettings::setUseClangd(bool use) { instance().m_data.useClangd = use; } +void ClangdSettings::setClangdFilePath(const Utils::FilePath &filePath) +{ + instance().m_data.executableFilePath = filePath; +} +#endif + +ClangdProjectSettings::ClangdProjectSettings(ProjectExplorer::Project *project) : m_project(project) +{ + loadSettings(); +} + +ClangdSettings::Data ClangdProjectSettings::settings() const +{ + if (m_useGlobalSettings) + return ClangdSettings::instance().data(); + return m_customSettings; +} + +void ClangdProjectSettings::setSettings(const ClangdSettings::Data &data) +{ + m_customSettings = data; + saveSettings(); + emit ClangdSettings::instance().changed(); +} + +void ClangdProjectSettings::setUseGlobalSettings(bool useGlobal) +{ + m_useGlobalSettings = useGlobal; + saveSettings(); + emit ClangdSettings::instance().changed(); +} + +void ClangdProjectSettings::loadSettings() +{ + if (!m_project) + return; + const QVariantMap data = m_project->namedSettings(clangdSettingsKey()).toMap(); + m_useGlobalSettings = data.value(clangdUseGlobalSettingsKey(), true).toBool(); + if (!m_useGlobalSettings) + m_customSettings.fromMap(data); +} + +void ClangdProjectSettings::saveSettings() +{ + if (!m_project) + return; + QVariantMap data; + if (!m_useGlobalSettings) + data = m_customSettings.toMap(); + data.insert(clangdUseGlobalSettingsKey(), m_useGlobalSettings); + m_project->setNamedSettings(clangdSettingsKey(), data); +} + +QVariantMap ClangdSettings::Data::toMap() const +{ + QVariantMap map; + map.insert(useClangdKey(), useClangd); + map.insert(clangdPathKey(), executableFilePath.toString()); + map.insert(clangdIndexingKey(), enableIndexing); + map.insert(clangdThreadLimitKey(), workerThreadLimit); + return map; +} + +void ClangdSettings::Data::fromMap(const QVariantMap &map) +{ + useClangd = map.value(useClangdKey(), false).toBool(); + executableFilePath = FilePath::fromString(map.value(clangdPathKey()).toString()); + enableIndexing = map.value(clangdIndexingKey(), true).toBool(); + workerThreadLimit = map.value(clangdThreadLimitKey(), 0).toInt(); +} diff --git a/src/plugins/cpptools/cppcodemodelsettings.h b/src/plugins/cpptools/cppcodemodelsettings.h index 5fc981e543..d4da25f3b0 100644 --- a/src/plugins/cpptools/cppcodemodelsettings.h +++ b/src/plugins/cpptools/cppcodemodelsettings.h @@ -38,6 +38,8 @@ QT_BEGIN_NAMESPACE class QSettings; QT_END_NAMESPACE +namespace ProjectExplorer { class Project; } + namespace CppTools { class CPPTOOLS_EXPORT CppCodeModelSettings : public QObject @@ -78,13 +80,6 @@ public: int indexerFileSizeLimitInMb() const; void setIndexerFileSizeLimitInMb(int sizeInMB); - void setUseClangd(bool use) { m_useClangd = use; } - bool useClangd() const { return m_useClangd; } - - static void setDefaultClangdPath(const Utils::FilePath &filePath); - void setClangdFilePath(const Utils::FilePath &filePath) { m_clangdFilePath = filePath; } - Utils::FilePath clangdFilePath() const; - void setCategorizeFindReferences(bool categorize) { m_categorizeFindReferences = categorize; } bool categorizeFindReferences() const { return m_categorizeFindReferences; } @@ -100,9 +95,84 @@ private: ClangDiagnosticConfigs m_clangCustomDiagnosticConfigs; Utils::Id m_clangDiagnosticConfigId; bool m_enableLowerClazyLevels = true; // For UI behavior only - Utils::FilePath m_clangdFilePath; - bool m_useClangd = false; bool m_categorizeFindReferences = false; // Ephemeral! }; +class CPPTOOLS_EXPORT ClangdSettings : public QObject +{ + Q_OBJECT +public: + class CPPTOOLS_EXPORT Data + { + public: + QVariantMap toMap() const; + void fromMap(const QVariantMap &map); + + Utils::FilePath executableFilePath; + int workerThreadLimit = 0; + bool useClangd = false; + bool enableIndexing = true; + }; + + ClangdSettings(const Data &data) : m_data(data) {} + + static ClangdSettings &instance(); + bool useClangd() const { return m_data.useClangd; } + + static void setDefaultClangdPath(const Utils::FilePath &filePath); + Utils::FilePath clangdFilePath() const; + bool indexingEnabled() const { return m_data.enableIndexing; } + int workerThreadLimit() const { return m_data.workerThreadLimit; } + + void setData(const Data &data); + Data data() const { return m_data; } + +#ifdef WITH_TESTS + static void setUseClangd(bool use); + static void setClangdFilePath(const Utils::FilePath &filePath); +#endif + +signals: + void changed(); + +private: + ClangdSettings() { loadSettings(); } + + void loadSettings(); + void saveSettings(); + + Data m_data; +}; + +inline bool operator==(const ClangdSettings::Data &s1, const ClangdSettings::Data &s2) +{ + return s1.useClangd == s2.useClangd + && s1.executableFilePath == s2.executableFilePath + && s1.workerThreadLimit == s2.workerThreadLimit + && s1.enableIndexing == s2.enableIndexing; +} +inline bool operator!=(const ClangdSettings::Data &s1, const ClangdSettings::Data &s2) +{ + return !(s1 == s2); +} + +class CPPTOOLS_EXPORT ClangdProjectSettings +{ +public: + ClangdProjectSettings(ProjectExplorer::Project *project); + + ClangdSettings::Data settings() const; + void setSettings(const ClangdSettings::Data &data); + bool useGlobalSettings() const { return m_useGlobalSettings; } + void setUseGlobalSettings(bool useGlobal); + +private: + void loadSettings(); + void saveSettings(); + + ProjectExplorer::Project * const m_project; + ClangdSettings::Data m_customSettings; + bool m_useGlobalSettings = true; +}; + } // namespace CppTools diff --git a/src/plugins/cpptools/cppcodemodelsettingspage.cpp b/src/plugins/cpptools/cppcodemodelsettingspage.cpp index 00e7b8081a..dc04dc3cb8 100644 --- a/src/plugins/cpptools/cppcodemodelsettingspage.cpp +++ b/src/plugins/cpptools/cppcodemodelsettingspage.cpp @@ -33,7 +33,10 @@ #include <coreplugin/icore.h> #include <utils/algorithm.h> +#include <utils/pathchooser.h> +#include <QFormLayout> +#include <QSpinBox> #include <QTextStream> namespace CppTools { @@ -100,8 +103,6 @@ void CppCodeModelSettingsWidget::setupClangCodeModelWidgets() const bool isClangActive = CppModelManager::instance()->isClangCodeModelActive(); m_ui->clangCodeModelIsDisabledHint->setVisible(!isClangActive); m_ui->clangCodeModelIsEnabledHint->setVisible(isClangActive); - m_ui->clangdCheckBox->setVisible(isClangActive); - m_ui->clangdChooser->setVisible(isClangActive); for (int i = 0; i < m_ui->clangDiagnosticConfigsSelectionWidget->layout()->count(); ++i) { QWidget *widget = m_ui->clangDiagnosticConfigsSelectionWidget->layout()->itemAt(i)->widget(); @@ -120,16 +121,6 @@ void CppCodeModelSettingsWidget::setupGeneralWidgets() const bool ignorePch = m_settings->pchUsage() == CppCodeModelSettings::PchUse_None; m_ui->ignorePCHCheckBox->setChecked(ignorePch); - - m_ui->clangdCheckBox->setChecked(m_settings->useClangd()); - m_ui->clangdCheckBox->setToolTip(tr("Use clangd for locators and \"Find References\".\n" - "Changing this option does not affect projects that are already open.")); - m_ui->clangdChooser->setExpectedKind(Utils::PathChooser::ExistingCommand); - m_ui->clangdChooser->setFilePath(codeModelSettings()->clangdFilePath()); - m_ui->clangdChooser->setEnabled(m_ui->clangdCheckBox->isChecked()); - connect(m_ui->clangdCheckBox, &QCheckBox::toggled, m_ui->clangdChooser, [this](bool checked) { - m_ui->clangdChooser->setEnabled(checked); - }); } bool CppCodeModelSettingsWidget::applyClangCodeModelWidgetsToSettings() const @@ -176,16 +167,6 @@ bool CppCodeModelSettingsWidget::applyGeneralWidgetsToSettings() const m_settings->setIndexerFileSizeLimitInMb(newFileSizeLimit); settingsChanged = true; } - const bool newUseClangd = m_ui->clangdCheckBox->isChecked(); - if (m_settings->useClangd() != newUseClangd) { - m_settings->setUseClangd(newUseClangd); - settingsChanged = true; - } - const Utils::FilePath newClangdPath = m_ui->clangdChooser->rawFilePath(); - if (m_settings->clangdFilePath() != newClangdPath) { - m_settings->setClangdFilePath(newClangdPath); - settingsChanged = true; - } const bool newIgnorePch = m_ui->ignorePCHCheckBox->isChecked(); const bool previousIgnorePch = m_settings->pchUsage() == CppCodeModelSettings::PchUse_None; @@ -210,5 +191,147 @@ CppCodeModelSettingsPage::CppCodeModelSettingsPage(CppCodeModelSettings *setting setWidgetCreator([settings] { return new CppCodeModelSettingsWidget(settings); }); } +class ClangdSettingsWidget::Private +{ +public: + QCheckBox useClangdCheckBox; + QCheckBox indexingCheckBox; + QSpinBox threadLimitSpinBox; + Utils::PathChooser clangdChooser; +}; + +ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsData) + : d(new Private) +{ + const ClangdSettings settings(settingsData); + d->useClangdCheckBox.setText(tr("Use clangd (EXPERIMENTAL)")); + d->useClangdCheckBox.setChecked(settings.useClangd()); + d->clangdChooser.setExpectedKind(Utils::PathChooser::ExistingCommand); + d->clangdChooser.setFilePath(settings.clangdFilePath()); + d->clangdChooser.setEnabled(d->useClangdCheckBox.isChecked()); + d->indexingCheckBox.setChecked(settings.indexingEnabled()); + d->indexingCheckBox.setToolTip(tr( + "If background indexing is enabled, global symbol searches will yield\n" + "more accurate results, at the cost of additional CPU load when\n" + "the project is first opened.")); + d->threadLimitSpinBox.setValue(settings.workerThreadLimit()); + d->threadLimitSpinBox.setSpecialValueText("Automatic"); + + const auto layout = new QVBoxLayout(this); + layout->addWidget(&d->useClangdCheckBox); + const auto formLayout = new QFormLayout; + const auto chooserLabel = new QLabel(tr("Path to executable:")); + formLayout->addRow(chooserLabel, &d->clangdChooser); + const auto indexingLabel = new QLabel(tr("Enable background indexing:")); + formLayout->addRow(indexingLabel, &d->indexingCheckBox); + const auto threadLimitLayout = new QHBoxLayout; + threadLimitLayout->addWidget(&d->threadLimitSpinBox); + threadLimitLayout->addStretch(1); + const auto threadLimitLabel = new QLabel(tr("Set worker thread count:")); + formLayout->addRow(threadLimitLabel, threadLimitLayout); + layout->addLayout(formLayout); + layout->addStretch(1); + + const auto toggleEnabled = [=](const bool checked) { + chooserLabel->setEnabled(checked); + d->clangdChooser.setEnabled(checked); + indexingLabel->setEnabled(checked); + d->indexingCheckBox.setEnabled(checked); + d->threadLimitSpinBox.setEnabled(checked); + }; + connect(&d->useClangdCheckBox, &QCheckBox::toggled, toggleEnabled); + toggleEnabled(d->useClangdCheckBox.isChecked()); + d->threadLimitSpinBox.setEnabled(d->useClangdCheckBox.isChecked()); + + connect(&d->useClangdCheckBox, &QCheckBox::toggled, + this, &ClangdSettingsWidget::settingsDataChanged); + connect(&d->indexingCheckBox, &QCheckBox::toggled, + this, &ClangdSettingsWidget::settingsDataChanged); + connect(&d->threadLimitSpinBox, qOverload<int>(&QSpinBox::valueChanged), + this, &ClangdSettingsWidget::settingsDataChanged); + connect(&d->clangdChooser, &Utils::PathChooser::pathChanged, + this, &ClangdSettingsWidget::settingsDataChanged); +} + +ClangdSettingsWidget::~ClangdSettingsWidget() +{ + delete d; +} + +ClangdSettings::Data ClangdSettingsWidget::settingsData() const +{ + ClangdSettings::Data data; + data.useClangd = d->useClangdCheckBox.isChecked(); + data.executableFilePath = d->clangdChooser.filePath(); + data.enableIndexing = d->indexingCheckBox.isChecked(); + data.workerThreadLimit = d->threadLimitSpinBox.value(); + return data; +} + +class ClangdSettingsPageWidget final : public Core::IOptionsPageWidget +{ + Q_DECLARE_TR_FUNCTIONS(CppTools::Internal::ClangdSettingsWidget) + +public: + ClangdSettingsPageWidget() : m_widget(ClangdSettings::instance().data()) + { + const auto layout = new QVBoxLayout(this); + layout->addWidget(&m_widget); + } + +private: + void apply() final { ClangdSettings::instance().setData(m_widget.settingsData()); } + + ClangdSettingsWidget m_widget; +}; + +ClangdSettingsPage::ClangdSettingsPage() +{ + setId("K.Clangd"); + setDisplayName(ClangdSettingsWidget::tr("Clangd")); + setCategory(Constants::CPP_SETTINGS_CATEGORY); + setWidgetCreator([] { return new ClangdSettingsPageWidget; }); +} + + +class ClangdProjectSettingsWidget::Private +{ +public: + Private(const ClangdProjectSettings &s) : settings(s), widget(s.settings()) {} + + ClangdProjectSettings settings; + ClangdSettingsWidget widget; + QCheckBox useGlobalSettingsCheckBox; +}; + +ClangdProjectSettingsWidget::ClangdProjectSettingsWidget(const ClangdProjectSettings &settings) + : d(new Private(settings)) +{ + const auto layout = new QVBoxLayout(this); + d->useGlobalSettingsCheckBox.setText(tr("Use global settings")); + layout->addWidget(&d->useGlobalSettingsCheckBox); + const auto separator = new QFrame; + separator->setFrameShape(QFrame::HLine); + layout->addWidget(separator); + layout->addWidget(&d->widget); + + d->useGlobalSettingsCheckBox.setChecked(d->settings.useGlobalSettings()); + d->widget.setEnabled(!d->settings.useGlobalSettings()); + connect(&d->useGlobalSettingsCheckBox, &QCheckBox::toggled, [this](bool checked) { + d->widget.setEnabled(!checked); + d->settings.setUseGlobalSettings(checked); + if (!checked) + d->settings.setSettings(d->widget.settingsData()); + }); + connect(&d->widget, &ClangdSettingsWidget::settingsDataChanged, [this] { + d->settings.setSettings(d->widget.settingsData()); + }); +} + +ClangdProjectSettingsWidget::~ClangdProjectSettingsWidget() +{ + delete d; +} + } // Internal } // CppTools diff --git a/src/plugins/cpptools/cppcodemodelsettingspage.h b/src/plugins/cpptools/cppcodemodelsettingspage.h index dd297af020..220645ca3e 100644 --- a/src/plugins/cpptools/cppcodemodelsettingspage.h +++ b/src/plugins/cpptools/cppcodemodelsettingspage.h @@ -38,5 +38,42 @@ public: explicit CppCodeModelSettingsPage(CppCodeModelSettings *settings); }; +class ClangdSettingsPage final : public Core::IOptionsPage +{ +public: + explicit ClangdSettingsPage(); +}; + +class ClangdSettingsWidget : public QWidget +{ + Q_OBJECT + +public: + ClangdSettingsWidget(const ClangdSettings::Data &settingsData); + ~ClangdSettingsWidget(); + + ClangdSettings::Data settingsData() const; + +signals: + void settingsDataChanged(); + +private: + class Private; + Private * const d; +}; + +class ClangdProjectSettingsWidget : public QWidget +{ + Q_OBJECT + +public: + ClangdProjectSettingsWidget(const ClangdProjectSettings &settings); + ~ClangdProjectSettingsWidget(); + +private: + class Private; + Private * const d; +}; + } // Internal namespace } // CppTools namespace diff --git a/src/plugins/cpptools/cppcodemodelsettingspage.ui b/src/plugins/cpptools/cppcodemodelsettingspage.ui index 2362131cbe..90136f81bd 100644 --- a/src/plugins/cpptools/cppcodemodelsettingspage.ui +++ b/src/plugins/cpptools/cppcodemodelsettingspage.ui @@ -81,31 +81,7 @@ </layout> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QCheckBox" name="clangdCheckBox"> - <property name="text"> - <string>Use clangd (EXPERIMENTAL)</string> - </property> - </widget> - </item> - <item> - <widget class="Utils::PathChooser" name="clangdChooser"/> - </item> - <item> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> + <layout class="QHBoxLayout" name="horizontalLayout_3"/> </item> </layout> </widget> @@ -174,11 +150,6 @@ <extends>QWidget</extends> <header>cpptools/clangdiagnosticconfigsselectionwidget.h</header> </customwidget> - <customwidget> - <class>Utils::PathChooser</class> - <extends>QLineEdit</extends> - <header location="global">utils/pathchooser.h</header> - </customwidget> </customwidgets> <resources/> <connections/> diff --git a/src/plugins/cpptools/cppheadersource_test.cpp b/src/plugins/cpptools/cppheadersource_test.cpp index 37244f4fba..be0bdd03c2 100644 --- a/src/plugins/cpptools/cppheadersource_test.cpp +++ b/src/plugins/cpptools/cppheadersource_test.cpp @@ -100,7 +100,7 @@ void CppToolsPlugin::initTestCase() void CppToolsPlugin::cleanupTestCase() { - Utils::FileUtils::removeRecursively(Utils::FilePath::fromString(baseTestDir())); + Utils::FilePath::fromString(baseTestDir()).removeRecursively(); CppFileSettings *fs = fileSettings(); fs->headerSearchPaths.removeLast(); fs->headerSearchPaths.removeLast(); diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index fbee2cebbd..2366b5d4da 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -1145,7 +1145,8 @@ void CppModelManager::updateCppEditorDocuments(bool projectsUpdated) const } } -QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectInfo) +QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectInfo, + const QSet<QString> &additionalFiles) { if (!newProjectInfo.isValid()) return QFuture<void>(); @@ -1236,6 +1237,7 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectIn // resolved includes that we could rely on. updateCppEditorDocuments(/*projectsUpdated = */ true); + filesToReindex.unite(additionalFiles); // Trigger reindexing const QFuture<void> indexingFuture = updateSourceFiles(filesToReindex, ForcedProgressNotification); @@ -1310,6 +1312,11 @@ bool CppModelManager::isCppEditor(Core::IEditor *editor) return editor->context().contains(ProjectExplorer::Constants::CXX_LANGUAGE_ID); } +bool CppModelManager::supportsOutline(const TextEditor::TextDocument *document) +{ + return instance()->d->m_activeModelManagerSupport->supportsOutline(document); +} + bool CppModelManager::isClangCodeModelActive() const { return d->m_activeModelManagerSupport != d->m_builtinModelManagerSupport; diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index 98991f9c6c..81e8ec3710 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -116,7 +116,8 @@ public: QList<ProjectInfo> projectInfos() const; ProjectInfo projectInfo(ProjectExplorer::Project *project) const; - QFuture<void> updateProjectInfo(const ProjectInfo &newProjectInfo); + QFuture<void> updateProjectInfo(const ProjectInfo &newProjectInfo, + const QSet<QString> &additionalFiles = {}); /// \return The project part with the given project file ProjectPart::Ptr projectPartForId(const QString &projectPartId) const override; @@ -142,6 +143,7 @@ public: void emitAbstractEditorSupportRemoved(const QString &filePath); static bool isCppEditor(Core::IEditor *editor); + static bool supportsOutline(const TextEditor::TextDocument *document); bool isClangCodeModelActive() const; QSet<AbstractEditorSupport*> abstractEditorSupports() const; diff --git a/src/plugins/cpptools/cppmodelmanagersupport.h b/src/plugins/cpptools/cppmodelmanagersupport.h index ccf7ee83de..13b6108fab 100644 --- a/src/plugins/cpptools/cppmodelmanagersupport.h +++ b/src/plugins/cpptools/cppmodelmanagersupport.h @@ -61,6 +61,7 @@ public: virtual FollowSymbolInterface &followSymbolInterface() = 0; virtual RefactoringEngineInterface &refactoringEngineInterface() = 0; virtual std::unique_ptr<AbstractOverviewModel> createOverviewModel() = 0; + virtual bool supportsOutline(const TextEditor::TextDocument *) const { return true; } }; class CPPTOOLS_EXPORT ModelManagerSupportProvider diff --git a/src/plugins/cpptools/cppprojectupdater.cpp b/src/plugins/cpptools/cppprojectupdater.cpp index 794fd7abe7..f34628af51 100644 --- a/src/plugins/cpptools/cppprojectupdater.cpp +++ b/src/plugins/cpptools/cppprojectupdater.cpp @@ -27,14 +27,21 @@ #include "cppmodelmanager.h" #include "cppprojectinfogenerator.h" +#include "generatedcodemodelsupport.h" + +#include <coreplugin/progressmanager/progressmanager.h> #include <projectexplorer/toolchainmanager.h> +#include <utils/algorithm.h> +#include <utils/fileutils.h> #include <utils/qtcassert.h> #include <utils/runextensions.h> #include <QFutureInterface> +using namespace ProjectExplorer; + namespace CppTools { CppProjectUpdater::CppProjectUpdater() @@ -46,11 +53,25 @@ CppProjectUpdater::CppProjectUpdater() m_futureSynchronizer.setCancelOnWait(true); } -void CppProjectUpdater::update(const ProjectExplorer::ProjectUpdateInfo &projectUpdateInfo) +CppProjectUpdater::~CppProjectUpdater() +{ + cancel(); +} + +void CppProjectUpdater::update(const ProjectUpdateInfo &projectUpdateInfo) +{ + update(projectUpdateInfo, {}); +} + +void CppProjectUpdater::update(const ProjectUpdateInfo &projectUpdateInfo, + const QList<ProjectExplorer::ExtraCompiler *> &extraCompilers) { // Stop previous update. cancel(); + m_extraCompilers = Utils::transform(extraCompilers, [](ExtraCompiler *compiler) { + return QPointer<ExtraCompiler>(compiler); + }); m_projectUpdateInfo = projectUpdateInfo; // Ensure that we do not operate on a deleted toolchain. @@ -68,15 +89,52 @@ void CppProjectUpdater::update(const ProjectExplorer::ProjectUpdateInfo &project }); m_generateFutureWatcher.setFuture(generateFuture); m_futureSynchronizer.addFuture(generateFuture); + + // extra compilers + for (QPointer<ExtraCompiler> compiler : qAsConst(m_extraCompilers)) { + if (compiler->isDirty()) { + auto watcher = new QFutureWatcher<void>; + // queued connection to delay after the extra compiler updated its result contents, + // which is also done in the main thread when compiler->run() finished + connect(watcher, &QFutureWatcherBase::finished, + this, [this, watcher] { + m_projectUpdateFutureInterface->setProgressValue( + m_projectUpdateFutureInterface->progressValue() + 1); + m_extraCompilersFutureWatchers.remove(watcher); + watcher->deleteLater(); + if (!watcher->isCanceled()) + checkForExtraCompilersFinished(); + }, + Qt::QueuedConnection); + m_extraCompilersFutureWatchers += watcher; + watcher->setFuture(QFuture<void>(compiler->run())); + m_futureSynchronizer.addFuture(watcher->future()); + } + } + + m_projectUpdateFutureInterface.reset(new QFutureInterface<void>); + m_projectUpdateFutureInterface->setProgressRange(0, m_extraCompilersFutureWatchers.size() + + 1 /*generateFuture*/); + m_projectUpdateFutureInterface->setProgressValue(0); + m_projectUpdateFutureInterface->reportStarted(); + Core::ProgressManager::addTask(m_projectUpdateFutureInterface->future(), + tr("Preparing C++ Code Model"), + "CppProjectUpdater"); } void CppProjectUpdater::cancel() { + if (m_projectUpdateFutureInterface && m_projectUpdateFutureInterface->isRunning()) + m_projectUpdateFutureInterface->reportFinished(); m_generateFutureWatcher.setFuture({}); + m_isProjectInfoGenerated = false; + qDeleteAll(m_extraCompilersFutureWatchers); + m_extraCompilersFutureWatchers.clear(); + m_extraCompilers.clear(); m_futureSynchronizer.cancelAllFutures(); } -void CppProjectUpdater::onToolChainRemoved(ProjectExplorer::ToolChain *t) +void CppProjectUpdater::onToolChainRemoved(ToolChain *t) { QTC_ASSERT(t, return); if (t == m_projectUpdateInfo.cToolChain || t == m_projectUpdateInfo.cxxToolChain) @@ -93,8 +151,33 @@ void CppProjectUpdater::onProjectInfoGenerated() if (m_generateFutureWatcher.isCanceled() || m_generateFutureWatcher.future().resultCount() < 1) return; - auto updateFuture = CppModelManager::instance()->updateProjectInfo( - m_generateFutureWatcher.result()); + m_projectUpdateFutureInterface->setProgressValue(m_projectUpdateFutureInterface->progressValue() + + 1); + m_isProjectInfoGenerated = true; + checkForExtraCompilersFinished(); +} + +void CppProjectUpdater::checkForExtraCompilersFinished() +{ + if (!m_extraCompilersFutureWatchers.isEmpty() || !m_isProjectInfoGenerated) + return; // still need to wait + + m_projectUpdateFutureInterface->reportFinished(); + m_projectUpdateFutureInterface.reset(); + + QList<ExtraCompiler *> extraCompilers; + QSet<QString> compilerFiles; + for (const QPointer<ExtraCompiler> &compiler : qAsConst(m_extraCompilers)) { + if (compiler) { + extraCompilers += compiler.data(); + compilerFiles += Utils::transform<QSet>(compiler->targets(), &Utils::FilePath::toString); + } + } + GeneratedCodeModelSupport::update(extraCompilers); + m_extraCompilers.clear(); + + auto updateFuture = CppModelManager::instance() + ->updateProjectInfo(m_generateFutureWatcher.result(), compilerFiles); m_futureSynchronizer.addFuture(updateFuture); } diff --git a/src/plugins/cpptools/cppprojectupdater.h b/src/plugins/cpptools/cppprojectupdater.h index 6b994871ef..c356ab63d1 100644 --- a/src/plugins/cpptools/cppprojectupdater.h +++ b/src/plugins/cpptools/cppprojectupdater.h @@ -29,6 +29,7 @@ #include "cpptools_global.h" #include "projectinfo.h" +#include <projectexplorer/extracompiler.h> #include <utils/futuresynchronizer.h> #include <QFutureWatcher> @@ -54,18 +55,26 @@ class CPPTOOLS_EXPORT CppProjectUpdater final : public QObject, public CppProjec public: CppProjectUpdater(); + ~CppProjectUpdater() override; void update(const ProjectExplorer::ProjectUpdateInfo &projectUpdateInfo) override; + void update(const ProjectExplorer::ProjectUpdateInfo &projectUpdateInfo, + const QList<ProjectExplorer::ExtraCompiler *> &extraCompilers); void cancel() override; private: void onToolChainRemoved(ProjectExplorer::ToolChain *); void onProjectInfoGenerated(); + void checkForExtraCompilersFinished(); private: ProjectExplorer::ProjectUpdateInfo m_projectUpdateInfo; + QList<QPointer<ProjectExplorer::ExtraCompiler>> m_extraCompilers; QFutureWatcher<ProjectInfo> m_generateFutureWatcher; + bool m_isProjectInfoGenerated = false; + QSet<QFutureWatcher<void> *> m_extraCompilersFutureWatchers; + std::unique_ptr<QFutureInterface<void>> m_projectUpdateFutureInterface; Utils::FutureSynchronizer m_futureSynchronizer; }; diff --git a/src/plugins/cpptools/cpptoolsconstants.h b/src/plugins/cpptools/cpptoolsconstants.h index 7ee83c1f70..9b5b1c6f64 100644 --- a/src/plugins/cpptools/cpptoolsconstants.h +++ b/src/plugins/cpptools/cpptoolsconstants.h @@ -95,14 +95,6 @@ const char LOCATOR_FILTER_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("CppTools", "C++ Cl const char SYMBOLS_FIND_FILTER_ID[] = "Symbols"; const char SYMBOLS_FIND_FILTER_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("CppTools", "C++ Symbols"); -// CLANG-UPGRADE-CHECK: Checks/update URLs. -// -// Upgrade the version in the URL. Note that we cannot use the macro -// CLANG_VERSION here because it might denote a version that was not yet -// released (e.g. 6.0.1, but only 6.0.0 was released). -constexpr const char TIDY_DOCUMENTATION_URL_TEMPLATE[] - = "https://releases.llvm.org/11.0.0/tools/clang/tools/extra/docs/clang-tidy/checks/%1.html"; - constexpr const char CLANG_STATIC_ANALYZER_DOCUMENTATION_URL[] = "https://clang-analyzer.llvm.org/available_checks.html"; diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp index c5796e0dba..1e77501c0f 100644 --- a/src/plugins/cpptools/cpptoolsplugin.cpp +++ b/src/plugins/cpptools/cpptoolsplugin.cpp @@ -49,6 +49,7 @@ #include <cppeditor/cppeditorconstants.h> #include <extensionsystem/pluginmanager.h> #include <projectexplorer/project.h> +#include <projectexplorer/projectpanelfactory.h> #include <projectexplorer/projecttree.h> #include <utils/algorithm.h> @@ -86,6 +87,7 @@ public: ~CppToolsPluginPrivate() { ExtensionSystem::PluginManager::removeObject(&m_cppProjectUpdaterFactory); + delete m_clangdSettingsPage; } StringTable stringTable; @@ -95,6 +97,7 @@ public: CppFileSettings m_fileSettings; CppFileSettingsPage m_cppFileSettingsPage{&m_fileSettings}; CppCodeModelSettingsPage m_cppCodeModelSettingsPage{&m_codeModelSettings}; + ClangdSettingsPage *m_clangdSettingsPage = nullptr; CppCodeStyleSettingsPage m_cppCodeStyleSettingsPage; CppProjectUpdaterFactory m_cppProjectUpdaterFactory; }; @@ -208,6 +211,14 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error) tr("Insert \"#pragma once\" instead of \"#ifndef\" include guards into header file"), [] { return usePragmaOnce() ? QString("true") : QString(); }); + const auto panelFactory = new ProjectExplorer::ProjectPanelFactory; + panelFactory->setPriority(100); + panelFactory->setDisplayName(tr("Clangd")); + panelFactory->setCreateWidgetFunction([](ProjectExplorer::Project *project) { + return new ClangdProjectSettingsWidget(project); + }); + ProjectExplorer::ProjectPanelFactory::registerFactory(panelFactory); + return true; } @@ -218,6 +229,8 @@ void CppToolsPlugin::extensionsInitialized() d->m_fileSettings.fromSettings(ICore::settings()); if (!d->m_fileSettings.applySuffixesToMimeDB()) qWarning("Unable to apply cpp suffixes to mime database (cpp mime types not found).\n"); + if (CppModelManager::instance()->isClangCodeModelActive()) + d->m_clangdSettingsPage = new ClangdSettingsPage; } CppCodeModelSettings *CppToolsPlugin::codeModelSettings() diff --git a/src/plugins/cpptools/cpptoolstestcase.cpp b/src/plugins/cpptools/cpptoolstestcase.cpp index c80a4a7cff..e9a6e85d0d 100644 --- a/src/plugins/cpptools/cpptoolstestcase.cpp +++ b/src/plugins/cpptools/cpptoolstestcase.cpp @@ -312,7 +312,7 @@ QString TemporaryDir::createFile(const QByteArray &relativePath, const QByteArra if (relativePathString.isEmpty() || QFileInfo(relativePathString).isAbsolute()) return QString(); - const QString filePath = m_temporaryDir.path() + QLatin1Char('/') + relativePathString; + const QString filePath = m_temporaryDir.filePath(relativePathString).path(); if (!TestCase::writeFile(filePath, contents)) return QString(); return filePath; @@ -368,7 +368,7 @@ TemporaryCopiedDir::TemporaryCopiedDir(const QString &sourceDirPath) QString TemporaryCopiedDir::absolutePath(const QByteArray &relativePath) const { - return m_temporaryDir.path() + QLatin1Char('/') + QString::fromUtf8(relativePath); + return m_temporaryDir.filePath(QString::fromUtf8(relativePath)).path(); } FileWriterAndRemover::FileWriterAndRemover(const QString &filePath, const QByteArray &contents) diff --git a/src/plugins/cpptools/cpptoolstestcase.h b/src/plugins/cpptools/cpptoolstestcase.h index 08ae5b7c70..d03a1b297c 100644 --- a/src/plugins/cpptools/cpptoolstestcase.h +++ b/src/plugins/cpptools/cpptoolstestcase.h @@ -155,7 +155,7 @@ public: TemporaryDir(); bool isValid() const { return m_isValid; } - QString path() const { return m_temporaryDir.path(); } + QString path() const { return m_temporaryDir.path().path(); } QString createFile(const QByteArray &relativePath, const QByteArray &contents); |