souffle  2.0.2-371-g6315b36
ErrorReport.h
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file reports/ErrorReport.h
12  *
13  * Defines a class for error reporting.
14  *
15  ***********************************************************************/
16 
17 #pragma once
18 
19 #include "parser/SrcLocation.h"
20 #include <algorithm>
21 #include <cassert>
22 #include <cstdlib>
23 #include <iostream>
24 #include <set>
25 #include <string>
26 #include <utility>
27 #include <vector>
28 
29 namespace souffle {
30 
31 class DiagnosticMessage {
32 public:
33  DiagnosticMessage(std::string message, SrcLocation location)
34  : message(std::move(message)), hasLoc(true), location(std::move(location)) {}
35 
36  DiagnosticMessage(std::string message) : message(std::move(message)), hasLoc(false) {}
37 
38  const std::string& getMessage() const {
39  return message;
40  }
41 
42  const SrcLocation& getLocation() const {
43  assert(hasLoc);
44  return location;
45  }
46 
47  bool hasLocation() const {
48  return hasLoc;
49  }
50 
51  void print(std::ostream& out) const {
52  out << message;
53  if (hasLoc) {
54  out << " in " << location.extloc();
55  }
56  out << "\n";
57  }
58 
59  friend std::ostream& operator<<(std::ostream& out, const DiagnosticMessage& diagnosticMessage) {
60  diagnosticMessage.print(out);
61  return out;
62  }
63 
64 private:
65  std::string message;
66  bool hasLoc;
68 };
69 
70 class Diagnostic {
71 public:
72  enum class Type { ERROR, WARNING };
73 
74  Diagnostic(Type type, DiagnosticMessage primaryMessage, std::vector<DiagnosticMessage> additionalMessages)
77 
80 
81  Type getType() const {
82  return type;
83  }
84 
85  const DiagnosticMessage& getPrimaryMessage() const {
86  return primaryMessage;
87  }
88 
89  const std::vector<DiagnosticMessage>& getAdditionalMessages() const {
90  return additionalMessages;
91  }
92 
93  void print(std::ostream& out) const {
94  out << (type == Type::ERROR ? "Error: " : "Warning: ");
96  for (const DiagnosticMessage& additionalMessage : additionalMessages) {
97  out << additionalMessage;
98  }
99  }
100 
101  friend std::ostream& operator<<(std::ostream& out, const Diagnostic& diagnostic) {
102  diagnostic.print(out);
103  return out;
104  }
105 
106  bool operator<(const Diagnostic& other) const {
107  if (primaryMessage.hasLocation() && !other.primaryMessage.hasLocation()) {
108  return true;
109  }
110  if (other.primaryMessage.hasLocation() && !primaryMessage.hasLocation()) {
111  return false;
112  }
113 
114  if (primaryMessage.hasLocation() && other.primaryMessage.hasLocation()) {
115  if (primaryMessage.getLocation() < other.primaryMessage.getLocation()) {
116  return true;
117  }
118  if (other.primaryMessage.getLocation() < primaryMessage.getLocation()) {
119  return false;
120  }
121  }
122 
123  if (type == Type::ERROR && other.getType() == Type::WARNING) {
124  return true;
125  }
126  if (other.getType() == Type::ERROR && type == Type::WARNING) {
127  return false;
128  }
129 
130  if (primaryMessage.getMessage() < other.primaryMessage.getMessage()) {
131  return true;
132  }
133  if (other.primaryMessage.getMessage() < primaryMessage.getMessage()) {
134  return false;
135  }
136 
137  return false;
138  }
139 
140 private:
141  Type type;
142  DiagnosticMessage primaryMessage;
143  std::vector<DiagnosticMessage> additionalMessages;
144 };
145 
146 class ErrorReport {
147 public:
148  ErrorReport(bool nowarn = false) : nowarn(nowarn) {}
149 
150  ErrorReport(const ErrorReport& other) = default;
151 
152  unsigned getNumErrors() const {
153  return std::count_if(diagnostics.begin(), diagnostics.end(),
154  [](Diagnostic d) -> bool { return d.getType() == Diagnostic::Type::ERROR; });
155  }
156 
157  unsigned getNumWarnings() const {
158  return std::count_if(diagnostics.begin(), diagnostics.end(),
159  [](Diagnostic d) -> bool { return d.getType() == Diagnostic::Type::WARNING; });
160  }
161 
162  unsigned getNumIssues() const {
163  return diagnostics.size();
164  }
165 
166  /** Adds an error with the given message and location */
167  void addError(const std::string& message, SrcLocation location) {
168  diagnostics.insert(
169  Diagnostic(Diagnostic::Type::ERROR, DiagnosticMessage(message, std::move(location))));
170  }
171 
172  /** Adds a warning with the given message and location */
173  void addWarning(const std::string& message, SrcLocation location) {
174  if (!nowarn) {
175  diagnostics.insert(
176  Diagnostic(Diagnostic::Type::WARNING, DiagnosticMessage(message, std::move(location))));
177  }
178  }
179 
180  void addDiagnostic(const Diagnostic& diagnostic) {
181  diagnostics.insert(diagnostic);
182  }
183 
184  void exitIfErrors() {
185  if (getNumErrors() == 0) {
186  return;
187  }
188 
189  std::cerr << *this << getNumErrors() << " errors generated, evaluation aborted\n";
190  exit(EXIT_FAILURE);
191  }
192 
193  void print(std::ostream& out) const {
194  for (const Diagnostic& diagnostic : diagnostics) {
195  out << diagnostic;
196  }
197  }
198 
199  friend std::ostream& operator<<(std::ostream& out, const ErrorReport& report) {
200  report.print(out);
201  return out;
202  }
203 
204 private:
205  std::set<Diagnostic> diagnostics;
206  bool nowarn;
207 };
208 
209 } // end of namespace souffle
souffle::Diagnostic::type
Type type
Definition: ErrorReport.h:147
souffle::Diagnostic::getPrimaryMessage
const DiagnosticMessage & getPrimaryMessage() const
Definition: ErrorReport.h:91
souffle::DiagnosticMessage::operator<<
friend std::ostream & operator<<(std::ostream &out, const DiagnosticMessage &diagnosticMessage)
Definition: ErrorReport.h:71
souffle::DiagnosticMessage::location
SrcLocation location
Definition: ErrorReport.h:79
SrcLocation.h
souffle::ErrorReport::getNumWarnings
unsigned getNumWarnings() const
Definition: ErrorReport.h:163
souffle::Diagnostic::operator<<
friend std::ostream & operator<<(std::ostream &out, const Diagnostic &diagnostic)
Definition: ErrorReport.h:107
souffle::DiagnosticMessage
Definition: ErrorReport.h:37
souffle::DiagnosticMessage::hasLoc
bool hasLoc
Definition: ErrorReport.h:78
souffle::ErrorReport::ErrorReport
ErrorReport(bool nowarn=false)
Definition: ErrorReport.h:154
souffle::Diagnostic::print
void print(std::ostream &out) const
Definition: ErrorReport.h:99
souffle::ErrorReport::getNumIssues
unsigned getNumIssues() const
Definition: ErrorReport.h:168
souffle::DiagnosticMessage::DiagnosticMessage
DiagnosticMessage(std::string message, SrcLocation location)
Definition: ErrorReport.h:45
souffle::ErrorReport::addError
void addError(const std::string &message, SrcLocation location)
Adds an error with the given message and location.
Definition: ErrorReport.h:173
souffle::Diagnostic
Definition: ErrorReport.h:76
souffle::Diagnostic::Type::ERROR
@ ERROR
souffle::DiagnosticMessage::print
void print(std::ostream &out) const
Definition: ErrorReport.h:63
souffle::Diagnostic::Type
Type
Definition: ErrorReport.h:78
souffle::Diagnostic::getType
Type getType() const
Definition: ErrorReport.h:87
souffle::ErrorReport::getNumErrors
unsigned getNumErrors() const
Definition: ErrorReport.h:158
souffle::Diagnostic::Diagnostic
Diagnostic(Type type, DiagnosticMessage primaryMessage, std::vector< DiagnosticMessage > additionalMessages)
Definition: ErrorReport.h:80
souffle::ErrorReport::nowarn
bool nowarn
Definition: ErrorReport.h:212
souffle::ErrorReport::print
void print(std::ostream &out) const
Definition: ErrorReport.h:199
souffle::DiagnosticMessage::hasLocation
bool hasLocation() const
Definition: ErrorReport.h:59
souffle::ErrorReport::operator<<
friend std::ostream & operator<<(std::ostream &out, const ErrorReport &report)
Definition: ErrorReport.h:205
souffle::Diagnostic::operator<
bool operator<(const Diagnostic &other) const
Definition: ErrorReport.h:112
std
Definition: Brie.h:3053
souffle::DiagnosticMessage::getMessage
const std::string & getMessage() const
Definition: ErrorReport.h:50
souffle::SrcLocation
A class describing a range in an input file.
Definition: SrcLocation.h:32
souffle::Diagnostic::additionalMessages
std::vector< DiagnosticMessage > additionalMessages
Definition: ErrorReport.h:149
souffle::ErrorReport::diagnostics
std::set< Diagnostic > diagnostics
Definition: ErrorReport.h:211
souffle::ErrorReport::addWarning
void addWarning(const std::string &message, SrcLocation location)
Adds a warning with the given message and location.
Definition: ErrorReport.h:179
souffle
Definition: AggregateOp.h:25
d
else d
Definition: htmlJsChartistMin.h:15
souffle::Diagnostic::getAdditionalMessages
const std::vector< DiagnosticMessage > & getAdditionalMessages() const
Definition: ErrorReport.h:95
souffle::DiagnosticMessage::message
std::string message
Definition: ErrorReport.h:77
souffle::ErrorReport::addDiagnostic
void addDiagnostic(const Diagnostic &diagnostic)
Definition: ErrorReport.h:186
souffle::ErrorReport::exitIfErrors
void exitIfErrors()
Definition: ErrorReport.h:190
souffle::ErrorReport
Definition: ErrorReport.h:152
souffle::Diagnostic::Type::WARNING
@ WARNING
souffle::Diagnostic::primaryMessage
DiagnosticMessage primaryMessage
Definition: ErrorReport.h:148
souffle::DiagnosticMessage::getLocation
const SrcLocation & getLocation() const
Definition: ErrorReport.h:54
souffle::SrcLocation::extloc
std::string extloc() const
An extended string describing this location in a end-user friendly way.
Definition: SrcLocation.cpp:93