1//===-- DiagnosticManager.h -------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef lldb_DiagnosticManager_h
10#define lldb_DiagnosticManager_h
11
12#include "lldb/lldb-defines.h"
13#include "lldb/lldb-types.h"
14
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/StringRef.h"
17
18#include <string>
19#include <vector>
20
21namespace lldb_private {
22
23enum DiagnosticOrigin {
24  eDiagnosticOriginUnknown = 0,
25  eDiagnosticOriginLLDB,
26  eDiagnosticOriginClang,
27  eDiagnosticOriginSwift,
28  eDiagnosticOriginLLVM
29};
30
31enum DiagnosticSeverity {
32  eDiagnosticSeverityError,
33  eDiagnosticSeverityWarning,
34  eDiagnosticSeverityRemark
35};
36
37const uint32_t LLDB_INVALID_COMPILER_ID = UINT32_MAX;
38
39class Diagnostic {
40  friend class DiagnosticManager;
41
42public:
43  DiagnosticOrigin getKind() const { return m_origin; }
44
45  static bool classof(const Diagnostic *diag) {
46    DiagnosticOrigin kind = diag->getKind();
47    switch (kind) {
48    case eDiagnosticOriginUnknown:
49    case eDiagnosticOriginLLDB:
50    case eDiagnosticOriginLLVM:
51      return true;
52    case eDiagnosticOriginClang:
53    case eDiagnosticOriginSwift:
54      return false;
55    }
56  }
57
58  Diagnostic(llvm::StringRef message, DiagnosticSeverity severity,
59             DiagnosticOrigin origin, uint32_t compiler_id)
60      : m_message(message), m_severity(severity), m_origin(origin),
61        m_compiler_id(compiler_id) {}
62
63  Diagnostic(const Diagnostic &rhs)
64      : m_message(rhs.m_message), m_severity(rhs.m_severity),
65        m_origin(rhs.m_origin), m_compiler_id(rhs.m_compiler_id) {}
66
67  virtual ~Diagnostic() = default;
68
69  virtual bool HasFixIts() const { return false; }
70
71  DiagnosticSeverity GetSeverity() const { return m_severity; }
72
73  uint32_t GetCompilerID() const { return m_compiler_id; }
74
75  llvm::StringRef GetMessage() const { return m_message; }
76
77  void AppendMessage(llvm::StringRef message,
78                     bool precede_with_newline = true) {
79    if (precede_with_newline)
80      m_message.push_back('\n');
81    m_message.append(message);
82  }
83
84protected:
85  std::string m_message;
86  DiagnosticSeverity m_severity;
87  DiagnosticOrigin m_origin;
88  uint32_t m_compiler_id; // Compiler-specific diagnostic ID
89};
90
91typedef std::vector<std::unique_ptr<Diagnostic>> DiagnosticList;
92
93class DiagnosticManager {
94public:
95  void Clear() {
96    m_diagnostics.clear();
97    m_fixed_expression.clear();
98  }
99
100  const DiagnosticList &Diagnostics() { return m_diagnostics; }
101
102  bool HasFixIts() const {
103    return llvm::any_of(m_diagnostics,
104                        [](const std::unique_ptr<Diagnostic> &diag) {
105                          return diag->HasFixIts();
106                        });
107  }
108
109  void AddDiagnostic(llvm::StringRef message, DiagnosticSeverity severity,
110                     DiagnosticOrigin origin,
111                     uint32_t compiler_id = LLDB_INVALID_COMPILER_ID) {
112    m_diagnostics.emplace_back(
113        std::make_unique<Diagnostic>(message, severity, origin, compiler_id));
114  }
115
116  void AddDiagnostic(std::unique_ptr<Diagnostic> diagnostic) {
117    m_diagnostics.push_back(std::move(diagnostic));
118  }
119
120  size_t Printf(DiagnosticSeverity severity, const char *format, ...)
121      __attribute__((format(printf, 3, 4)));
122  void PutString(DiagnosticSeverity severity, llvm::StringRef str);
123
124  void AppendMessageToDiagnostic(llvm::StringRef str) {
125    if (!m_diagnostics.empty())
126      m_diagnostics.back()->AppendMessage(str);
127  }
128
129  // Returns a string containing errors in this format:
130  //
131  // "error: error text\n
132  // warning: warning text\n
133  // remark text\n"
134  std::string GetString(char separator = '\n');
135
136  void Dump(Log *log);
137
138  const std::string &GetFixedExpression() { return m_fixed_expression; }
139
140  // Moves fixed_expression to the internal storage.
141  void SetFixedExpression(std::string fixed_expression) {
142    m_fixed_expression = std::move(fixed_expression);
143  }
144
145protected:
146  DiagnosticList m_diagnostics;
147  std::string m_fixed_expression;
148};
149}
150
151#endif /* lldb_DiagnosticManager_h */
152