| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | //====================================================================================================================== | ||
| 2 | //! @file | ||
| 3 | /* | ||
| 4 | TTS - Tiny Test System | ||
| 5 | Copyright : TTS Contributors & Maintainers | ||
| 6 | SPDX-License-Identifier: BSL-1.0 | ||
| 7 | */ | ||
| 8 | //====================================================================================================================== | ||
| 9 | #pragma once | ||
| 10 | |||
| 11 | #include <tts/tools/output.hpp> | ||
| 12 | |||
| 13 | namespace tts | ||
| 14 | { | ||
| 15 | //==================================================================================================================== | ||
| 16 | /** | ||
| 17 | @ingroup tools-sinks | ||
| 18 | @public | ||
| 19 | @brief output_sink adding compiler-style diagnostics for every failing/fatal assertion. | ||
| 20 | |||
| 21 | Forwards every message to a target sink (tts::output_handler::default_sink() by default) | ||
| 22 | unchanged, and additionally prints one `path:line: error: message` / | ||
| 23 | `path:line: fatal error: message` line per failing/fatal assertion - built from | ||
| 24 | @ref output_sink's structured `assertion_failed()` hook, not by parsing text - so editors/IDEs | ||
| 25 | with a GCC/Clang-style problem matcher (VS Code's C/C++ extension provides `$gcc`, vim has | ||
| 26 | quickfix, ...) can jump straight to it. Prints even under `-q`, when the raw failure line it | ||
| 27 | complements is itself suppressed. | ||
| 28 | |||
| 29 | @groupheader{Example} | ||
| 30 | @code | ||
| 31 | tts::diagnostics_sink diagnostics; | ||
| 32 | tts::output().sink(diagnostics); | ||
| 33 | @endcode | ||
| 34 | **/ | ||
| 35 | //==================================================================================================================== | ||
| 36 | struct diagnostics_sink : output_sink | ||
| 37 | { | ||
| 38 | 100 | explicit diagnostics_sink(output_sink& target = output_handler::default_sink()) | |
| 39 | 100 | : target_(&target) | |
| 40 | { | ||
| 41 | 100 | } | |
| 42 | |||
| 43 | 10 | void write(text const& t) override | |
| 44 | { | ||
| 45 | 10 | target_->write(t); | |
| 46 | 10 | } | |
| 47 | |||
| 48 | 1 | void assertion_failed(text const& location, text const& message, bool fatal) override | |
| 49 | { | ||
| 50 | // location is already "[file:line]" (see tts::_::source_location) - strip the brackets. | ||
| 51 | 1 | char const* loc = location.data(); | |
| 52 | 1 | std::size_t len = strlen(loc); // NOSONAR - loc always comes from a well-formed tts::text | |
| 53 |
1/1✓ Branch 1 taken 1 times.
|
1 | target_->write(text {"%.*s: %s: %s\n", |
| 54 | 1 | static_cast<int>(len - 2), | |
| 55 | loc + 1, | ||
| 56 | fatal ? "fatal error" : "error", | ||
| 57 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | message.data()}); |
| 58 | 1 | } | |
| 59 | |||
| 60 | 3 | void flush() override | |
| 61 | { | ||
| 62 | 3 | target_->flush(); | |
| 63 | 3 | } | |
| 64 | |||
| 65 | private: | ||
| 66 | output_sink* target_; | ||
| 67 | }; | ||
| 68 | } | ||
| 69 |