OpenVDB  12.0.0
Logger.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: Apache-2.0
3 
4 /// @file compiler/Logger.h
5 ///
6 /// @authors Richard Jones
7 ///
8 /// @brief Logging system to collect errors and warnings throughout the
9 /// different stages of parsing and compilation.
10 ///
11 
12 #ifndef OPENVDB_AX_COMPILER_LOGGER_HAS_BEEN_INCLUDED
13 #define OPENVDB_AX_COMPILER_LOGGER_HAS_BEEN_INCLUDED
14 
15 #include "../ast/AST.h"
16 
17 #include <openvdb/version.h>
18 
19 #include <functional>
20 #include <string>
21 #include <unordered_map>
22 
23 class TestLogger;
24 
25 namespace openvdb {
27 namespace OPENVDB_VERSION_NAME {
28 
29 namespace ax {
30 
31 /// @brief Logger for collecting errors and warnings that occur during AX
32 /// compilation.
33 ///
34 /// @details Error and warning output can be customised using the function
35 /// pointer arguments. These require a function that takes the formatted error
36 /// or warning string and handles the output, returning void.
37 /// e.g.
38 /// void streamCerr(const std::string& message) {
39 /// std::cerr << message << std::endl;
40 /// }
41 ///
42 /// The Logger handles formatting of messages, tracking of number of errors or
43 /// warnings and retrieval of errored lines of code to be printed if needed.
44 /// Use of the Logger to track new errors or warnings can be done either with
45 /// the line/column numbers directly (e.g during lexing and parsing where the
46 /// code is being iterated through) or referring to the AST node using its
47 /// position in the Tree (e.g. during codegen where only the AST node is known
48 /// directly, not the corresponding line/column numbers). To find the line or
49 /// column numbers for events logged using AST nodes, the Logger stores a map
50 /// of Node* to line and column numbers. This must be populated e.g. during
51 /// parsing, to allow resolution of code locations when they are not
52 /// explicitly available. The Logger also stores a pointer to the AST Tree
53 /// that these nodes belong to and the code used to create it.
54 ///
55 /// @warning The logger is not thread safe. A unique instance of the Logger
56 /// should be used for unique invocations of ax pipelines.
58 {
59 public:
60  using Ptr = std::shared_ptr<Logger>;
61 
62  using CodeLocation = std::pair<size_t, size_t>;
63  using OutputFunction = std::function<void(const std::string&)>;
64 
65  /// @brief Construct a Logger with optional error and warning output
66  /// functions, defaults stream errors to std::cerr and suppress warnings
67  /// @param errors Optional error output function
68  /// @param warnings Optional warning output function
69  Logger(const OutputFunction& errors =
70  [](const std::string& msg){
71  std::cerr << msg << std::endl;
72  },
73  const OutputFunction& warnings = [](const std::string&){});
74  ~Logger();
75 
76  /// @brief Log a compiler error and its offending code location. If the
77  /// offending location is (0,0), the message is treated as not having an
78  /// associated code location.
79  /// @param message The error message
80  /// @param lineCol The line/column number of the offending code
81  /// @return true if can continue to capture future messages.
82  bool error(const std::string& message, const CodeLocation& lineCol = CodeLocation(0,0));
83 
84  /// @brief Log a compiler error using the offending AST node. Used in AST
85  /// traversal.
86  /// @param message The error message
87  /// @param node The offending AST node causing the error
88  /// @return true if can continue to capture future messages.
89  bool error(const std::string& message, const ax::ast::Node* node);
90 
91  /// @brief Log a compiler warning and its offending code location. If the
92  /// offending location is (0,0), the message is treated as not having an
93  /// associated code location.
94  /// @param message The warning message
95  /// @param lineCol The line/column number of the offending code
96  /// @return true if can continue to capture future messages.
97  bool warning(const std::string& message, const CodeLocation& lineCol = CodeLocation(0,0));
98 
99  /// @brief Log a compiler warning using the offending AST node. Used in AST
100  /// traversal.
101  /// @param message The warning message
102  /// @param node The offending AST node causing the warning
103  /// @return true if can continue to capture future messages.
104  bool warning(const std::string& message, const ax::ast::Node* node);
105 
106  ///
107 
108  /// @brief Returns the number of errors that have been encountered
109  inline size_t errors() const { return mNumErrors; }
110  /// @brief Returns the number of warnings that have been encountered
111  inline size_t warnings() const { return mNumWarnings; }
112 
113  /// @brief Returns true if an error has been found, false otherwise
114  inline bool hasError() const { return this->errors() > 0; }
115  /// @brief Returns true if a warning has been found, false otherwise
116  inline bool hasWarning() const { return this->warnings() > 0; }
117  /// @brief Returns true if it has errored and the max errors has been hit
118  inline bool atErrorLimit() const {
119  return this->getMaxErrors() > 0 && this->errors() >= this->getMaxErrors();
120  }
121 
122  /// @brief Clear the tree-code mapping and reset the number of errors/warnings
123  /// @note The tree-code mapping must be repopulated to retrieve line and
124  /// column numbers during AST traversal i.e. code generation. The
125  /// openvdb::ax::ast::parse() function does this for a given input code
126  /// string.
127  void clear();
128 
129  /// @brief Set any warnings that are encountered to be promoted to errors
130  /// @param warnAsError If true, warnings will be treated as errors
131  void setWarningsAsErrors(const bool warnAsError = false);
132  /// @brief Returns if warning are promoted to errors
133  bool getWarningsAsErrors() const;
134 
135  /// @brief Sets the maximum number of errors that are allowed before
136  /// compilation should exit.
137  /// @note The logger will continue to increment the error counter beyond
138  /// this value but, once reached, it will not invoke the error callback.
139  /// @param maxErrors The number of allowed errors
140  void setMaxErrors(const size_t maxErrors = 0);
141  /// @brief Returns the number of allowed errors
142  size_t getMaxErrors() const;
143 
144  /// Error/warning formatting options
145 
146  /// @brief Set whether the output should number the errors/warnings
147  /// @param numbered If true, messages will be numbered
148  void setNumberedOutput(const bool numbered = true);
149  /// @brief Number of spaces to indent every new line before the message is formatted
150  void setIndent(const size_t ident = 0);
151  /// @brief Set a prefix for each warning message
152  void setErrorPrefix(const char* prefix = "error: ");
153  /// @brief Set a prefix for each warning message
154  void setWarningPrefix(const char* prefix = "warning: ");
155  /// @brief Set whether the output should include the offending line of code
156  /// @param print If true, offending lines of code will be appended to the
157  /// output message
158  void setPrintLines(const bool print = true);
159 
160  /// @brief Returns whether the messages will be numbered
161  bool getNumberedOutput() const;
162  /// @brief Returns the number of spaces to be printed before every new line
163  size_t getIndent() const;
164  /// @brief Returns the prefix for each error message
165  const char* getErrorPrefix() const;
166  /// @brief Returns the prefix for each warning message
167  const char* getWarningPrefix() const;
168  /// @brief Returns whether the messages will include the line of offending code
169  bool getPrintLines() const;
170 
171  /// @brief Set the source code that lines can be printed from if an error or
172  /// warning is raised
173  /// @param code The AX code as a c-style string
174  void setSourceCode(const char* code);
175 
176  /// These functions are only to be used during parsing to allow line and
177  /// column number retrieval during later stages of compilation when working
178  /// solely with an AST
179 
180  /// @brief Set the AST source tree which will be used as reference for the
181  /// locations of nodes when resolving line and column numbers during AST
182  /// traversal
183  /// @note To be used just by ax::parse before any AST modifications to
184  /// ensure traversal of original source tree is possible, when adding
185  /// messages using Node* which may correspond to modified trees
186  /// @param tree Pointer to const AST
187  void setSourceTree(openvdb::ax::ast::Tree::ConstPtr tree);
188 
189  /// @brief Add a node to the code location map
190  /// @param node Pointer to AST node
191  /// @param location Line and column number in code
192  void addNodeLocation(const ax::ast::Node* node, const CodeLocation& location);
193 
194  // forward declaration
195  struct Settings;
196  struct SourceCode;
197 
198 private:
199 
200  friend class ::TestLogger;
201 
202  OutputFunction mErrorOutput;
203  OutputFunction mWarningOutput;
204 
205  size_t mNumErrors;
206  size_t mNumWarnings;
207 
208  std::unique_ptr<Settings> mSettings;
209 
210  // components needed for verbose error info i.e. line/column numbers and
211  // lines from source code
212  std::unique_ptr<SourceCode> mCode;
213  ax::ast::Tree::ConstPtr mTreePtr;
214  std::unordered_map<const ax::ast::Node*, CodeLocation> mNodeToLineColMap;
215 };
216 
217 } // namespace ax
218 } // namespace OPENVDB_VERSION_NAME
219 } // namespace openvdb
220 
221 #endif // OPENVDB_AX_COMPILER_LOGGER_HAS_BEEN_INCLUDED
222 
std::pair< size_t, size_t > CodeLocation
Definition: Logger.h:62
std::shared_ptr< Logger > Ptr
Definition: Logger.h:60
#define OPENVDB_AX_API
Definition: Platform.h:289
OPENVDB_AX_API void print(const ast::Node &node, const bool numberStatements=true, std::ostream &os=std::cout, const char *indent=" ")
Writes a descriptive printout of a Node hierarchy into a target stream.
std::shared_ptr< const Tree > ConstPtr
Definition: AST.h:565
bool atErrorLimit() const
Returns true if it has errored and the max errors has been hit.
Definition: Logger.h:118
Definition: Exceptions.h:13
size_t warnings() const
Returns the number of warnings that have been encountered.
Definition: Logger.h:111
bool hasError() const
Returns true if an error has been found, false otherwise.
Definition: Logger.h:114
std::function< void(const std::string &)> OutputFunction
Definition: Logger.h:63
Logger for collecting errors and warnings that occur during AX compilation.
Definition: Logger.h:57
bool hasWarning() const
Returns true if a warning has been found, false otherwise.
Definition: Logger.h:116
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
The base abstract node which determines the interface and required methods for all derived concrete n...
Definition: AST.h:102
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218
size_t errors() const
Returns the number of errors that have been encountered.
Definition: Logger.h:109