Files
carbon-lang/toolchain/diagnostics/format_providers.cpp
T
Jon Ross-Perkins acbe6530c3 Move diagnostics into a namespace (#5173)
What this really does is avoids shadowing names, so that we can
comfortable have things like `Check::DiagnosticEmitter` or
`Check::DiagnosticLoc` without shadowing being a concern.

Note, down this path I'm also thinking about:

- Renaming misc DiagnosticConsumer/DiagnosticEmitter classes, possibly
just to DiagnosticConsumer/DiagnosticEmitter (so
`Check::DiagnosticEmitter` instead of `SemIRLocDiagnosticEmitter`).
- Dropping `Diagnostic` from `Emitter::DiagnosticBuilder`.
- But not for `Check::DiagnosticBuilder`, because `Check::Builder` would
be ambiguous.
- Renaming diagnostics/diagnostic_* to drop "diagnostic".

[Discussion about SemIRLoc ->
DiagnosticLoc](https://discord.com/channels/655572317891461132/655578254970716160/1353771570463768698)
reminded me of this (in particular the older [Check::DiagnosticBuilder
discussion](https://discord.com/channels/655572317891461132/655578254970716160/1344363562608627763)),
but I'd only do that rename if there's matching consensus about a path
forward where we keep SemIRLoc, and in a way that it's only ever used
for diagnostics (the divergence from which is at the root of current
LocId discussion).

I'm trying to keep that separate from a namespace addition for clarity.
2025-03-26 19:12:10 +00:00

88 lines
2.7 KiB
C++

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "toolchain/diagnostics/format_providers.h"
#include "common/check.h"
#include "llvm/ADT/StringExtras.h"
auto llvm::format_provider<Carbon::Diagnostics::BoolAsSelect>::format(
const Carbon::Diagnostics::BoolAsSelect& wrapper, raw_ostream& out,
StringRef style) -> void {
if (style.empty()) {
llvm::format_provider<bool>::format(wrapper.value, out, style);
return;
}
auto sep = style.find('|');
CARBON_CHECK(
sep != llvm::StringRef::npos,
"BoolAsSelect requires a `|` separating true and false results: `{0}`",
style);
CARBON_CHECK(style.find('|', sep + 1) == llvm::StringRef::npos,
"BoolAsSelect only allows one `|`: `{0}`", style);
if (wrapper.value) {
out << style.take_front(sep);
} else {
out << style.drop_front(sep + 1);
}
}
auto llvm::format_provider<Carbon::Diagnostics::IntAsSelect>::format(
const Carbon::Diagnostics::IntAsSelect& wrapper, raw_ostream& out,
StringRef style) -> void {
if (style == "s") {
if (wrapper.value != 1) {
out << "s";
}
return;
} else if (style.empty()) {
llvm::format_provider<int>::format(wrapper.value, out, style);
return;
}
auto cursor = style;
while (!cursor.empty()) {
auto case_sep = cursor.find("|");
auto token = cursor.substr(0, case_sep);
if (case_sep == llvm::StringRef::npos) {
cursor = llvm::StringRef();
} else {
cursor = cursor.drop_front(case_sep + 1);
}
auto pair_sep = token.find(':');
CARBON_CHECK(pair_sep != llvm::StringRef::npos,
"IntAsSelect requires a `:` separating each comparison and "
"output string: `{0}`",
style);
auto comp = token.take_front(pair_sep);
auto output_string = token.drop_front(pair_sep + 1);
if (comp.empty()) {
// Default case.
CARBON_CHECK(cursor.empty(),
"IntAsSelect requires the default case be last: `{0}`",
style);
out << output_string;
return;
} else if (comp.consume_front("=")) {
// Equality comparison.
int value;
CARBON_CHECK(to_integer(comp, value),
"IntAsSelect has invalid value in comparison: `{0}`", style);
if (value == wrapper.value) {
out << output_string;
return;
}
} else {
CARBON_FATAL("IntAsSelect has unrecognized comparison: `{0}`", style);
}
}
CARBON_FATAL("IntAsSelect doesn't handle `{0}`: `{1}`", wrapper.value, style);
}