From 8cfef9657a112276dd2308bf31e61b17580c5088 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Mon, 22 Feb 2016 17:18:18 +0100 Subject: [PATCH] Clang: Introduce switching/adding of warning configurations A warning configuration is a list of command line (warning) options for libclang. Three non-editable built-in configurations are provided by default. The user can copy a configuration to customize it. This is still a global setting and it changes take effect after re-opening a document. Both issues will be addressed in follow-up changes. Change-Id: I86667d7dc39ad31b88666454220e6da563797740 Reviewed-by: Leena Miettinen Reviewed-by: Marco Bubke --- .../clangeditordocumentprocessor.cpp | 4 +- .../cpptools/clangdiagnosticconfig.cpp | 78 +++++++ src/plugins/cpptools/clangdiagnosticconfig.h | 63 ++++++ .../cpptools/clangdiagnosticconfigsmodel.cpp | 146 +++++++++++++ .../cpptools/clangdiagnosticconfigsmodel.h | 55 +++++ .../cpptools/clangdiagnosticconfigswidget.cpp | 196 ++++++++++++++++++ .../cpptools/clangdiagnosticconfigswidget.h | 73 +++++++ .../cpptools/clangdiagnosticconfigswidget.ui | 81 ++++++++ src/plugins/cpptools/cppcodemodelsettings.cpp | 104 +++++++--- src/plugins/cpptools/cppcodemodelsettings.h | 15 +- .../cpptools/cppcodemodelsettingspage.cpp | 32 +-- .../cpptools/cppcodemodelsettingspage.h | 5 +- .../cpptools/cppcodemodelsettingspage.ui | 39 +--- src/plugins/cpptools/cpptools.pro | 7 + src/plugins/cpptools/cpptools.qbs | 4 + src/plugins/cpptools/cpptoolsconstants.h | 3 +- 16 files changed, 820 insertions(+), 85 deletions(-) create mode 100644 src/plugins/cpptools/clangdiagnosticconfig.cpp create mode 100644 src/plugins/cpptools/clangdiagnosticconfig.h create mode 100644 src/plugins/cpptools/clangdiagnosticconfigsmodel.cpp create mode 100644 src/plugins/cpptools/clangdiagnosticconfigsmodel.h create mode 100644 src/plugins/cpptools/clangdiagnosticconfigswidget.cpp create mode 100644 src/plugins/cpptools/clangdiagnosticconfigswidget.h create mode 100644 src/plugins/cpptools/clangdiagnosticconfigswidget.ui diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 8cdd19d436..38f7cb2d51 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -342,8 +342,8 @@ static QStringList languageOptions(const QString &filePath, CppTools::ProjectPar static QStringList fileArguments(const QString &filePath, CppTools::ProjectPart *projectPart) { - return QStringList(languageOptions(filePath, projectPart)) - + CppTools::codeModelSettings()->extraClangOptions(); + return languageOptions(filePath, projectPart) + + CppTools::codeModelSettings()->clangDiagnosticConfig().commandLineOptions(); } ClangBackEnd::FileContainer diff --git a/src/plugins/cpptools/clangdiagnosticconfig.cpp b/src/plugins/cpptools/clangdiagnosticconfig.cpp new file mode 100644 index 0000000000..62d259c521 --- /dev/null +++ b/src/plugins/cpptools/clangdiagnosticconfig.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "clangdiagnosticconfig.h" + +namespace CppTools { + +Core::Id ClangDiagnosticConfig::id() const +{ + return m_id; +} + +void ClangDiagnosticConfig::setId(const Core::Id &id) +{ + m_id = id; +} + +QString ClangDiagnosticConfig::displayName() const +{ + return m_displayName; +} + +void ClangDiagnosticConfig::setDisplayName(const QString &displayName) +{ + m_displayName = displayName; +} + +QStringList ClangDiagnosticConfig::commandLineOptions() const +{ + return m_commandLineOptions; +} + +void ClangDiagnosticConfig::setCommandLineOptions(const QStringList &options) +{ + m_commandLineOptions = options; +} + +bool ClangDiagnosticConfig::isReadOnly() const +{ + return m_isReadOnly; +} + +void ClangDiagnosticConfig::setIsReadOnly(bool isReadOnly) +{ + m_isReadOnly = isReadOnly; +} + +bool ClangDiagnosticConfig::operator==(const ClangDiagnosticConfig &other) const +{ + return m_id == other.m_id + && m_displayName == other.m_displayName + && m_commandLineOptions == other.m_commandLineOptions + && m_isReadOnly == other.m_isReadOnly; +} + +} // namespace CppTools diff --git a/src/plugins/cpptools/clangdiagnosticconfig.h b/src/plugins/cpptools/clangdiagnosticconfig.h new file mode 100644 index 0000000000..17a5a768bb --- /dev/null +++ b/src/plugins/cpptools/clangdiagnosticconfig.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "cpptools_global.h" + +#include + +#include +#include + +namespace CppTools { + +class CPPTOOLS_EXPORT ClangDiagnosticConfig +{ +public: + Core::Id id() const; + void setId(const Core::Id &id); + + QString displayName() const; + void setDisplayName(const QString &displayName); + + QStringList commandLineOptions() const; + void setCommandLineOptions(const QStringList &commandLineOptions); + + bool isReadOnly() const; + void setIsReadOnly(bool isReadOnly); + + bool operator==(const ClangDiagnosticConfig &other) const; + +private: + Core::Id m_id; + QString m_displayName; + QStringList m_commandLineOptions; + bool m_isReadOnly = false; +}; + +using ClangDiagnosticConfigs = QVector; + +} // namespace CppTools diff --git a/src/plugins/cpptools/clangdiagnosticconfigsmodel.cpp b/src/plugins/cpptools/clangdiagnosticconfigsmodel.cpp new file mode 100644 index 0000000000..ccd78141d8 --- /dev/null +++ b/src/plugins/cpptools/clangdiagnosticconfigsmodel.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "clangdiagnosticconfigsmodel.h" + +#include "cpptoolsconstants.h" + +#include + +#include + +namespace CppTools { +namespace Internal { + +static void addConfigForQuestionableConstructs(ClangDiagnosticConfigsModel &model) +{ + ClangDiagnosticConfig config; + config.setId("Builtin.Questionable"); + config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel", + "Warnings for questionable constructs")); + config.setIsReadOnly(true); + config.setCommandLineOptions({ + QStringLiteral("-Wall"), + QStringLiteral("-Wextra"), + }); + + model.appendOrUpdate(config); +} + +static void addConfigForPedanticWarnings(ClangDiagnosticConfigsModel &model) +{ + ClangDiagnosticConfig config; + config.setId("Builtin.Pedantic"); + config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel", + "Pedantic Warnings")); + config.setIsReadOnly(true); + config.setCommandLineOptions({QStringLiteral("-Wpedantic")}); + + model.appendOrUpdate(config); +} + +static void addConfigForAlmostEveryWarning(ClangDiagnosticConfigsModel &model) +{ + ClangDiagnosticConfig config; + config.setId(Constants::CPP_CLANG_BUILTIN_CONFIG_ID_EVERYTHING_WITH_EXCEPTIONS); + config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel", + "Warnings for almost everything")); + config.setIsReadOnly(true); + config.setCommandLineOptions({ + QStringLiteral("-Weverything"), + QStringLiteral("-Wno-c++98-compat"), + QStringLiteral("-Wno-c++98-compat-pedantic"), + QStringLiteral("-Wno-unused-macros"), + QStringLiteral("-Wno-newline-eof"), + QStringLiteral("-Wno-exit-time-destructors"), + QStringLiteral("-Wno-global-constructors"), + QStringLiteral("-Wno-gnu-zero-variadic-macro-arguments"), + QStringLiteral("-Wno-documentation"), + QStringLiteral("-Wno-shadow"), + QStringLiteral("-Wno-missing-prototypes"), // Not optimal for C projects. + }); + + model.appendOrUpdate(config); +} + +static void addBuiltinConfigs(ClangDiagnosticConfigsModel &model) +{ + addConfigForPedanticWarnings(model); + addConfigForQuestionableConstructs(model); + addConfigForAlmostEveryWarning(model); +} + +ClangDiagnosticConfigsModel::ClangDiagnosticConfigsModel(const ClangDiagnosticConfigs &customConfigs) +{ + addBuiltinConfigs(*this); + + foreach (const ClangDiagnosticConfig &config, customConfigs) + m_diagnosticConfigs.append(config); +} + +int ClangDiagnosticConfigsModel::size() const +{ + return m_diagnosticConfigs.size(); +} + +const ClangDiagnosticConfig &ClangDiagnosticConfigsModel::at(int index) const +{ + return m_diagnosticConfigs.at(index); +} + +void ClangDiagnosticConfigsModel::appendOrUpdate(const ClangDiagnosticConfig &config) +{ + const int index = indexOfConfig(config.id()); + + if (index >= 0 && index < m_diagnosticConfigs.size()) + m_diagnosticConfigs.replace(index, config); + else + m_diagnosticConfigs.append(config); +} + +void ClangDiagnosticConfigsModel::removeConfigWithId(const Core::Id &id) +{ + m_diagnosticConfigs.removeOne(configWithId(id)); +} + +ClangDiagnosticConfigs ClangDiagnosticConfigsModel::configs() const +{ + return m_diagnosticConfigs; +} + +const ClangDiagnosticConfig &ClangDiagnosticConfigsModel::configWithId(const Core::Id &id) const +{ + return m_diagnosticConfigs.at(indexOfConfig(id)); +} + +int ClangDiagnosticConfigsModel::indexOfConfig(const Core::Id &id) const +{ + return Utils::indexOf(m_diagnosticConfigs, [&](const ClangDiagnosticConfig &config) { + return config.id() == id; + }); +} + +} // namespace Internal +} // namespace CppTools diff --git a/src/plugins/cpptools/clangdiagnosticconfigsmodel.h b/src/plugins/cpptools/clangdiagnosticconfigsmodel.h new file mode 100644 index 0000000000..ffccd0868a --- /dev/null +++ b/src/plugins/cpptools/clangdiagnosticconfigsmodel.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "clangdiagnosticconfig.h" + +namespace CppTools { +namespace Internal { + +class ClangDiagnosticConfigsModel +{ +public: + ClangDiagnosticConfigsModel(const ClangDiagnosticConfigs &customConfigs); + + int size() const; + const ClangDiagnosticConfig &at(int index) const; + + void appendOrUpdate(const ClangDiagnosticConfig &config); + void removeConfigWithId(const Core::Id &id); + + ClangDiagnosticConfigs configs() const; + const ClangDiagnosticConfig &configWithId(const Core::Id &id) const; + +private: + int indexOfConfig(const Core::Id &id) const; + +private: + ClangDiagnosticConfigs m_diagnosticConfigs; +}; + +} // namespace Internal +} // namespace CppTools diff --git a/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp b/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp new file mode 100644 index 0000000000..fbecf04972 --- /dev/null +++ b/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "clangdiagnosticconfigswidget.h" +#include "ui_clangdiagnosticconfigswidget.h" + +#include +#include + +#include +#include +#include + +namespace CppTools { +namespace Internal { + +ClangDiagnosticConfigsWidget::ClangDiagnosticConfigsWidget( + const ClangDiagnosticConfigs &customConfigs, + const Core::Id &configToSelect, + QWidget *parent) + : QWidget(parent) + , m_ui(new Ui::ClangDiagnosticConfigsWidget) + , m_diagnosticConfigsModel(customConfigs) +{ + m_ui->setupUi(this); + + connect(m_ui->configChooserComboBox, + static_cast(&QComboBox::currentIndexChanged), + this, + &ClangDiagnosticConfigsWidget::onCurrentConfigChanged); + connect(m_ui->copyButton, &QPushButton::clicked, + this, &ClangDiagnosticConfigsWidget::onCopyButtonClicked); + connect(m_ui->removeButton, &QPushButton::clicked, + this, &ClangDiagnosticConfigsWidget::onRemoveButtonClicked); + connect(m_ui->diagnosticOptionsTextEdit->document(), &QTextDocument::contentsChanged, + this, &ClangDiagnosticConfigsWidget::onDiagnosticOptionsEdited); + + syncWidgetsToModel(configToSelect); +} + +ClangDiagnosticConfigsWidget::~ClangDiagnosticConfigsWidget() +{ + delete m_ui; +} + +void ClangDiagnosticConfigsWidget::onCurrentConfigChanged(int) +{ + syncOtherWidgetsToComboBox(); +} + +static ClangDiagnosticConfig createCustomConfig(const ClangDiagnosticConfig &config, + const QString &displayName) +{ + ClangDiagnosticConfig copied = config; + copied.setId(Core::Id::fromString(QUuid::createUuid().toString())); + copied.setDisplayName(displayName); + copied.setIsReadOnly(false); + + return copied; +} + +void ClangDiagnosticConfigsWidget::onCopyButtonClicked() +{ + const ClangDiagnosticConfig &config = currentConfig(); + + bool diaglogAccepted = false; + const QString newName = QInputDialog::getText(this, + tr("Copy Diagnostic Configuration"), + tr("Diagnostic configuration name:"), + QLineEdit::Normal, + tr("%1 (Copy)").arg(config.displayName()), + &diaglogAccepted); + if (diaglogAccepted) { + const ClangDiagnosticConfig customConfig = createCustomConfig(config, newName); + m_diagnosticConfigsModel.appendOrUpdate(customConfig); + + syncConfigChooserToModel(customConfig.id()); + m_ui->diagnosticOptionsTextEdit->setFocus(); + } +} + +void ClangDiagnosticConfigsWidget::onRemoveButtonClicked() +{ + m_diagnosticConfigsModel.removeConfigWithId(currentConfigId()); + + syncConfigChooserToModel(); +} + +void ClangDiagnosticConfigsWidget::onDiagnosticOptionsEdited() +{ + const QString diagnosticOptions + = m_ui->diagnosticOptionsTextEdit->document()->toPlainText().trimmed(); + const QStringList updatedCommandLine + = diagnosticOptions.trimmed().split(QLatin1Char(' '), QString::SkipEmptyParts); + + ClangDiagnosticConfig updatedConfig = currentConfig(); + updatedConfig.setCommandLineOptions(updatedCommandLine); + + m_diagnosticConfigsModel.appendOrUpdate(updatedConfig); +} + +void ClangDiagnosticConfigsWidget::syncWidgetsToModel(const Core::Id &configToSelect) +{ + syncConfigChooserToModel(configToSelect); + syncOtherWidgetsToComboBox(); +} + +static QString adaptedDisplayName(const ClangDiagnosticConfig &config) +{ + return config.isReadOnly() + ? QObject::tr("%1 [built-in]").arg(config.displayName()) + : config.displayName(); +} + +void ClangDiagnosticConfigsWidget::syncConfigChooserToModel(const Core::Id &configToSelect) +{ + m_ui->configChooserComboBox->clear(); + int currentIndex = -1; + + const int size = m_diagnosticConfigsModel.size(); + for (int i = 0; i < size; ++i) { + const ClangDiagnosticConfig &config = m_diagnosticConfigsModel.at(i); + m_ui->configChooserComboBox->addItem(adaptedDisplayName(config), config.id().toSetting()); + + if (configToSelect == config.id()) + currentIndex = i; + } + + if (currentIndex != -1) + m_ui->configChooserComboBox->setCurrentIndex(currentIndex); +} + +void ClangDiagnosticConfigsWidget::syncOtherWidgetsToComboBox() +{ + if (isConfigChooserEmpty()) + return; + + const ClangDiagnosticConfig &config = currentConfig(); + + // Update main button row + m_ui->removeButton->setEnabled(!config.isReadOnly()); + + // Update child widgets + const QString commandLineOptions = config.commandLineOptions().join(QLatin1Char(' ')); + m_ui->diagnosticOptionsTextEdit->document()->setPlainText(commandLineOptions); + m_ui->diagnosticOptionsTextEdit->setReadOnly(config.isReadOnly()); +} + +bool ClangDiagnosticConfigsWidget::isConfigChooserEmpty() const +{ + return m_ui->configChooserComboBox->count() == 0; +} + +const ClangDiagnosticConfig &ClangDiagnosticConfigsWidget::currentConfig() const +{ + return m_diagnosticConfigsModel.configWithId(currentConfigId()); +} + +Core::Id ClangDiagnosticConfigsWidget::currentConfigId() const +{ + return Core::Id::fromSetting(m_ui->configChooserComboBox->currentData()); +} + +ClangDiagnosticConfigs ClangDiagnosticConfigsWidget::customConfigs() const +{ + const ClangDiagnosticConfigs allConfigs = m_diagnosticConfigsModel.configs(); + + return Utils::filtered(allConfigs, [](const ClangDiagnosticConfig &config){ + return !config.isReadOnly(); + }); +} + +} // Internal namespace +} // CppTools namespace diff --git a/src/plugins/cpptools/clangdiagnosticconfigswidget.h b/src/plugins/cpptools/clangdiagnosticconfigswidget.h new file mode 100644 index 0000000000..2938afd274 --- /dev/null +++ b/src/plugins/cpptools/clangdiagnosticconfigswidget.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "clangdiagnosticconfig.h" +#include "clangdiagnosticconfigsmodel.h" + +#include + +namespace CppTools { +namespace Internal { + +namespace Ui { class ClangDiagnosticConfigsWidget; } + +class ClangDiagnosticConfigsWidget : public QWidget +{ + Q_OBJECT + +public: + explicit ClangDiagnosticConfigsWidget(const ClangDiagnosticConfigs &customConfigs, + const Core::Id &configToSelect, + QWidget *parent = 0); + + Core::Id currentConfigId() const; + ClangDiagnosticConfigs customConfigs() const; + + ~ClangDiagnosticConfigsWidget(); + +private slots: + void onCurrentConfigChanged(int); + void onCopyButtonClicked(); + void onRemoveButtonClicked(); + + void onDiagnosticOptionsEdited(); + +private: + void syncWidgetsToModel(const Core::Id &configToSelect = Core::Id()); + void syncConfigChooserToModel(const Core::Id &configToSelect = Core::Id()); + void syncOtherWidgetsToComboBox(); + + bool isConfigChooserEmpty() const; + const ClangDiagnosticConfig ¤tConfig() const; + +private: + Ui::ClangDiagnosticConfigsWidget *m_ui; + ClangDiagnosticConfigsModel m_diagnosticConfigsModel; +}; + +} // Internal namespace +} // CppTools namespace diff --git a/src/plugins/cpptools/clangdiagnosticconfigswidget.ui b/src/plugins/cpptools/clangdiagnosticconfigswidget.ui new file mode 100644 index 0000000000..60776e5d47 --- /dev/null +++ b/src/plugins/cpptools/clangdiagnosticconfigswidget.ui @@ -0,0 +1,81 @@ + + + CppTools::Internal::ClangDiagnosticConfigsWidget + + + + 0 + 0 + 545 + 300 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Configuration to use: + + + + + + + + 0 + 0 + + + + + + + + Copy... + + + + + + + Remove + + + + + + + + + + + + For appropriate options, consult the GCC or Clang manual pages or the <a href="https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html">GCC online documentation</a>. + + + true + + + + + + + + diff --git a/src/plugins/cpptools/cppcodemodelsettings.cpp b/src/plugins/cpptools/cppcodemodelsettings.cpp index 225bcc417f..246080dc11 100644 --- a/src/plugins/cpptools/cppcodemodelsettings.cpp +++ b/src/plugins/cpptools/cppcodemodelsettings.cpp @@ -24,24 +24,63 @@ ****************************************************************************/ #include "cppcodemodelsettings.h" + +#include "clangdiagnosticconfigsmodel.h" #include "cpptoolsconstants.h" +#include + #include using namespace CppTools; -static QLatin1String cppHeaderMimeType(Constants::CPP_HEADER_MIMETYPE); -static QLatin1String cHeaderMimeType(Constants::C_HEADER_MIMETYPE); -static QLatin1String clangExtraOptionsKey(Constants::CPPTOOLS_EXTRA_CLANG_OPTIONS); +static Core::Id initialClangDiagnosticConfigId() +{ return Core::Id(Constants::CPP_CLANG_BUILTIN_CONFIG_ID_EVERYTHING_WITH_EXCEPTIONS); } + +static CppCodeModelSettings::PCHUsage initialPchUsage() +{ return CppCodeModelSettings::PchUse_None; } + +static QString clangDiagnosticConfigKey() +{ return QStringLiteral("ClangDiagnosticConfig"); } + +static QString clangDiagnosticConfigsArrayKey() +{ return QStringLiteral("ClangDiagnosticConfigs"); } + +static QString clangDiagnosticConfigsArrayIdKey() +{ return QLatin1String("id"); } + +static QString clangDiagnosticConfigsArrayDisplayNameKey() +{ return QLatin1String("displayName"); } + +static QString clangDiagnosticConfigsArrayOptionsKey() +{ return QLatin1String("diagnosticOptions"); } + +static QString pchUsageKey() +{ return QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_PCH_USAGE); } void CppCodeModelSettings::fromSettings(QSettings *s) { s->beginGroup(QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP)); - setExtraClangOptions(s->value(clangExtraOptionsKey, defaultExtraClangOptions()).toStringList()); - - QVariant v = s->value(QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_PCH_USAGE), PchUse_None); - setPCHUsage(static_cast(v.toInt())); + const int size = s->beginReadArray(clangDiagnosticConfigsArrayKey()); + for (int i = 0; i < size; ++i) { + s->setArrayIndex(i); + + ClangDiagnosticConfig config; + config.setId(Core::Id::fromSetting(s->value(clangDiagnosticConfigsArrayIdKey()))); + config.setDisplayName(s->value(clangDiagnosticConfigsArrayDisplayNameKey()).toString()); + config.setCommandLineOptions(s->value(clangDiagnosticConfigsArrayOptionsKey()).toStringList()); + m_clangCustomDiagnosticConfigs.append(config); + } + s->endArray(); + + const Core::Id diagnosticConfigId = Core::Id::fromSetting( + s->value(clangDiagnosticConfigKey(), + initialClangDiagnosticConfigId().toSetting())); + setClangDiagnosticConfigId(diagnosticConfigId); + + const QVariant pchUsageVariant = s->value(pchUsageKey(), initialPchUsage()); + setPCHUsage(static_cast(pchUsageVariant.toInt())); s->endGroup(); emit changed(); @@ -51,39 +90,50 @@ void CppCodeModelSettings::toSettings(QSettings *s) { s->beginGroup(QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP)); - s->setValue(clangExtraOptionsKey, extraClangOptions()); - s->setValue(QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_PCH_USAGE), pchUsage()); + s->beginWriteArray(clangDiagnosticConfigsArrayKey()); + for (int i = 0, size = m_clangCustomDiagnosticConfigs.size(); i < size; ++i) { + const ClangDiagnosticConfig &config = m_clangCustomDiagnosticConfigs.at(i); + + s->setArrayIndex(i); + s->setValue(clangDiagnosticConfigsArrayIdKey(), config.id().toSetting()); + s->setValue(clangDiagnosticConfigsArrayDisplayNameKey(), config.displayName()); + s->setValue(clangDiagnosticConfigsArrayOptionsKey(), config.commandLineOptions()); + } + s->endArray(); + + s->setValue(clangDiagnosticConfigKey(), clangDiagnosticConfigId().toSetting()); + s->setValue(pchUsageKey(), pchUsage()); s->endGroup(); emit changed(); } -QStringList CppCodeModelSettings::defaultExtraClangOptions() +Core::Id CppCodeModelSettings::clangDiagnosticConfigId() const +{ + return m_clangDiagnosticConfigId; +} + +void CppCodeModelSettings::setClangDiagnosticConfigId(const Core::Id &configId) { - return { - QStringLiteral("-Weverything"), - QStringLiteral("-Wno-c++98-compat"), - QStringLiteral("-Wno-c++98-compat-pedantic"), - QStringLiteral("-Wno-unused-macros"), - QStringLiteral("-Wno-newline-eof"), - QStringLiteral("-Wno-exit-time-destructors"), - QStringLiteral("-Wno-global-constructors"), - QStringLiteral("-Wno-gnu-zero-variadic-macro-arguments"), - QStringLiteral("-Wno-documentation"), - QStringLiteral("-Wno-shadow"), - QStringLiteral("-Wno-missing-prototypes"), // Not optimal for C projects. - }; + m_clangDiagnosticConfigId = configId; +} + +const ClangDiagnosticConfig CppCodeModelSettings::clangDiagnosticConfig() const +{ + const Internal::ClangDiagnosticConfigsModel configsModel(m_clangCustomDiagnosticConfigs); + + return configsModel.configWithId(clangDiagnosticConfigId()); } -QStringList CppCodeModelSettings::extraClangOptions() const +ClangDiagnosticConfigs CppCodeModelSettings::clangCustomDiagnosticConfigs() const { - return m_extraClangOptions; + return m_clangCustomDiagnosticConfigs; } -void CppCodeModelSettings::setExtraClangOptions(const QStringList &extraClangOptions) +void CppCodeModelSettings::setClangCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs) { - m_extraClangOptions = extraClangOptions; + m_clangCustomDiagnosticConfigs = configs; } CppCodeModelSettings::PCHUsage CppCodeModelSettings::pchUsage() const diff --git a/src/plugins/cpptools/cppcodemodelsettings.h b/src/plugins/cpptools/cppcodemodelsettings.h index c6deaa43c2..81dab011af 100644 --- a/src/plugins/cpptools/cppcodemodelsettings.h +++ b/src/plugins/cpptools/cppcodemodelsettings.h @@ -28,6 +28,8 @@ #include "cpptools_global.h" +#include "clangdiagnosticconfigsmodel.h" + #include #include @@ -52,9 +54,12 @@ public: void toSettings(QSettings *s); public: - static QStringList defaultExtraClangOptions(); - QStringList extraClangOptions() const; - void setExtraClangOptions(const QStringList &extraClangOptions); + Core::Id clangDiagnosticConfigId() const; + void setClangDiagnosticConfigId(const Core::Id &configId); + const ClangDiagnosticConfig clangDiagnosticConfig() const; + + ClangDiagnosticConfigs clangCustomDiagnosticConfigs() const; + void setClangCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs); PCHUsage pchUsage() const; void setPCHUsage(PCHUsage pchUsage); @@ -64,10 +69,12 @@ public: // for tests signals: void changed(); + void clangDiagnosticConfigIdChanged(); private: - QStringList m_extraClangOptions; PCHUsage m_pchUsage = PchUse_None; + ClangDiagnosticConfigs m_clangCustomDiagnosticConfigs; + Core::Id m_clangDiagnosticConfigId; }; } // namespace CppTools diff --git a/src/plugins/cpptools/cppcodemodelsettingspage.cpp b/src/plugins/cpptools/cppcodemodelsettingspage.cpp index 93206b39b3..95d4d93346 100644 --- a/src/plugins/cpptools/cppcodemodelsettingspage.cpp +++ b/src/plugins/cpptools/cppcodemodelsettingspage.cpp @@ -24,6 +24,8 @@ ****************************************************************************/ #include "cppcodemodelsettingspage.h" + +#include "clangdiagnosticconfigswidget.h" #include "cppmodelmanager.h" #include "cpptoolsconstants.h" #include "ui_cppcodemodelsettingspage.h" @@ -43,10 +45,6 @@ CppCodeModelSettingsWidget::CppCodeModelSettingsWidget(QWidget *parent) m_ui->setupUi(this); m_ui->clangSettingsGroupBox->setVisible(true); - connect(m_ui->clangOptionsResetButton, &QPushButton::clicked, [this]() { - const QString options = m_settings->defaultExtraClangOptions().join(QLatin1Char('\n')); - m_ui->clangOptionsToAppendTextEdit->document()->setPlainText(options); - }); } CppCodeModelSettingsWidget::~CppCodeModelSettingsWidget() @@ -73,15 +71,17 @@ void CppCodeModelSettingsWidget::applyToSettings() const m_settings->toSettings(Core::ICore::settings()); } -void CppCodeModelSettingsWidget::setupClangCodeModelWidgets() const +void CppCodeModelSettingsWidget::setupClangCodeModelWidgets() { const bool isClangActive = CppModelManager::instance()->isClangCodeModelActive(); m_ui->activateClangCodeModelPluginHint->setVisible(!isClangActive); m_ui->clangSettingsGroupBox->setEnabled(isClangActive); - const QString extraClangOptions = m_settings->extraClangOptions().join(QLatin1Char('\n')); - m_ui->clangOptionsToAppendTextEdit->document()->setPlainText(extraClangOptions); + m_clangDiagnosticConfigsWidget = new ClangDiagnosticConfigsWidget( + m_settings->clangCustomDiagnosticConfigs(), + m_settings->clangDiagnosticConfigId()); + m_ui->clangSettingsGroupBox->layout()->addWidget(m_clangDiagnosticConfigsWidget); } void CppCodeModelSettingsWidget::setupPchCheckBox() const @@ -94,12 +94,18 @@ bool CppCodeModelSettingsWidget::applyClangCodeModelWidgetsToSettings() const { bool settingsChanged = false; - const QStringList previousOptions = m_settings->extraClangOptions(); - const QString newOptionsAsString = m_ui->clangOptionsToAppendTextEdit->document()->toPlainText(); - const QStringList newOptions = newOptionsAsString.split(QLatin1Char('\n'), - QString::SkipEmptyParts); - if (newOptions != previousOptions) { - m_settings->setExtraClangOptions(newOptions); + const Core::Id oldConfigId = m_settings->clangDiagnosticConfigId(); + const Core::Id currentConfigId = m_clangDiagnosticConfigsWidget->currentConfigId(); + if (oldConfigId != currentConfigId) { + m_settings->setClangDiagnosticConfigId(currentConfigId); + settingsChanged = true; + } + + const ClangDiagnosticConfigs oldDiagnosticConfigs = m_settings->clangCustomDiagnosticConfigs(); + const ClangDiagnosticConfigs currentDiagnosticConfigs + = m_clangDiagnosticConfigsWidget->customConfigs(); + if (oldDiagnosticConfigs != currentDiagnosticConfigs) { + m_settings->setClangCustomDiagnosticConfigs(currentDiagnosticConfigs); settingsChanged = true; } diff --git a/src/plugins/cpptools/cppcodemodelsettingspage.h b/src/plugins/cpptools/cppcodemodelsettingspage.h index 5a9df7dbe3..6462d634c9 100644 --- a/src/plugins/cpptools/cppcodemodelsettingspage.h +++ b/src/plugins/cpptools/cppcodemodelsettingspage.h @@ -39,6 +39,8 @@ QT_FORWARD_DECLARE_CLASS(QSettings) namespace CppTools { namespace Internal { +class ClangDiagnosticConfigsWidget; + namespace Ui { class CppCodeModelSettingsPage; } class CppCodeModelSettingsWidget: public QWidget @@ -53,7 +55,7 @@ public: void applyToSettings() const; private: - void setupClangCodeModelWidgets() const; + void setupClangCodeModelWidgets(); void setupPchCheckBox() const; bool applyClangCodeModelWidgetsToSettings() const; @@ -61,6 +63,7 @@ private: private: Ui::CppCodeModelSettingsPage *m_ui; + QPointer m_clangDiagnosticConfigsWidget; QSharedPointer m_settings; }; diff --git a/src/plugins/cpptools/cppcodemodelsettingspage.ui b/src/plugins/cpptools/cppcodemodelsettingspage.ui index 913b505e7a..974f0f6b6e 100644 --- a/src/plugins/cpptools/cppcodemodelsettingspage.ui +++ b/src/plugins/cpptools/cppcodemodelsettingspage.ui @@ -24,47 +24,12 @@ - Clang Code Model + Clang Code Model Warnings false - - - - - Append additional command line options to Clang, one per line. <i>Use this with care.</i> - - - - - - - - - - - - Reset Options - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - + diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro index 67e8d16571..f98a85cde8 100644 --- a/src/plugins/cpptools/cpptools.pro +++ b/src/plugins/cpptools/cpptools.pro @@ -9,6 +9,9 @@ HEADERS += \ builtineditordocumentparser.h \ builtineditordocumentprocessor.h \ builtinindexingsupport.h \ + clangdiagnosticconfig.h \ + clangdiagnosticconfigsmodel.h \ + clangdiagnosticconfigswidget.h \ commentssettings.h \ completionsettingspage.h \ cppchecksymbols.h \ @@ -84,6 +87,9 @@ SOURCES += \ builtineditordocumentparser.cpp \ builtineditordocumentprocessor.cpp \ builtinindexingsupport.cpp \ + clangdiagnosticconfig.cpp \ + clangdiagnosticconfigsmodel.cpp \ + clangdiagnosticconfigswidget.cpp \ commentssettings.cpp \ completionsettingspage.cpp \ cppchecksymbols.cpp \ @@ -149,6 +155,7 @@ SOURCES += \ compileroptionsbuilder.cpp FORMS += \ + clangdiagnosticconfigswidget.ui \ completionsettingspage.ui \ cppcodemodelsettingspage.ui \ cppcodestylesettingspage.ui \ diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs index f424237957..84ff91f800 100644 --- a/src/plugins/cpptools/cpptools.qbs +++ b/src/plugins/cpptools/cpptools.qbs @@ -31,6 +31,10 @@ QtcPlugin { "builtineditordocumentparser.cpp", "builtineditordocumentparser.h", "builtineditordocumentprocessor.cpp", "builtineditordocumentprocessor.h", "builtinindexingsupport.cpp", "builtinindexingsupport.h", + "clangdiagnosticconfig.cpp", "clangdiagnosticconfig.h", + "clangdiagnosticconfigsmodel.cpp", "clangdiagnosticconfigsmodel.h", + "clangdiagnosticconfigswidget.cpp", "clangdiagnosticconfigswidget.h", + "clangdiagnosticconfigswidget.ui", "compileroptionsbuilder.cpp", "compileroptionsbuilder.h", "commentssettings.cpp", "commentssettings.h", "completionsettingspage.cpp", "completionsettingspage.h", "completionsettingspage.ui", diff --git a/src/plugins/cpptools/cpptoolsconstants.h b/src/plugins/cpptools/cpptoolsconstants.h index 37e8acb601..90a62b8f71 100644 --- a/src/plugins/cpptools/cpptoolsconstants.h +++ b/src/plugins/cpptools/cpptoolsconstants.h @@ -49,7 +49,8 @@ const char LOWERCASE_CPPFILES_KEY[] = "LowerCaseFiles"; enum { lowerCaseFilesDefault = 1 }; const char CPPTOOLS_SORT_EDITOR_DOCUMENT_OUTLINE[] = "SortedMethodOverview"; const char CPPTOOLS_MODEL_MANAGER_PCH_USAGE[] = "PCHUsage"; -const char CPPTOOLS_EXTRA_CLANG_OPTIONS[] = "ExtraClangOptions"; + +const char CPP_CLANG_BUILTIN_CONFIG_ID_EVERYTHING_WITH_EXCEPTIONS[] = "Builtin.EverythingWithExceptions"; const char CPP_CODE_STYLE_SETTINGS_ID[] = "A.Cpp.Code Style"; const char CPP_CODE_STYLE_SETTINGS_NAME[] = QT_TRANSLATE_NOOP("CppTools", "Code Style"); -- GitLab