diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-22 15:33:02 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-22 15:33:15 +0000 |
| commit | 5e84edbe1a79c6a7752ee276ea6c1a4daef4fa8e (patch) | |
| tree | 0d958458a13aea9183b92dfb8b4f767e6d98414b /include/cps | |
| parent | 0e8bc8c3e806796bf3b03e7da6c59ff24e58559f (diff) | |
fix(diagnostics): print each identical diagnostic once
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Diffstat (limited to 'include/cps')
| -rw-r--r-- | include/cps/Diagnostics.h | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/include/cps/Diagnostics.h b/include/cps/Diagnostics.h index 4bcb877..9c9ea37 100644 --- a/include/cps/Diagnostics.h +++ b/include/cps/Diagnostics.h @@ -1,6 +1,7 @@ #pragma once #include <cstdarg> #include <cstdio> +#include <set> #include <string> namespace cps { @@ -30,14 +31,24 @@ inline std::string diagnosticPrefix(Severity S, const std::string &Locus = "cpsc return (Locus.empty() ? "" : Span("01", Locus + ":") + " ") + Span(Color, Label); } +// Every diagnostic line printed so far, to suppress exact repeats. +inline std::set<std::string> PrintedDiagnostics; + // Prints "<path>:<line>: <label>: <message>\n" (just "<path>:" when the line is // unknown, "cpsc:" when no source is set). inline void vsourceDiagnostic(Severity S, int Line, const char *Format, va_list Args) { std::string Locus = DiagnosticSource.empty() ? "cpsc" : DiagnosticSource; if (!DiagnosticSource.empty() && Line > 0) Locus += ":" + std::to_string(Line); - std::fputs(diagnosticPrefix(S, Locus).c_str(), stderr); - std::vfprintf(stderr, Format, Args); - std::fputc('\n', stderr); + va_list Copy; + va_copy(Copy, Args); + int Length = std::vsnprintf(nullptr, 0, Format, Copy); + va_end(Copy); + std::string Message(Length > 0 ? Length : 0, '\0'); + if (Length > 0) std::vsnprintf(Message.data(), Message.size() + 1, Format, Args); + std::string Text = diagnosticPrefix(S, Locus) + Message + '\n'; + // The same node can be diagnosed more than once; print each line once. + if (!PrintedDiagnostics.insert(Text).second) return; + std::fputs(Text.c_str(), stderr); } __attribute__((format(printf, 2, 3))) |
