GCC Code Coverage Report


Directory: ./
File: openvdb_ax/openvdb_ax/compiler/Logger.cc
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 87 121 71.9%
Functions: 22 30 73.3%
Branches: 50 102 49.0%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 /// @file compiler/Logger.cc
5
6 #include "Logger.h"
7
8 #include <stack>
9
10 namespace openvdb {
11 OPENVDB_USE_VERSION_NAMESPACE
12 namespace OPENVDB_VERSION_NAME {
13
14 namespace ax {
15
16 4682 struct Logger::Settings
17 {
18 size_t mMaxErrors = 0;
19 bool mWarningsAsErrors = false;
20 // message formatting settings
21 bool mNumbered = true;
22 const char* mErrorPrefix = "error: ";
23 const char* mWarningPrefix = "warning: ";
24 bool mPrintLines = false;
25 std::string mIndent;
26 };
27
28
29 /// @brief Wrapper around a code snippet to print individual lines from a multi
30 /// line string
31 /// @note Assumes a null terminated c-style string input
32 3380 struct Logger::SourceCode
33 {
34 SourceCode(const char* string = nullptr)
35 3380 : mString(string)
36 , mOffsets()
37
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3380 times.
3380 , mLines() {
38 reset(string);
39 }
40
41 /// @brief Print a line of the multi-line string to the stream
42 /// @note If no string hs been provided, will do nothing
43 /// @param line Line number to print
44 /// @param os Output stream
45 void getLine(const size_t num, std::ostream* os)
46 {
47 if (num < 1) return;
48 if (mOffsets.empty()) getLineOffsets();
49 if (num > mLines) return;
50 const size_t start = mOffsets[num - 1];
51 const size_t end = mOffsets[num];
52 for (size_t i = start; i < end - 1; ++i) *os << mString[i];
53 }
54
55 void reset(const char* string)
56 {
57 mString = string;
58 mOffsets.clear();
59 mLines = 0;
60 }
61
62 bool hasString() const { return static_cast<bool>(mString); }
63
64 private:
65
66 void getLineOffsets()
67 {
68 if (!mString) return;
69 mOffsets.emplace_back(0);
70 size_t offset = 1;
71 const char* iter = mString;
72 while (*iter != '\0') {
73 if (*iter == '\n') mOffsets.emplace_back(offset);
74 ++iter; ++offset;
75 }
76 mOffsets.emplace_back(offset);
77 mLines = mOffsets.size();
78 }
79
80 const char* mString;
81 std::vector<size_t> mOffsets;
82 size_t mLines;
83 };
84
85 namespace {
86
87 /// @brief Return a stack denoting the position in the tree of this node
88 /// Where each node is represented by its childidx of its parent
89 /// This gives a branching path to follow to reach this node from the
90 /// tree root
91 /// @parm node Node pointer to create position stack for
92 1857 inline std::stack<size_t> pathStackFromNode(const ast::Node* node)
93 {
94 std::stack<size_t> path;
95 const ast::Node* child = node;
96 const ast::Node* parent = node->parent();
97
2/2
✓ Branch 0 taken 4558 times.
✓ Branch 1 taken 1857 times.
6415 while (parent) {
98
2/4
✓ Branch 1 taken 4558 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4558 times.
✗ Branch 5 not taken.
4558 path.emplace(child->childidx());
99 child = parent;
100 parent = child->parent();
101 }
102 1857 return path;
103 }
104
105 /// @brief Iterate through a tree, following the branch numbers from the path
106 /// stack, returning a Node* to the node at this position
107 /// @parm path Stack of child branches to follow
108 /// @parm tree Tree containing node to return
109 1857 inline const ast::Node* nodeFromPathStack(std::stack<size_t>& path,
110 const ast::Tree& tree)
111 {
112 1857 const ast::Node* node = &tree;
113
1/2
✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
6415 while (node) {
114
2/2
✓ Branch 0 taken 4558 times.
✓ Branch 1 taken 1857 times.
6415 if (path.empty()) return node;
115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4558 times.
4558 node = node->child(path.top());
116 path.pop();
117 }
118 return nullptr;
119 }
120
121 /// @brief Given any node and a tree and node to location map, return the line
122 /// and column number for the nodes equivalent (in terms of position in the
123 /// tree) from the supplied tree
124 /// @note Requires the map to have been populated for all nodes in the supplied
125 /// tree, otherwise will return 0:0
126 inline const Logger::CodeLocation
127
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1857 times.
1865 nodeToCodeLocation(const ast::Node* node,
128 const ast::Tree::ConstPtr tree,
129 const std::unordered_map
130 <const ax::ast::Node*, Logger::CodeLocation>& map)
131 {
132
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1857 times.
1865 if (!tree) return Logger::CodeLocation(0,0);
133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1857 times.
1857 assert(node);
134 1857 std::stack<size_t> pathStack = pathStackFromNode(node);
135
1/2
✓ Branch 1 taken 1857 times.
✗ Branch 2 not taken.
1857 const ast::Node* nodeInMap = nodeFromPathStack(pathStack, *tree);
136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1857 times.
1857 const auto locationIter = map.find(nodeInMap);
137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1857 times.
1857 if (locationIter == map.end()) return Logger::CodeLocation(0,0);
138 1857 return locationIter->second;
139 }
140
141 2459 std::string format(const std::string& message,
142 const Logger::CodeLocation& loc,
143 const size_t numMessage,
144 const bool numbered,
145 const bool printLines,
146 const std::string& indent,
147 Logger::SourceCode* sourceCode)
148 {
149 4918 std::stringstream ss;
150 ss << indent;
151
2/4
✓ Branch 0 taken 2459 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2459 times.
✗ Branch 4 not taken.
4918 if (numbered) ss << "[" << numMessage << "] ";
152
3/4
✓ Branch 0 taken 122167 times.
✓ Branch 1 taken 2459 times.
✓ Branch 3 taken 122167 times.
✗ Branch 4 not taken.
124626 for (auto c : message) {
153 122167 ss << c;
154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 122167 times.
122167 if (c == '\n') ss << indent;
155 }
156
2/2
✓ Branch 0 taken 2446 times.
✓ Branch 1 taken 13 times.
2459 if (loc.first > 0) {
157
2/4
✓ Branch 1 taken 2446 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2446 times.
✗ Branch 5 not taken.
4892 ss << " " << loc.first << ":" << loc.second;
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2446 times.
2446 if (printLines && sourceCode) {
159 ss << '\n' << indent;
160 sourceCode->getLine(loc.first, &ss);
161 ss << '\n' << indent;
162 for (size_t i = 0; i < loc.second - 1; ++i) ss << '-';
163 ss << '^';
164 }
165 }
166 2459 return ss.str();
167 }
168
169 }
170
171 2341 Logger::Logger(const Logger::OutputFunction& errors,
172 2341 const Logger::OutputFunction& warnings)
173 : mErrorOutput(errors)
174 , mWarningOutput(warnings)
175 , mNumErrors(0)
176 , mNumWarnings(0)
177 2341 , mSettings(new Logger::Settings())
178
2/4
✓ Branch 2 taken 2341 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2341 times.
✗ Branch 6 not taken.
2341 , mCode() {}
179
180 2341 Logger::~Logger() {}
181
182 3380 void Logger::setSourceCode(const char* code)
183 {
184 3380 mCode.reset(new SourceCode(code));
185 3380 }
186
187 892 bool Logger::error(const std::string& message,
188 const Logger::CodeLocation& lineCol)
189 {
190 // check if we've already exceeded the error limit
191 892 const bool limit = this->atErrorLimit();
192 // Always increment the error counter
193 892 ++mNumErrors;
194
2/2
✓ Branch 0 taken 891 times.
✓ Branch 1 taken 1 times.
892 if (limit) return false;
195
3/4
✓ Branch 4 taken 891 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 886 times.
✓ Branch 8 taken 5 times.
2673 mErrorOutput(format(this->getErrorPrefix() + message,
196 lineCol,
197 this->errors(),
198 891 this->getNumberedOutput(),
199 891 this->getPrintLines(),
200 891 this->mSettings->mIndent,
201 this->mCode.get()));
202 886 return !this->atErrorLimit();
203 }
204
205 315 bool Logger::error(const std::string& message,
206 const ax::ast::Node* node)
207 {
208
4/8
✓ Branch 2 taken 315 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 315 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 310 times.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
625 return this->error(message, nodeToCodeLocation(node, mTreePtr, mNodeToLineColMap));
209 }
210
211 1569 bool Logger::warning(const std::string& message,
212 const Logger::CodeLocation& lineCol)
213 {
214
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1568 times.
1569 if (this->getWarningsAsErrors()) {
215
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 return this->error(message + " [warning-as-error]", lineCol);
216 }
217 else {
218 1568 ++mNumWarnings;
219
2/4
✓ Branch 4 taken 1568 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1568 times.
✗ Branch 8 not taken.
4704 mWarningOutput(format(this->getWarningPrefix() + message,
220 lineCol,
221 this->warnings(),
222 1568 this->getNumberedOutput(),
223 1568 this->getPrintLines(),
224 1568 this->mSettings->mIndent,
225 this->mCode.get()));
226 1568 return true;
227 }
228 }
229
230 1550 bool Logger::warning(const std::string& message,
231 const ax::ast::Node* node)
232 {
233
4/8
✓ Branch 2 taken 1550 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1550 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1547 times.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
3097 return this->warning(message, nodeToCodeLocation(node, mTreePtr, mNodeToLineColMap));
234 }
235
236 1 void Logger::setWarningsAsErrors(const bool warnAsError)
237 {
238 1 mSettings->mWarningsAsErrors = warnAsError;
239 1 }
240
241 1569 bool Logger::getWarningsAsErrors() const
242 {
243 1569 return mSettings->mWarningsAsErrors;
244 }
245
246 2 void Logger::setMaxErrors(const size_t maxErrors)
247 {
248 2 mSettings->mMaxErrors = maxErrors;
249 2 }
250
251 3102 size_t Logger::getMaxErrors() const
252 {
253 3102 return mSettings->mMaxErrors;
254 }
255
256 void Logger::setNumberedOutput(const bool numbered)
257 {
258 mSettings->mNumbered = numbered;
259 }
260
261 void Logger::setIndent(const size_t ident)
262 {
263 mSettings->mIndent = std::string(ident, ' ');
264 }
265
266 void Logger::setErrorPrefix(const char* prefix)
267 {
268 mSettings->mErrorPrefix = prefix;
269 }
270
271 void Logger::setWarningPrefix(const char* prefix)
272 {
273 mSettings->mWarningPrefix = prefix;
274 }
275
276 void Logger::setPrintLines(const bool print)
277 {
278 mSettings->mPrintLines = print;
279 }
280
281 2459 bool Logger::getNumberedOutput() const
282 {
283 2459 return mSettings->mNumbered;
284 }
285
286 size_t Logger::getIndent() const
287 {
288 return mSettings->mIndent.size();
289 }
290
291 891 const char* Logger::getErrorPrefix() const
292 {
293 891 return mSettings->mErrorPrefix;
294 }
295
296 1568 const char* Logger::getWarningPrefix() const
297 {
298 1568 return mSettings->mWarningPrefix;
299 }
300
301 2459 bool Logger::getPrintLines() const
302 {
303 2459 return mSettings->mPrintLines;
304 }
305
306
2/2
✓ Branch 0 taken 2551 times.
✓ Branch 1 taken 459 times.
3010 void Logger::clear()
307 {
308 mCode.reset();
309 3010 mNumErrors = 0;
310 3010 mNumWarnings = 0;
311 mNodeToLineColMap.clear();
312 mTreePtr = nullptr;
313 3010 }
314
315 3380 void Logger::setSourceTree(openvdb::ax::ast::Tree::ConstPtr tree)
316 {
317 mTreePtr = tree;
318 3380 }
319
320 101110 void Logger::addNodeLocation(const ax::ast::Node* node, const Logger::CodeLocation& location)
321 {
322 mNodeToLineColMap.emplace(node, location);
323 101110 }
324
325 } // namespace ax
326 } // namespace OPENVDB_VERSION_NAME
327 } // namespace openvdb
328
329