aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/cpptools
diff options
context:
space:
mode:
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>2021-07-05 12:17:43 +0300
committerOrgad Shaneh <orgad.shaneh@audiocodes.com>2021-07-05 12:17:45 +0300
commit84839ee397c659c07dddb9459bc50e72cd083ab4 (patch)
tree81e3ae4ac0f414b049e0f0cb50c4fb2fced0ee0b /src/plugins/cpptools
parent32f46e55ed5297157d1abf499d70f6c0f08d34d7 (diff)
parent21115ae5118dafcf3ac9b7558761cd3925842236 (diff)
Merge remote-tracking branch 'origin/5.0'
Diffstat (limited to 'src/plugins/cpptools')
-rw-r--r--src/plugins/cpptools/clangdiagnosticconfig.cpp23
-rw-r--r--src/plugins/cpptools/compileroptionsbuilder.cpp5
-rw-r--r--src/plugins/cpptools/compileroptionsbuilder.h1
-rw-r--r--src/plugins/cpptools/cppcodemodelsettings.cpp119
-rw-r--r--src/plugins/cpptools/cppcodemodelsettings.h88
-rw-r--r--src/plugins/cpptools/cppcodemodelsettingspage.cpp167
-rw-r--r--src/plugins/cpptools/cppcodemodelsettingspage.h37
-rw-r--r--src/plugins/cpptools/cppcodemodelsettingspage.ui31
-rw-r--r--src/plugins/cpptools/cppheadersource_test.cpp2
-rw-r--r--src/plugins/cpptools/cppmodelmanager.cpp9
-rw-r--r--src/plugins/cpptools/cppmodelmanager.h4
-rw-r--r--src/plugins/cpptools/cppmodelmanagersupport.h1
-rw-r--r--src/plugins/cpptools/cppprojectupdater.cpp91
-rw-r--r--src/plugins/cpptools/cppprojectupdater.h9
-rw-r--r--src/plugins/cpptools/cpptoolsconstants.h8
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.cpp13
-rw-r--r--src/plugins/cpptools/cpptoolstestcase.cpp4
-rw-r--r--src/plugins/cpptools/cpptoolstestcase.h2
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);