diagnostic_emitter.h 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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 DIAGNOSTICS_DIAGNOSTICEMITTER_H_
  5. #define DIAGNOSTICS_DIAGNOSTICEMITTER_H_
  6. #include <functional>
  7. #include <string>
  8. #include "llvm/ADT/Any.h"
  9. #include "llvm/ADT/STLExtras.h"
  10. #include "llvm/ADT/SmallVector.h"
  11. #include "llvm/ADT/StringRef.h"
  12. #include "llvm/Support/raw_ostream.h"
  13. namespace Carbon {
  14. // An instance of a single error or warning. Information about the diagnostic
  15. // can be recorded into it for more complex consumers.
  16. //
  17. // TODO: turn this into a much more reasonable API when we add some actual
  18. // uses of it.
  19. struct Diagnostic {
  20. llvm::StringRef short_name;
  21. std::string message;
  22. };
  23. // Manages the creation of reports, the testing if diagnostics are enabled, and
  24. // the collection of reports.
  25. class DiagnosticEmitter {
  26. public:
  27. using Callback = std::function<void(const Diagnostic&)>;
  28. explicit DiagnosticEmitter(Callback callback)
  29. : callback_(std::move(callback)) {}
  30. ~DiagnosticEmitter() {}
  31. // Emits an error unconditionally. `F` is guaranteed to be called.
  32. template <typename DiagnosticT>
  33. void EmitError(
  34. llvm::function_ref<void(typename DiagnosticT::Substitutions&)> f) {
  35. typename DiagnosticT::Substitutions substitutions;
  36. f(substitutions);
  37. callback_({.short_name = DiagnosticT::ShortName,
  38. .message = DiagnosticT::Format(substitutions)});
  39. }
  40. // Emits a warning if `F` returns true. `F` may or may not be called if the
  41. // warning is disabled.
  42. template <typename DiagnosticT>
  43. void EmitWarningIf(
  44. llvm::function_ref<bool(typename DiagnosticT::Substitutions&)> f) {
  45. // TODO(kfm): check if this warning is enabled
  46. typename DiagnosticT::Substitutions substitutions;
  47. if (f(substitutions)) {
  48. callback_({.short_name = DiagnosticT::ShortName,
  49. .message = DiagnosticT::Format(substitutions)});
  50. }
  51. }
  52. private:
  53. Callback callback_;
  54. };
  55. inline auto ConsoleDiagnosticEmitter() -> DiagnosticEmitter& {
  56. static auto* emitter = new DiagnosticEmitter(
  57. [](const Diagnostic& d) { llvm::errs() << d.message << "\n"; });
  58. return *emitter;
  59. }
  60. inline auto NullDiagnosticEmitter() -> DiagnosticEmitter& {
  61. static auto* emitter = new DiagnosticEmitter([](const Diagnostic&) {});
  62. return *emitter;
  63. }
  64. } // namespace Carbon
  65. #endif // DIAGNOSTICS_DIAGNOSTICEMITTER_H_