1303241Sdim//===-- DiagnosticManager.h -------------------------------------*- C++ -*-===//
2303241Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6303241Sdim//
7303241Sdim//===----------------------------------------------------------------------===//
8303241Sdim
9303241Sdim#ifndef lldb_DiagnosticManager_h
10303241Sdim#define lldb_DiagnosticManager_h
11303241Sdim
12303241Sdim#include "lldb/lldb-defines.h"
13303241Sdim#include "lldb/lldb-types.h"
14303241Sdim
15360784Sdim#include "llvm/ADT/STLExtras.h"
16314564Sdim#include "llvm/ADT/StringRef.h"
17314564Sdim
18303241Sdim#include <string>
19303241Sdim#include <vector>
20303241Sdim
21314564Sdimnamespace lldb_private {
22303241Sdim
23314564Sdimenum DiagnosticOrigin {
24314564Sdim  eDiagnosticOriginUnknown = 0,
25314564Sdim  eDiagnosticOriginLLDB,
26314564Sdim  eDiagnosticOriginClang,
27314564Sdim  eDiagnosticOriginSwift,
28314564Sdim  eDiagnosticOriginLLVM
29303241Sdim};
30303241Sdim
31314564Sdimenum DiagnosticSeverity {
32314564Sdim  eDiagnosticSeverityError,
33314564Sdim  eDiagnosticSeverityWarning,
34314564Sdim  eDiagnosticSeverityRemark
35303241Sdim};
36303241Sdim
37303241Sdimconst uint32_t LLDB_INVALID_COMPILER_ID = UINT32_MAX;
38303241Sdim
39314564Sdimclass Diagnostic {
40314564Sdim  friend class DiagnosticManager;
41303241Sdim
42303241Sdimpublic:
43314564Sdim  DiagnosticOrigin getKind() const { return m_origin; }
44314564Sdim
45314564Sdim  static bool classof(const Diagnostic *diag) {
46314564Sdim    DiagnosticOrigin kind = diag->getKind();
47314564Sdim    switch (kind) {
48314564Sdim    case eDiagnosticOriginUnknown:
49314564Sdim    case eDiagnosticOriginLLDB:
50314564Sdim    case eDiagnosticOriginLLVM:
51314564Sdim      return true;
52314564Sdim    case eDiagnosticOriginClang:
53314564Sdim    case eDiagnosticOriginSwift:
54314564Sdim      return false;
55303241Sdim    }
56314564Sdim  }
57303241Sdim
58314564Sdim  Diagnostic(llvm::StringRef message, DiagnosticSeverity severity,
59314564Sdim             DiagnosticOrigin origin, uint32_t compiler_id)
60314564Sdim      : m_message(message), m_severity(severity), m_origin(origin),
61314564Sdim        m_compiler_id(compiler_id) {}
62314564Sdim
63314564Sdim  Diagnostic(const Diagnostic &rhs)
64314564Sdim      : m_message(rhs.m_message), m_severity(rhs.m_severity),
65314564Sdim        m_origin(rhs.m_origin), m_compiler_id(rhs.m_compiler_id) {}
66314564Sdim
67314564Sdim  virtual ~Diagnostic() = default;
68314564Sdim
69314564Sdim  virtual bool HasFixIts() const { return false; }
70314564Sdim
71314564Sdim  DiagnosticSeverity GetSeverity() const { return m_severity; }
72314564Sdim
73314564Sdim  uint32_t GetCompilerID() const { return m_compiler_id; }
74314564Sdim
75314564Sdim  llvm::StringRef GetMessage() const { return m_message; }
76314564Sdim
77314564Sdim  void AppendMessage(llvm::StringRef message,
78314564Sdim                     bool precede_with_newline = true) {
79314564Sdim    if (precede_with_newline)
80314564Sdim      m_message.push_back('\n');
81314564Sdim    m_message.append(message);
82314564Sdim  }
83314564Sdim
84303241Sdimprotected:
85314564Sdim  std::string m_message;
86314564Sdim  DiagnosticSeverity m_severity;
87314564Sdim  DiagnosticOrigin m_origin;
88314564Sdim  uint32_t m_compiler_id; // Compiler-specific diagnostic ID
89303241Sdim};
90303241Sdim
91360784Sdimtypedef std::vector<std::unique_ptr<Diagnostic>> DiagnosticList;
92303241Sdim
93314564Sdimclass DiagnosticManager {
94303241Sdimpublic:
95314564Sdim  void Clear() {
96314564Sdim    m_diagnostics.clear();
97314564Sdim    m_fixed_expression.clear();
98314564Sdim  }
99314564Sdim
100314564Sdim  const DiagnosticList &Diagnostics() { return m_diagnostics; }
101314564Sdim
102360784Sdim  bool HasFixIts() const {
103360784Sdim    return llvm::any_of(m_diagnostics,
104360784Sdim                        [](const std::unique_ptr<Diagnostic> &diag) {
105360784Sdim                          return diag->HasFixIts();
106360784Sdim                        });
107314564Sdim  }
108303241Sdim
109314564Sdim  void AddDiagnostic(llvm::StringRef message, DiagnosticSeverity severity,
110314564Sdim                     DiagnosticOrigin origin,
111314564Sdim                     uint32_t compiler_id = LLDB_INVALID_COMPILER_ID) {
112360784Sdim    m_diagnostics.emplace_back(
113360784Sdim        std::make_unique<Diagnostic>(message, severity, origin, compiler_id));
114314564Sdim  }
115303241Sdim
116360784Sdim  void AddDiagnostic(std::unique_ptr<Diagnostic> diagnostic) {
117360784Sdim    m_diagnostics.push_back(std::move(diagnostic));
118314564Sdim  }
119314564Sdim
120314564Sdim  size_t Printf(DiagnosticSeverity severity, const char *format, ...)
121314564Sdim      __attribute__((format(printf, 3, 4)));
122360784Sdim  void PutString(DiagnosticSeverity severity, llvm::StringRef str);
123314564Sdim
124314564Sdim  void AppendMessageToDiagnostic(llvm::StringRef str) {
125360784Sdim    if (!m_diagnostics.empty())
126314564Sdim      m_diagnostics.back()->AppendMessage(str);
127314564Sdim  }
128303241Sdim
129314564Sdim  // Returns a string containing errors in this format:
130314564Sdim  //
131314564Sdim  // "error: error text\n
132314564Sdim  // warning: warning text\n
133314564Sdim  // remark text\n"
134314564Sdim  std::string GetString(char separator = '\n');
135314564Sdim
136314564Sdim  void Dump(Log *log);
137314564Sdim
138314564Sdim  const std::string &GetFixedExpression() { return m_fixed_expression; }
139314564Sdim
140314564Sdim  // Moves fixed_expression to the internal storage.
141314564Sdim  void SetFixedExpression(std::string fixed_expression) {
142314564Sdim    m_fixed_expression = std::move(fixed_expression);
143314564Sdim  }
144314564Sdim
145303241Sdimprotected:
146314564Sdim  DiagnosticList m_diagnostics;
147314564Sdim  std::string m_fixed_expression;
148303241Sdim};
149303241Sdim}
150303241Sdim
151303241Sdim#endif /* lldb_DiagnosticManager_h */
152