diagnostic_consumer.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_DIAGNOSTICS_DIAGNOSTIC_CONSUMER_H_
  5. #define CARBON_TOOLCHAIN_DIAGNOSTICS_DIAGNOSTIC_CONSUMER_H_
  6. #include "common/ostream.h"
  7. #include "llvm/ADT/StringRef.h"
  8. #include "toolchain/diagnostics/diagnostic.h"
  9. namespace Carbon {
  10. // Receives diagnostics as they are emitted.
  11. class DiagnosticConsumer {
  12. public:
  13. virtual ~DiagnosticConsumer() = default;
  14. // Handle a diagnostic.
  15. //
  16. // This relies on moves of the Diagnostic. At present, diagnostics are
  17. // allocated on the stack, so their lifetime is that of HandleDiagnostic.
  18. // However, SortingDiagnosticConsumer needs a longer lifetime, until all
  19. // diagnostics have been produced. As a consequence, it needs to either copy
  20. // or move the Diagnostic, and right now we're moving due to the overhead of
  21. // notes.
  22. //
  23. // At present, there is no persistent storage of diagnostics because IDEs
  24. // would be fine with diagnostics being printed immediately and discarded,
  25. // without SortingDiagnosticConsumer. If this becomes a performance issue, we
  26. // may want to investigate alternative ownership models that address both IDE
  27. // and CLI user needs.
  28. virtual auto HandleDiagnostic(Diagnostic diagnostic) -> void = 0;
  29. // Flushes any buffered input.
  30. virtual auto Flush() -> void {}
  31. };
  32. // A diagnostic consumer that prints to a stream.
  33. class StreamDiagnosticConsumer : public DiagnosticConsumer {
  34. public:
  35. explicit StreamDiagnosticConsumer(llvm::raw_ostream* stream)
  36. : stream_(stream) {}
  37. auto HandleDiagnostic(Diagnostic diagnostic) -> void override;
  38. auto Flush() -> void override { stream_->flush(); }
  39. auto set_stream(llvm::raw_ostream* stream) -> void { stream_ = stream; }
  40. auto set_include_diagnostic_kind(bool value) -> void {
  41. include_diagnostic_kind_ = value;
  42. }
  43. private:
  44. auto Print(const DiagnosticMessage& message, llvm::StringRef prefix) -> void;
  45. llvm::raw_ostream* stream_;
  46. // Whether to include the diagnostic kind when printing.
  47. bool include_diagnostic_kind_ = false;
  48. // Whethere we've printed a diagnostic. Used for printing separators.
  49. bool printed_diagnostic_ = false;
  50. };
  51. // Returns a diagnostic consumer instance that prints to stderr.
  52. auto ConsoleDiagnosticConsumer() -> DiagnosticConsumer&;
  53. // Diagnostic consumer adaptor that tracks whether any errors have been
  54. // produced.
  55. class ErrorTrackingDiagnosticConsumer : public DiagnosticConsumer {
  56. public:
  57. explicit ErrorTrackingDiagnosticConsumer(DiagnosticConsumer& next_consumer)
  58. : next_consumer_(&next_consumer) {}
  59. auto HandleDiagnostic(Diagnostic diagnostic) -> void override {
  60. seen_error_ |= diagnostic.level == DiagnosticLevel::Error;
  61. next_consumer_->HandleDiagnostic(std::move(diagnostic));
  62. }
  63. // Reset whether we've seen an error.
  64. auto Reset() -> void { seen_error_ = false; }
  65. // Returns whether we've seen an error since the last reset.
  66. auto seen_error() const -> bool { return seen_error_; }
  67. private:
  68. DiagnosticConsumer* next_consumer_;
  69. bool seen_error_ = false;
  70. };
  71. } // namespace Carbon
  72. #endif // CARBON_TOOLCHAIN_DIAGNOSTICS_DIAGNOSTIC_CONSUMER_H_