blob: 50d3c02b32383ba296a93c81f985b2d2b718f3b4 [file]
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmDiagnostics.h"
#include <cassert>
#include <map>
#include <string>
#include <utility>
#include <cmext/string_view>
#include "cmStringAlgorithms.h"
namespace {
#if __cplusplus >= 201703L
constexpr unsigned validateDiagnosticsSubtree(unsigned parent, unsigned index)
{
// Ensure that all diagnostics, starting from the specified index, have the
// specified parent as an ancestor. Return the first index that violates
// this condition.
while (index < cmDiagnostics::CategoryCount &&
cmDiagnostics::CategoryInfo[index].Parent == parent) {
unsigned const child = index;
// For each diagnostic, 'consume' its children (if any).
index = validateDiagnosticsSubtree(child, ++index);
}
return index;
}
static_assert(validateDiagnosticsSubtree(cmDiagnostics::CMD_NONE, 1) ==
cmDiagnostics::CategoryCount,
"Diagnostics are not properly ordered"
" (hint: LHS is the index of the first misordered diagnostic)");
#endif
cm::optional<cmDiagnosticCategory> stringToCategory(cm::string_view input)
{
using Map = std::map<cm::string_view, cmDiagnosticCategory>;
static Map const mapping = {
#define CATEGORY_MAP(C) { #C ""_s, cmDiagnostics::C },
CM_FOR_EACH_DIAGNOSTIC_CATEGORY(CATEGORY_MAP)
#undef CATEGORY_MAP
};
assert(!input.empty());
if (input.size() >= 4 && cmHasLiteralPrefix(input, "CMD_")) {
auto const i = mapping.find(input);
if (i != mapping.end()) {
return i->second;
}
}
return cm::nullopt;
}
}
#if __cplusplus < 201703L
// Prior to C++17, the compiler is unhappy if this member doesn't have explicit
// storage... and clang-tidy is unhappy if it does.
// NOLINTNEXTLINE(*-redundant-declaration)
constexpr cmDiagnostics::DiagnosticCategoryInformation
cmDiagnostics::CategoryInfo[cmDiagnostics::CategoryCount];
#endif
cm::string_view cmDiagnostics::GetActionString(DiagnosticAction action)
{
switch (action) {
case Ignore:
return "IGNORE"_s;
case Warn:
return "WARN"_s;
case SendError:
return "SEND_ERROR"_s;
case FatalError:
return "FATAL_ERROR"_s;
default:
return {};
}
}
cm::string_view cmDiagnostics::GetCategoryString(DiagnosticCategory category)
{
static cm::string_view const names[CategoryCount] = {
{}, // CMD_NONE
#define CATEGORY_NAME(C) #C ""_s,
CM_FOR_EACH_DIAGNOSTIC_CATEGORY(CATEGORY_NAME)
#undef CATEGORY_MAP
};
if (category < CategoryCount) {
return names[category];
}
return {};
}
cm::optional<cmDiagnosticAction> cmDiagnostics::GetDiagnosticAction(
cm::string_view name)
{
if (name == "IGNORE"_s) {
return DiagnosticAction::Ignore;
}
if (name == "WARN"_s) {
return DiagnosticAction::Warn;
}
if (name == "SEND_ERROR"_s) {
return DiagnosticAction::SendError;
}
if (name == "FATAL_ERROR"_s) {
return DiagnosticAction::FatalError;
}
return cm::nullopt;
}
cm::optional<cmDiagnosticCategory> cmDiagnostics::GetDiagnosticCategory(
cm::string_view name)
{
return stringToCategory(name);
}