GCC Code Coverage Report


Directory: ./
File: openvdb_ax/openvdb_ax/compiler/Logger.h
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 6 8 75.0%
Functions: 1 2 50.0%
Branches: 42 77 54.5%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-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 {
26 OPENVDB_USE_VERSION_NAMESPACE
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.
57 class OPENVDB_AX_API Logger
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
16/29
✗ Branch 0 not taken.
✓ Branch 1 taken 7938 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 547 times.
✓ Branch 4 taken 4373 times.
✓ Branch 5 taken 1539 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 38 not taken.
19866 inline size_t errors() const { return mNumErrors; }
110 /// @brief Returns the number of warnings that have been encountered
111
11/22
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
1587 inline size_t warnings() const { return mNumWarnings; }
112
113 /// @brief Returns true if an error has been found, false otherwise
114
5/10
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
286 inline bool hasError() const { return this->errors() > 0; }
115 /// @brief Returns true if a warning has been found, false otherwise
116
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
6 inline bool hasWarning() const { return this->warnings() > 0; }
117 /// @brief Returns true if it has errored and the max errors has been hit
118 2206 inline bool atErrorLimit() const {
119
4/4
✓ Branch 1 taken 896 times.
✓ Branch 2 taken 1310 times.
✓ Branch 4 taken 285 times.
✓ Branch 5 taken 611 times.
2206 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
223