• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef SRC_DIAGNOSTIC_DIAGNOSTIC_H_
16 #define SRC_DIAGNOSTIC_DIAGNOSTIC_H_
17 
18 #include <string>
19 #include <utility>
20 #include <vector>
21 
22 #include "src/source.h"
23 
24 namespace tint {
25 namespace diag {
26 
27 /// Severity is an enumerator of diagnostic severities.
28 enum class Severity { Note, Warning, Error, InternalCompilerError, Fatal };
29 
30 /// @return true iff `a` is more than, or of equal severity to `b`
31 inline bool operator>=(Severity a, Severity b) {
32   return static_cast<int>(a) >= static_cast<int>(b);
33 }
34 
35 /// System is an enumerator of Tint systems that can be the originator of a
36 /// diagnostic message.
37 enum class System {
38   AST,
39   Clone,
40   Inspector,
41   Program,
42   ProgramBuilder,
43   Reader,
44   Resolver,
45   Semantic,
46   Symbol,
47   Test,
48   Transform,
49   Utils,
50   Writer,
51 };
52 
53 /// Diagnostic holds all the information for a single compiler diagnostic
54 /// message.
55 class Diagnostic {
56  public:
57   /// severity is the severity of the diagnostic message.
58   Severity severity = Severity::Error;
59   /// source is the location of the diagnostic.
60   Source source;
61   /// message is the text associated with the diagnostic.
62   std::string message;
63   /// system is the Tint system that raised the diagnostic.
64   System system;
65   /// code is the error code, for example a validation error might have the code
66   /// `"v-0001"`.
67   const char* code = nullptr;
68 };
69 
70 /// List is a container of Diagnostic messages.
71 class List {
72  public:
73   /// iterator is the type used for range based iteration.
74   using iterator = std::vector<Diagnostic>::const_iterator;
75 
76   /// Constructs the list with no elements.
77   List();
78 
79   /// Copy constructor. Copies the diagnostics from `list` into this list.
80   /// @param list the list of diagnostics to copy into this list.
81   List(std::initializer_list<Diagnostic> list);
82 
83   /// Copy constructor. Copies the diagnostics from `list` into this list.
84   /// @param list the list of diagnostics to copy into this list.
85   List(const List& list);
86 
87   /// Move constructor. Moves the diagnostics from `list` into this list.
88   /// @param list the list of diagnostics to move into this list.
89   List(List&& list);
90   ~List();
91 
92   /// Assignment operator. Copies the diagnostics from `list` into this list.
93   /// @param list the list to copy into this list.
94   /// @return this list.
95   List& operator=(const List& list);
96 
97   /// Assignment move operator. Moves the diagnostics from `list` into this
98   /// list.
99   /// @param list the list to move into this list.
100   /// @return this list.
101   List& operator=(List&& list);
102 
103   /// adds a diagnostic to the end of this list.
104   /// @param diag the diagnostic to append to this list.
add(Diagnostic && diag)105   void add(Diagnostic&& diag) {
106     if (diag.severity >= Severity::Error) {
107       error_count_++;
108     }
109     entries_.emplace_back(std::move(diag));
110   }
111 
112   /// adds a list of diagnostics to the end of this list.
113   /// @param list the diagnostic to append to this list.
add(const List & list)114   void add(const List& list) {
115     for (auto diag : list) {
116       add(std::move(diag));
117     }
118   }
119 
120   /// adds the note message with the given Source to the end of this list.
121   /// @param system the system raising the note message
122   /// @param note_msg the note message
123   /// @param source the source of the note diagnostic
add_note(System system,const std::string & note_msg,const Source & source)124   void add_note(System system,
125                 const std::string& note_msg,
126                 const Source& source) {
127     diag::Diagnostic note{};
128     note.severity = diag::Severity::Note;
129     note.system = system;
130     note.source = source;
131     note.message = note_msg;
132     add(std::move(note));
133   }
134 
135   /// adds the warning message with the given Source to the end of this list.
136   /// @param system the system raising the warning message
137   /// @param warning_msg the warning message
138   /// @param source the source of the warning diagnostic
add_warning(System system,const std::string & warning_msg,const Source & source)139   void add_warning(System system,
140                    const std::string& warning_msg,
141                    const Source& source) {
142     diag::Diagnostic warning{};
143     warning.severity = diag::Severity::Warning;
144     warning.system = system;
145     warning.source = source;
146     warning.message = warning_msg;
147     add(std::move(warning));
148   }
149 
150   /// adds the error message without a source to the end of this list.
151   /// @param system the system raising the error message
152   /// @param err_msg the error message
add_error(System system,std::string err_msg)153   void add_error(System system, std::string err_msg) {
154     diag::Diagnostic error{};
155     error.severity = diag::Severity::Error;
156     error.system = system;
157     error.message = std::move(err_msg);
158     add(std::move(error));
159   }
160 
161   /// adds the error message with the given Source to the end of this list.
162   /// @param system the system raising the error message
163   /// @param err_msg the error message
164   /// @param source the source of the error diagnostic
add_error(System system,std::string err_msg,const Source & source)165   void add_error(System system, std::string err_msg, const Source& source) {
166     diag::Diagnostic error{};
167     error.severity = diag::Severity::Error;
168     error.system = system;
169     error.source = source;
170     error.message = std::move(err_msg);
171     add(std::move(error));
172   }
173 
174   /// adds the error message with the given code and Source to the end of this
175   /// list.
176   /// @param system the system raising the error message
177   /// @param code the error code
178   /// @param err_msg the error message
179   /// @param source the source of the error diagnostic
add_error(System system,const char * code,std::string err_msg,const Source & source)180   void add_error(System system,
181                  const char* code,
182                  std::string err_msg,
183                  const Source& source) {
184     diag::Diagnostic error{};
185     error.code = code;
186     error.severity = diag::Severity::Error;
187     error.system = system;
188     error.source = source;
189     error.message = std::move(err_msg);
190     add(std::move(error));
191   }
192 
193   /// adds an internal compiler error message to the end of this list.
194   /// @param system the system raising the error message
195   /// @param err_msg the error message
196   /// @param source the source of the internal compiler error
add_ice(System system,const std::string & err_msg,const Source & source)197   void add_ice(System system,
198                const std::string& err_msg,
199                const Source& source) {
200     diag::Diagnostic ice{};
201     ice.severity = diag::Severity::InternalCompilerError;
202     ice.system = system;
203     ice.source = source;
204     ice.message = err_msg;
205     add(std::move(ice));
206   }
207 
208   /// @returns true iff the diagnostic list contains errors diagnostics (or of
209   /// higher severity).
contains_errors()210   bool contains_errors() const { return error_count_ > 0; }
211   /// @returns the number of error diagnostics (or of higher severity).
error_count()212   size_t error_count() const { return error_count_; }
213   /// @returns the number of entries in the list.
count()214   size_t count() const { return entries_.size(); }
215   /// @returns the first diagnostic in the list.
begin()216   iterator begin() const { return entries_.begin(); }
217   /// @returns the last diagnostic in the list.
end()218   iterator end() const { return entries_.end(); }
219 
220   /// @returns a formatted string of all the diagnostics in this list.
221   std::string str() const;
222 
223  private:
224   std::vector<Diagnostic> entries_;
225   size_t error_count_ = 0;
226 };
227 
228 }  // namespace diag
229 }  // namespace tint
230 
231 #endif  // SRC_DIAGNOSTIC_DIAGNOSTIC_H_
232