Diagnostics: Overhaul warnings in cmake-gui

Replace the old (and poorly designed) mechanisms for altering warnings
in cmake-gui with a new warning tree that adaptively handles all
diagnostic categories that are defined.
This commit is contained in:
Matthew Woehlke
2026-03-05 13:57:08 -05:00
parent ca5d569524
commit e0b0ac4295
7 changed files with 146 additions and 282 deletions

View File

@@ -190,9 +190,6 @@ CMakeSetupDialog::CMakeSetupDialog()
a = OptionsMenu->addAction(tr("Warning Messages..."));
QObject::connect(a, &QAction::triggered, this,
&CMakeSetupDialog::doWarningMessagesDialog);
this->WarnUninitializedAction =
OptionsMenu->addAction(tr("&Warn Uninitialized (--warn-uninitialized)"));
this->WarnUninitializedAction->setCheckable(true);
QAction* debugAction = OptionsMenu->addAction(tr("&Debug Output"));
debugAction->setCheckable(true);
@@ -341,13 +338,6 @@ void CMakeSetupDialog::initialize()
QObject::connect(this->Environment, &QAbstractButton::clicked, this,
&CMakeSetupDialog::editEnvironment);
QObject::connect(this->WarnUninitializedAction, &QAction::triggered,
this->CMakeThread->cmakeInstance(),
&QCMake::setWarnUninitializedMode);
QObject::connect(this->CMakeThread->cmakeInstance(),
&QCMake::warnUninitializedModeChanged,
this->WarnUninitializedAction, &QAction::setChecked);
if (!this->SourceDirectory->text().isEmpty() &&
!this->DeferredPreset.isNull()) {
this->onSourceDirectoryChanged(this->SourceDirectory->text());

View File

@@ -119,7 +119,6 @@ protected:
QAction* ExitAction;
QAction* ConfigureAction;
QAction* GenerateAction;
QAction* WarnUninitializedAction;
QAction* InstallForCommandLineAction;
State CurrentState;
QString DeferredPreset;

View File

@@ -30,7 +30,6 @@ QCMake::QCMake(QObject* p)
, StartEnvironment(QProcessEnvironment::systemEnvironment())
, Environment(QProcessEnvironment::systemEnvironment())
{
this->WarnUninitializedMode = false;
qRegisterMetaType<QCMakeProperty>();
qRegisterMetaType<QCMakePropertyList>();
qRegisterMetaType<QProcessEnvironment>();
@@ -241,8 +240,6 @@ void QCMake::configure()
this->CMakeInstance->SetGeneratorPlatform(this->Platform.toStdString());
this->CMakeInstance->SetGeneratorToolset(this->Toolset.toStdString());
this->CMakeInstance->LoadCache();
// FIXME
// this->CMakeInstance->SetWarnUninitialized(this->WarnUninitializedMode);
this->CMakeInstance->PreLoadCMakeFiles();
InterruptFlag = 0;
@@ -651,66 +648,17 @@ bool QCMake::getDebugOutput() const
return this->CMakeInstance->GetDebugOutput();
}
bool QCMake::getSuppressDevWarnings()
void QCMake::setDiagnosticAction(cmDiagnostics::DiagnosticCategory category,
cmDiagnostics::DiagnosticAction action)
{
cmDiagnosticAction const action =
this->CMakeInstance->GetCurrentSnapshot().GetDiagnostic(
cmDiagnostics::CMD_AUTHOR);
return action == cmDiagnostics::Ignore;
this->CMakeInstance->GetCurrentSnapshot().SetDiagnostic(category, action,
false);
}
void QCMake::setSuppressDevWarnings(bool value)
cmDiagnosticAction QCMake::getDiagnosticAction(
cmDiagnosticCategory category) const
{
// FIXME
// this->CMakeInstance->GetCurrentSnapshot().DemoteDiagnostic();
// SetSuppressDevWarnings(value);
}
bool QCMake::getSuppressDeprecatedWarnings()
{
cmDiagnosticAction const action =
this->CMakeInstance->GetCurrentSnapshot().GetDiagnostic(
cmDiagnostics::CMD_DEPRECATED);
return action == cmDiagnostics::Ignore;
}
void QCMake::setSuppressDeprecatedWarnings(bool value)
{
// FIXME
// this->CMakeInstance->SetSuppressDeprecatedWarnings(value);
}
bool QCMake::getDevWarningsAsErrors()
{
cmDiagnosticAction const action =
this->CMakeInstance->GetCurrentSnapshot().GetDiagnostic(
cmDiagnostics::CMD_AUTHOR);
return action >= cmDiagnostics::SendError;
}
void QCMake::setDevWarningsAsErrors(bool value)
{
// FIXME
// this->CMakeInstance->SetDevWarningsAsErrors(value);
}
bool QCMake::getDeprecatedWarningsAsErrors()
{
cmDiagnosticAction const action =
this->CMakeInstance->GetCurrentSnapshot().GetDiagnostic(
cmDiagnostics::CMD_DEPRECATED);
return action >= cmDiagnostics::SendError;
}
void QCMake::setDeprecatedWarningsAsErrors(bool value)
{
// FIXME
// this->CMakeInstance->SetDeprecatedWarningsAsErrors(value);
}
void QCMake::setWarnUninitializedMode(bool value)
{
this->WarnUninitializedMode = value;
return this->CMakeInstance->GetCurrentSnapshot().GetDiagnostic(category);
}
void QCMake::checkOpenPossible()

View File

@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmCMakePresetsGraph.h"
#include "cmDiagnostics.h"
#include "cmake.h"
#ifdef _MSC_VER
@@ -105,24 +106,9 @@ public slots:
void reloadCache();
/// set whether to do debug output
void setDebugOutput(bool);
/// get whether to do suppress dev warnings
bool getSuppressDevWarnings();
/// set whether to do suppress dev warnings
void setSuppressDevWarnings(bool value);
/// get whether to do suppress deprecated warnings
bool getSuppressDeprecatedWarnings();
/// set whether to do suppress deprecated warnings
void setSuppressDeprecatedWarnings(bool value);
/// get whether to treat developer (author) warnings as errors
bool getDevWarningsAsErrors();
/// set whether to treat developer (author) warnings as errors
void setDevWarningsAsErrors(bool value);
/// get whether to treat deprecated warnings as errors
bool getDeprecatedWarningsAsErrors();
/// set whether to treat deprecated warnings as errors
void setDeprecatedWarningsAsErrors(bool value);
/// set whether to run cmake with warnings about uninitialized variables
void setWarnUninitializedMode(bool value);
/// set diagnostic action
void setDiagnosticAction(cmDiagnostics::DiagnosticCategory,
cmDiagnostics::DiagnosticAction);
/// check if project IDE open is possible and emit openPossible signal
void checkOpenPossible();
/// Reload the preset files and tree
@@ -145,6 +131,8 @@ public:
std::vector<cmake::GeneratorInfo> const& availableGenerators() const;
/// get whether to do debug output
bool getDebugOutput() const;
/// get diagnostic action
cmDiagnosticAction getDiagnosticAction(cmDiagnosticCategory) const;
signals:
/// signal when properties change (during read from disk or configure
@@ -163,8 +151,6 @@ signals:
void presetChanged(QString const& name);
/// signal when there's an error reading the presets files
void presetLoadError(QString const& dir, QString const& error);
/// signal when uninitialized warning changes
void warnUninitializedModeChanged(bool value);
/// signal for progress events
void progressChanged(QString const& msg, float percent);
/// signal when configure is done
@@ -196,7 +182,6 @@ protected:
void stderrCallback(std::string const& msg);
void setUpEnvironment() const;
bool WarnUninitializedMode;
QString SourceDirectory;
QString BinaryDirectory;
QString MaybeRelativeBinaryDirectory;

View File

@@ -2,6 +2,20 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "WarningMessagesDialog.h"
#include "cm/string_view"
#include <QButtonGroup>
#include <QHeaderView>
#include <QRadioButton>
#include <QToolButton>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include "cmDiagnostics.h"
#include "QCMake.h"
#include "QCMakeSizeType.h"
WarningMessagesDialog::WarningMessagesDialog(QWidget* prnt, QCMake* instance)
: QDialog(prnt)
, cmakeInstance(instance)
@@ -13,84 +27,83 @@ WarningMessagesDialog::WarningMessagesDialog(QWidget* prnt, QCMake* instance)
void WarningMessagesDialog::setInitialValues()
{
this->suppressDeveloperWarnings->setChecked(
this->cmakeInstance->getSuppressDevWarnings());
this->suppressDeprecatedWarnings->setChecked(
this->cmakeInstance->getSuppressDeprecatedWarnings());
QHeaderView* const header = this->treeWidget->header();
header->setSectionResizeMode(0, QHeaderView::Stretch);
header->setSectionResizeMode(1, QHeaderView::ResizeToContents);
header->setSectionResizeMode(2, QHeaderView::ResizeToContents);
header->setSectionResizeMode(3, QHeaderView::ResizeToContents);
this->developerWarningsAsErrors->setChecked(
this->cmakeInstance->getDevWarningsAsErrors());
this->deprecatedWarningsAsErrors->setChecked(
this->cmakeInstance->getDeprecatedWarningsAsErrors());
std::map<unsigned, QTreeWidgetItem*> items = {
{ 0, this->treeWidget->invisibleRootItem() },
};
for (unsigned i = 1; i < cmDiagnostics::CategoryCount; ++i) {
auto const category = static_cast<cmDiagnosticCategory>(i);
cm::string_view const cname =
cmDiagnostics::GetCategoryString(category).substr(4);
QTreeWidgetItem* const parent =
items[cmDiagnostics::CategoryInfo[category].Parent];
QTreeWidgetItem* const item = new QTreeWidgetItem(parent);
item->setText(0,
QString::fromUtf8(cname.data(),
static_cast<cm_qsizetype>(cname.size())));
auto makeButton = [](QString const& text) {
QToolButton* const button = new QToolButton;
button->setCheckable(true);
button->setText(text);
return button;
};
QAbstractButton* const ignore = makeButton(tr("Ignore"));
QAbstractButton* const warn = makeButton(tr("Warn"));
QAbstractButton* const error = makeButton(tr("Error"));
QButtonGroup* const buttonGroup = new QButtonGroup(treeWidget);
buttonGroup->addButton(ignore, cmDiagnosticAction::Ignore);
buttonGroup->addButton(warn, cmDiagnosticAction::Warn);
buttonGroup->addButton(error, cmDiagnosticAction::SendError);
buttonGroup->setExclusive(true);
this->buttons.emplace(i, buttonGroup);
treeWidget->setItemWidget(item, 1, ignore);
treeWidget->setItemWidget(item, 2, warn);
treeWidget->setItemWidget(item, 3, error);
cmDiagnosticAction const action =
this->cmakeInstance->getDiagnosticAction(category);
switch (action) {
case cmDiagnostics::SendError:
case cmDiagnostics::FatalError:
error->setChecked(true);
break;
case cmDiagnostics::Warn:
warn->setChecked(true);
break;
default:
ignore->setChecked(true);
break;
}
items.emplace(i, item);
}
for (auto const& ii : items) {
ii.second->setExpanded(true);
}
}
void WarningMessagesDialog::setupSignals()
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
static auto const checkStateChanged = &QCheckBox::checkStateChanged;
#else
static auto const checkStateChanged = &QCheckBox::stateChanged;
#endif
QObject::connect(this->buttonBox, &QDialogButtonBox::accepted, this,
&WarningMessagesDialog::doAccept);
QObject::connect(this->suppressDeveloperWarnings, checkStateChanged, this,
&WarningMessagesDialog::doSuppressDeveloperWarningsChanged);
QObject::connect(
this->suppressDeprecatedWarnings, checkStateChanged, this,
&WarningMessagesDialog::doSuppressDeprecatedWarningsChanged);
QObject::connect(this->developerWarningsAsErrors, checkStateChanged, this,
&WarningMessagesDialog::doDeveloperWarningsAsErrorsChanged);
QObject::connect(
this->deprecatedWarningsAsErrors, checkStateChanged, this,
&WarningMessagesDialog::doDeprecatedWarningsAsErrorsChanged);
}
void WarningMessagesDialog::doAccept()
{
this->cmakeInstance->setSuppressDevWarnings(
this->suppressDeveloperWarnings->isChecked());
this->cmakeInstance->setSuppressDeprecatedWarnings(
this->suppressDeprecatedWarnings->isChecked());
this->cmakeInstance->setDevWarningsAsErrors(
this->developerWarningsAsErrors->isChecked());
this->cmakeInstance->setDeprecatedWarningsAsErrors(
this->deprecatedWarningsAsErrors->isChecked());
}
void WarningMessagesDialog::doSuppressDeveloperWarningsChanged(
CheckState state)
{
// no warnings implies no errors either
if (state) {
this->developerWarningsAsErrors->setChecked(false);
}
}
void WarningMessagesDialog::doSuppressDeprecatedWarningsChanged(
CheckState state)
{
// no warnings implies no errors either
if (state) {
this->deprecatedWarningsAsErrors->setChecked(false);
}
}
void WarningMessagesDialog::doDeveloperWarningsAsErrorsChanged(
CheckState state)
{
// warnings as errors implies warnings are not suppressed
if (state) {
this->suppressDeveloperWarnings->setChecked(false);
}
}
void WarningMessagesDialog::doDeprecatedWarningsAsErrorsChanged(
CheckState state)
{
// warnings as errors implies warnings are not suppressed
if (state) {
this->suppressDeprecatedWarnings->setChecked(false);
for (auto const& ii : this->buttons) {
this->cmakeInstance->setDiagnosticAction(
static_cast<cmDiagnosticCategory>(ii.first),
static_cast<cmDiagnosticAction>(ii.second->checkedId()));
}
}

View File

@@ -2,12 +2,17 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
#include <map>
#include <QDialog>
#include <QWidget>
#include "QCMake.h"
#include "ui_WarningMessagesDialog.h"
class QButtonGroup;
class QCMake;
/**
* Dialog window for setting the warning message related options.
*/
@@ -17,12 +22,6 @@ class WarningMessagesDialog
{
Q_OBJECT
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
using CheckState = Qt::CheckState;
#else
using CheckState = int;
#endif
public:
WarningMessagesDialog(QWidget* prnt, QCMake* instance);
@@ -32,30 +31,9 @@ private slots:
*/
void doAccept();
/**
* Handler for checked state changed event of the suppress developer warnings
* checkbox.
*/
void doSuppressDeveloperWarningsChanged(CheckState state);
/**
* Handler for checked state changed event of the suppress deprecated
* warnings checkbox.
*/
void doSuppressDeprecatedWarningsChanged(CheckState state);
/**
* Handler for checked state changed event of the developer warnings as
* errors checkbox.
*/
void doDeveloperWarningsAsErrorsChanged(CheckState state);
/**
* Handler for checked state changed event of the deprecated warnings as
* errors checkbox.
*/
void doDeprecatedWarningsAsErrorsChanged(CheckState state);
private:
QCMake* cmakeInstance;
std::map<unsigned, QButtonGroup*> buttons;
/**
* Set the initial values of the widgets on this dialog window, using the

View File

@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>300</width>
<width>450</width>
<height>300</height>
</rect>
</property>
@@ -18,103 +18,54 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<widget class="QTreeWidget" name="treeWidget">
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="title">
<string>Suppress Warnings</string>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="suppressDeveloperWarnings">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Suppress developer (author) warnings.</string>
</property>
<property name="text">
<string>Developer Warnings</string>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="suppressDeprecatedWarnings">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Suppress deprecated warnings.</string>
</property>
<property name="text">
<string>Deprecated Warnings</string>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="title">
<string>Warnings as Errors</string>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="developerWarningsAsErrors">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Treat developer (author) warnings as errors.</string>
</property>
<property name="text">
<string>Developer Warnings as Errors</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="deprecatedWarningsAsErrors">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Treat deprecated warnings as errors.</string>
</property>
<property name="text">
<string>Deprecated Warnings as Errors</string>
</property>
</widget>
</item>
</layout>
<property name="itemsExpandable">
<bool>false</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<property name="expandsOnDoubleClick">
<bool>false</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">Category</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">Ignore</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">Warn</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">Error</string>
</property>
</column>
</widget>
</item>
<item>