From 679fe69e92f192ef8d3b014dcf7e1624e16c9c77 Mon Sep 17 00:00:00 2001 From: Asher Mancinelli Date: Mon, 5 Apr 2021 09:00:33 -0700 Subject: Apply first pass at diag handler structure --- flang/include/flang/Common/colors.h | 34 ++++++++++++ flang/include/flang/Parser/diagnostics-engine.h | 20 +++++++ flang/include/flang/Parser/message.h | 35 ++++++++---- flang/lib/Parser/message.cpp | 72 ++++++++++++++++++++++--- 4 files changed, 145 insertions(+), 16 deletions(-) create mode 100644 flang/include/flang/Common/colors.h create mode 100644 flang/include/flang/Parser/diagnostics-engine.h diff --git a/flang/include/flang/Common/colors.h b/flang/include/flang/Common/colors.h new file mode 100644 index 000000000000..feb259c22c67 --- /dev/null +++ b/flang/include/flang/Common/colors.h @@ -0,0 +1,34 @@ +//===-- include/flang/Parser/colors.h ---------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Defines colors used for diagnostics. +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_PARSER_COLORS_H_ +#define FORTRAN_PARSER_COLORS_H_ + +#include "llvm/Support/raw_ostream.h" + +namespace Fortran::common { + +static constexpr enum llvm::raw_ostream::Colors noteColor = + llvm::raw_ostream::BLACK; +static constexpr enum llvm::raw_ostream::Colors remarkColor = + llvm::raw_ostream::BLUE; +static constexpr enum llvm::raw_ostream::Colors warningColor = + llvm::raw_ostream::MAGENTA; +static constexpr enum llvm::raw_ostream::Colors errorColor = llvm::raw_ostream::RED; +static constexpr enum llvm::raw_ostream::Colors fatalColor = llvm::raw_ostream::RED; +// Used for changing only the bold attribute. +static constexpr enum llvm::raw_ostream::Colors savedColor = + llvm::raw_ostream::SAVEDCOLOR; + +} // namespace Fortran::common + +#endif \ No newline at end of file diff --git a/flang/include/flang/Parser/diagnostics-engine.h b/flang/include/flang/Parser/diagnostics-engine.h new file mode 100644 index 000000000000..beb03d77aeeb --- /dev/null +++ b/flang/include/flang/Parser/diagnostics-engine.h @@ -0,0 +1,20 @@ +//===-- include/flang/Parser/characters.h -----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_PARSER_CHARACTERS_H_ +#define FORTRAN_PARSER_CHARACTERS_H_ + +namespace Fortran::parser { + +class DiagnosticsEngine { + +}; + +} // namespace Fortran::parser + +#endif \ No newline at end of file diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h index 13f30879dc4f..fbba0b922e01 100644 --- a/flang/include/flang/Parser/message.h +++ b/flang/include/flang/Parser/message.h @@ -29,34 +29,46 @@ namespace Fortran::parser { +enum class DiagnosticLevel { + Note=0, + Remark, + Warning, + Error, + Fatal, +}; + // Use "..."_err_en_US and "..."_en_US literals to define the static // text and fatality of a message. class MessageFixedText { public: constexpr MessageFixedText( - const char str[], std::size_t n, bool isFatal = false) - : text_{str, n}, isFatal_{isFatal} {} + const char str[], std::size_t n, DiagnosticLevel diagnosticLevel = DiagnosticLevel::Remark) + : text_{str, n}, diagnosticLevel_{diagnosticLevel} {} + constexpr MessageFixedText( + const char str[], std::size_t n, bool isFatal) + : text_{str, n}, diagnosticLevel_{isFatal ? DiagnosticLevel::Fatal : DiagnosticLevel::Remark} {} constexpr MessageFixedText(const MessageFixedText &) = default; constexpr MessageFixedText(MessageFixedText &&) = default; constexpr MessageFixedText &operator=(const MessageFixedText &) = default; constexpr MessageFixedText &operator=(MessageFixedText &&) = default; CharBlock text() const { return text_; } - bool isFatal() const { return isFatal_; } + bool isFatal() const { return diagnosticLevel_ == DiagnosticLevel::Fatal; } + DiagnosticLevel GetDiagnosticLevel() const { return diagnosticLevel_; } private: CharBlock text_; - bool isFatal_{false}; + DiagnosticLevel diagnosticLevel_{DiagnosticLevel::Remark}; }; inline namespace literals { constexpr MessageFixedText operator""_en_US(const char str[], std::size_t n) { - return MessageFixedText{str, n, false /* not fatal */}; + return MessageFixedText{str, n, DiagnosticLevel::Remark}; } constexpr MessageFixedText operator""_err_en_US( const char str[], std::size_t n) { - return MessageFixedText{str, n, true /* fatal */}; + return MessageFixedText{str, n, DiagnosticLevel::Fatal}; } } // namespace literals @@ -69,7 +81,7 @@ class MessageFormattedText { public: template MessageFormattedText(const MessageFixedText &text, A &&...x) - : isFatal_{text.isFatal()} { + : diagnosticLevel_{text.GetDiagnosticLevel()} { Format(&text, Convert(std::forward(x))...); } MessageFormattedText(const MessageFormattedText &) = default; @@ -77,7 +89,8 @@ public: MessageFormattedText &operator=(const MessageFormattedText &) = default; MessageFormattedText &operator=(MessageFormattedText &&) = default; const std::string &string() const { return string_; } - bool isFatal() const { return isFatal_; } + bool isFatal() const { return diagnosticLevel_ == DiagnosticLevel::Fatal; } + DiagnosticLevel GetDiagnosticLevel() const { return diagnosticLevel_; } std::string MoveString() { return std::move(string_); } private: @@ -104,7 +117,7 @@ private: std::intmax_t Convert(std::int64_t x) { return x; } std::uintmax_t Convert(std::uint64_t x) { return x; } - bool isFatal_{false}; + DiagnosticLevel diagnosticLevel_{DiagnosticLevel::Remark}; std::string string_; std::forward_list conversions_; // preserves created strings }; @@ -131,6 +144,7 @@ public: MessageExpectedText(MessageExpectedText &&) = default; MessageExpectedText &operator=(const MessageExpectedText &) = default; MessageExpectedText &operator=(MessageExpectedText &&) = default; + DiagnosticLevel GetDiagnosticLevel() const { return DiagnosticLevel::Fatal; } std::string ToString() const; bool Merge(const MessageExpectedText &); @@ -173,6 +187,9 @@ public: bool attachmentIsContext() const { return attachmentIsContext_; } Reference attachment() const { return attachment_; } + DiagnosticLevel GetDiagnosticLevel() const; + void EmitPrefix(llvm::raw_ostream &) const; + std::string GetPrefix() const; void SetContext(Message *c) { attachment_ = c; diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp index d1c29fb76a8d..8baf1de461b3 100644 --- a/flang/lib/Parser/message.cpp +++ b/flang/lib/Parser/message.cpp @@ -8,6 +8,7 @@ #include "flang/Parser/message.h" #include "flang/Common/idioms.h" +#include "flang/Common/colors.h" #include "flang/Parser/char-set.h" #include "llvm/Support/raw_ostream.h" #include @@ -143,16 +144,74 @@ bool Message::SortBefore(const Message &that) const { location_, that.location_); } -bool Message::IsFatal() const { +DiagnosticLevel Message::GetDiagnosticLevel() const { return std::visit( common::visitors{ - [](const MessageExpectedText &) { return true; }, - [](const MessageFixedText &x) { return x.isFatal(); }, - [](const MessageFormattedText &x) { return x.isFatal(); }, + [](const MessageFixedText &t) { return t.GetDiagnosticLevel(); }, + [](const MessageFormattedText &t) { return t.GetDiagnosticLevel(); }, + [](const MessageExpectedText &t) { return t.GetDiagnosticLevel(); }, }, text_); } +std::string Message::GetPrefix() const { + std::string prefix{""}; + switch (GetDiagnosticLevel()) { + case DiagnosticLevel::Note: prefix += "note: "; break; + case DiagnosticLevel::Remark: break; + case DiagnosticLevel::Warning: prefix += "warning: "; break; + case DiagnosticLevel::Error: + case DiagnosticLevel::Fatal: prefix += "error: "; break; + } + return prefix; +} + +void Message::EmitPrefix(llvm::raw_ostream &os) const { + static const bool showColors{false}; + if (showColors) { + // Print diagnostic category in bold and color + switch (GetDiagnosticLevel()) { + case DiagnosticLevel::Note: + os.changeColor(noteColor, true); + break; + case DiagnosticLevel::Remark: + os.changeColor(remarkColor, true); + break; + case DiagnosticLevel::Warning: + os.changeColor(warningColor, true); + break; + case DiagnosticLevel::Error: + os.changeColor(errorColor, true); + break; + case DiagnosticLevel::Fatal: + os.changeColor(fatalColor, true); + break; + } + } + + switch (GetDiagnosticLevel()) { + case DiagnosticLevel::Note: + os << "note: "; + break; + case DiagnosticLevel::Remark: + break; + case DiagnosticLevel::Warning: + os << "warning: "; + break; + case DiagnosticLevel::Error: + case DiagnosticLevel::Fatal: + os << "error: "; + break; + } + + if (showColors) + os.resetColor(); +} + +bool Message::IsFatal() const { + return GetDiagnosticLevel() == DiagnosticLevel::Fatal; +} + std::string Message::ToString() const { return std::visit( common::visitors{ @@ -191,9 +250,8 @@ void Message::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked, bool echoSourceLine) const { std::optional provenanceRange{GetProvenanceRange(allCooked)}; std::string text; - if (IsFatal()) { - text += "error: "; - } + // EmitPrefix(o); + text += GetPrefix(); text += ToString(); const AllSources &sources{allCooked.allSources()}; sources.EmitMessage(o, provenanceRange, text, echoSourceLine); -- cgit v1.2.1