diff options
author | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2019-01-28 12:40:03 +0100 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2019-02-05 15:22:20 +0000 |
commit | f6c46ce35d9018335a19d8d75fda4dfd7adf69b3 (patch) | |
tree | d996bc810d2486bc2af3eb4bd57795c7195ce0d0 /src/plugins/clangcodemodel | |
parent | b9d3055e7218e6dc202047c4a341df51c8e8cd67 (diff) |
Clang: Add tooltip action to remove specific warnings/checks
...from the diagnostic configuration.
If no custom diagnostic configuration is set in Projects Mode > Clang,
one is created and set for the current project. Otherwise the current
custom diagnostic set in the project settings is modified.
Change-Id: I5c48280c90f0e807e7333122d504dda302a8b0a9
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
Diffstat (limited to 'src/plugins/clangcodemodel')
-rw-r--r-- | src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp | 50 | ||||
-rw-r--r-- | src/plugins/clangcodemodel/clangtextmark.cpp | 123 | ||||
-rw-r--r-- | src/plugins/clangcodemodel/clangutils.cpp | 46 | ||||
-rw-r--r-- | src/plugins/clangcodemodel/clangutils.h | 17 |
4 files changed, 188 insertions, 48 deletions
diff --git a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp index 497af71993..5f85a2e226 100644 --- a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp +++ b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp @@ -25,6 +25,7 @@ #include "clangdiagnostictooltipwidget.h" #include "clangfixitoperation.h" +#include "clangutils.h" #include <coreplugin/editormanager/editormanager.h> @@ -149,7 +150,7 @@ public: QTC_CHECK(!"Link target cannot be handled."); if (hideToolTipAfterLinkActivation) - Utils::ToolTip::hideImmediately(); + ::Utils::ToolTip::hideImmediately(); }); return label; @@ -171,50 +172,6 @@ public: private: enum class IndentMode { Indent, DoNotIndent }; - static bool isClazyOption(const QString &option) { return option.startsWith("-Wclazy"); } - - class DiagnosticTextInfo - { - public: - DiagnosticTextInfo(const QString &text) - : m_text(text) - , m_squareBracketStartIndex(text.lastIndexOf('[')) - {} - - QString textWithoutOption() const - { - if (m_squareBracketStartIndex == -1) - return m_text; - - return m_text.mid(0, m_squareBracketStartIndex - 1); - } - - QString option() const - { - if (m_squareBracketStartIndex == -1) - return QString(); - - const int index = m_squareBracketStartIndex + 1; - return m_text.mid(index, m_text.count() - index - 1); - } - - QString category() const - { - if (m_squareBracketStartIndex == -1) - return QString(); - - const int index = m_squareBracketStartIndex + 1; - if (isClazyOption(m_text.mid(index))) - return QCoreApplication::translate("ClangDiagnosticWidget", "Clazy Issue"); - else - return QCoreApplication::translate("ClangDiagnosticWidget", "Clang-Tidy Issue"); - } - - private: - const QString m_text; - const int m_squareBracketStartIndex; - }; - // Diagnostics from clazy/tidy do not have any category or option set but // we will conclude them from the diagnostic message. // @@ -233,6 +190,7 @@ private: ClangBackEnd::DiagnosticContainer supplementedDiagnostic = diagnostic; + using namespace ClangCodeModel::Utils; DiagnosticTextInfo info(diagnostic.text); supplementedDiagnostic.enableOption = info.option(); supplementedDiagnostic.category = info.category(); @@ -269,7 +227,7 @@ private: QString option = optionAsUtf8String.toString(); // Clazy - if (isClazyOption(option)) { + if (ClangCodeModel::Utils::DiagnosticTextInfo::isClazyOption(option)) { option = optionAsUtf8String.mid(8); // Remove "-Wclazy-" prefix. return QString::fromUtf8(CLAZY_DOCUMENTATION_URL_TEMPLATE).arg(option); } diff --git a/src/plugins/clangcodemodel/clangtextmark.cpp b/src/plugins/clangcodemodel/clangtextmark.cpp index b8dc9a92a4..41ee4c1533 100644 --- a/src/plugins/clangcodemodel/clangtextmark.cpp +++ b/src/plugins/clangcodemodel/clangtextmark.cpp @@ -27,11 +27,20 @@ #include "clangconstants.h" #include "clangdiagnostictooltipwidget.h" +#include "clangeditordocumentprocessor.h" +#include "clangmodelmanagersupport.h" +#include "clangprojectsettings.h" #include "clangutils.h" -#include <utils/utilsicons.h> +#include <coreplugin/icore.h> +#include <cpptools/clangdiagnosticconfigsmodel.h> +#include <cpptools/cpptoolsreuse.h> +#include <cpptools/cppcodemodelsettings.h> + +#include <utils/fadingindicator.h> #include <utils/qtcassert.h> #include <utils/theme/theme.h> +#include <utils/utilsicons.h> #include <QAction> #include <QApplication> @@ -64,6 +73,102 @@ static Core::Id categoryForSeverity(ClangBackEnd::DiagnosticSeverity severity) return isWarningOrNote(severity) ? Constants::CLANG_WARNING : Constants::CLANG_ERROR; } +ProjectExplorer::Project *projectForCurrentEditor() +{ + using namespace CppTools; + using namespace ClangCodeModel::Internal; + + const QString filePath = Utils::currentCppEditorDocumentFilePath(); + if (filePath.isEmpty()) + return nullptr; + + if (auto processor = ClangEditorDocumentProcessor::get(filePath)) { + if (ProjectPart::Ptr projectPart = processor->projectPart()) + return projectPart->project; + } + + return nullptr; +} + +void disableDiagnosticInConfig(CppTools::ClangDiagnosticConfig &config, + const ClangBackEnd::DiagnosticContainer &diagnostic) +{ + // Clang check + if (!diagnostic.disableOption.isEmpty()) { + config.setClangOptions(config.clangOptions() + QStringList(diagnostic.disableOption)); + return; + } + + // Clazy check + using namespace ClangCodeModel::Utils; + DiagnosticTextInfo textInfo(diagnostic.text); + if (DiagnosticTextInfo::isClazyOption(textInfo.option())) { + const QString checkName = DiagnosticTextInfo::clazyCheckName(textInfo.option()); + QStringList newChecks = config.clazyChecks().split(','); + newChecks.removeOne(checkName); + config.setClazyChecks(newChecks.join(',')); + return; + } + + // Tidy check + config.setClangTidyChecks(config.clangTidyChecks() + QString(",-") + textInfo.option()); +} + +void disableDiagnosticInCurrentProjectConfig(const ClangBackEnd::DiagnosticContainer &diagnostic) +{ + using namespace CppTools; + using namespace ClangCodeModel::Internal; + + ProjectExplorer::Project *project = projectForCurrentEditor(); + QTC_ASSERT(project, return ); + + // Get settings + ClangProjectSettings &projectSettings = ClangModelManagerSupport::instance()->projectSettings( + project); + const QSharedPointer<CppCodeModelSettings> globalSettings = codeModelSettings(); + + // Get config id + Core::Id currentConfigId = projectSettings.warningConfigId(); + if (projectSettings.useGlobalConfig()) + currentConfigId = globalSettings->clangDiagnosticConfigId(); + + // Get config + const ClangDiagnosticConfigs originalConfigs = globalSettings->clangCustomDiagnosticConfigs(); + ClangDiagnosticConfigsModel configsModel(globalSettings->clangCustomDiagnosticConfigs()); + QTC_ASSERT(configsModel.hasConfigWithId(currentConfigId), return ); + ClangDiagnosticConfig config = configsModel.configWithId(currentConfigId); + + // Create copy if needed + if (config.isReadOnly()) { + const QString name = QCoreApplication::translate("ClangDiagnosticConfig", + "Project: %1 (based on %2)") + .arg(project->displayName(), config.displayName()); + config = ClangDiagnosticConfigsModel::createCustomConfig(config, name); + } + + // Modify diagnostic config + disableDiagnosticInConfig(config, diagnostic); + configsModel.appendOrUpdate(config); + + // Set global settings + globalSettings->setClangCustomDiagnosticConfigs(configsModel.customConfigs()); + globalSettings->toSettings(Core::ICore::settings()); + + // Set project settings + if (projectSettings.useGlobalConfig()) + projectSettings.setUseGlobalConfig(false); + projectSettings.setWarningConfigId(config.id()); + projectSettings.store(); + + // Notify the user about changed project specific settings + const QString text + = QCoreApplication::translate("ClangDiagnosticConfig", + "Changes applied in Projects Mode > Clang Code Model"); + ::Utils::FadingIndicator::showText(Core::ICore::mainWindow(), + text, + ::Utils::FadingIndicator::SmallText); +} + } // anonymous namespace ClangTextMark::ClangTextMark(const FileName &fileName, @@ -88,6 +193,8 @@ ClangTextMark::ClangTextMark(const FileName &fileName, : ::Utils::Theme::CodeModel_Error_TextMarkColor); } + // Copy to clipboard action + QVector<QAction *> actions; QAction *action = new QAction(); action->setIcon(QIcon::fromTheme("edit-copy", ::Utils::Icons::COPY.icon())); QObject::connect(action, &QAction::triggered, [diagnostic]() { @@ -96,7 +203,19 @@ ClangTextMark::ClangTextMark(const FileName &fileName, ClangDiagnosticWidget::InfoBar); QApplication::clipboard()->setText(text, QClipboard::Clipboard); }); - setActions({action}); + actions << action; + + // Remove diagnostic warning action + if (projectForCurrentEditor()) { + action = new QAction(); + action->setIcon(::Utils::Icons::BROKEN.icon()); + QObject::connect(action, &QAction::triggered, [diagnostic]() { + disableDiagnosticInCurrentProjectConfig(diagnostic); + }); + actions << action; + } + + setActions(actions); } void ClangTextMark::updateIcon(bool valid) diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index 8a27a115a2..481b0774f8 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -373,5 +373,51 @@ QString currentCppEditorDocumentFilePath() return filePath; } +DiagnosticTextInfo::DiagnosticTextInfo(const QString &text) + : m_text(text) + , m_squareBracketStartIndex(text.lastIndexOf('[')) +{} + +QString DiagnosticTextInfo::textWithoutOption() const +{ + if (m_squareBracketStartIndex == -1) + return m_text; + + return m_text.mid(0, m_squareBracketStartIndex - 1); +} + +QString DiagnosticTextInfo::option() const +{ + if (m_squareBracketStartIndex == -1) + return QString(); + + const int index = m_squareBracketStartIndex + 1; + return m_text.mid(index, m_text.count() - index - 1); +} + +QString DiagnosticTextInfo::category() const +{ + if (m_squareBracketStartIndex == -1) + return QString(); + + const int index = m_squareBracketStartIndex + 1; + if (isClazyOption(m_text.mid(index))) + return QCoreApplication::translate("ClangDiagnosticWidget", "Clazy Issue"); + else + return QCoreApplication::translate("ClangDiagnosticWidget", "Clang-Tidy Issue"); +} + +bool DiagnosticTextInfo::isClazyOption(const QString &option) +{ + return option.startsWith("-Wclazy"); +} + +QString DiagnosticTextInfo::clazyCheckName(const QString &option) +{ + if (option.startsWith("-Wclazy")) + return option.mid(8); // Chop "-Wclazy-" + return option; +} + } // namespace Utils } // namespace Clang diff --git a/src/plugins/clangcodemodel/clangutils.h b/src/plugins/clangcodemodel/clangutils.h index b7f705b57b..4db869896b 100644 --- a/src/plugins/clangcodemodel/clangutils.h +++ b/src/plugins/clangcodemodel/clangutils.h @@ -72,6 +72,23 @@ QString diagnosticCategoryPrefixRemoved(const QString &text); void generateCompilationDB(::Utils::FileName projectDir, CppTools::ProjectInfo projectInfo); +class DiagnosticTextInfo +{ +public: + DiagnosticTextInfo(const QString &text); + + QString textWithoutOption() const; + QString option() const; + QString category() const; + + static bool isClazyOption(const QString &option); + static QString clazyCheckName(const QString &option); + +private: + const QString m_text; + const int m_squareBracketStartIndex; +}; + namespace Text { template <class CharacterProvider> |