A diagnostic library for printing compiler diagnostics.
- The diagnostic architecture is based on Google's Carbon Language diagnostic implementation, but not the exact implementation.
CowStringis inspired by Rust'sCowimplementation.- The error reporting or rendering on the terminal is closer to the Rust's.
Spanis an absolute position within the source string. This does not accept signed positions. The range is[0, max(dsize_t)]. The default type alias fordsize_tisunsigned, but if you don't wnat it, you can define the macroDARK_DIAGNOSTICS_SIZE_TYPEbefore the header.
For example:
#define DARK_DIAGNOSTICS_SIZE_TYPE std::size_t
#include <diagnostics.hpp>
This provides more information to the current diagnostic that will be rendered below the marked span.
Source: |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
^ ^
| |
| This is an error
|- This is a second error.
This is a single string source that supports newlines and could be split into multiple lines or skipped if it has too many lines that don't have diagnostic.
This is a custom struct or class that inherits from the DiagnosticConverter<LocT>. It allows the user to customise or build diagnostic location to the diagnostic builder.
This an object that consumes the diagnostics, which could a consumer that prints the diagnostics on the terminal or sorts the consumers. These consumers can be plugged into each other; such as plugging sort and stream consumers, which will sort first then print it on the terminal. There are three predefined consumers:
StreamDiagnosticConsumerThis outputs the diagnostic to theFILE*(stderr,stdout, or file)ErrorTrackingDiagnosticConsumerThis tracks the error. If it encounters error, the error flag will be turned on.SortingDiagnosticConsumerThis sorts the diagnostics and needs a explicit flush.
This uses the std::format under the hood so you can use every options that it uses.
# How to use
This library is a C++ header only library so it very easy to use. You can clone the repo and add the include path to the `include` folder inside the cloned repo.
1. Clone the repo
```sh
git clone [email protected]:amitsingh19975/diagnostics.git
- Include it in your project
# If you're using CMake
include_directories(repo_path/diagnostics/include)# You could pass -I flag while compiling
cc -Irepo_path/diagnostics/include my_program- Including the header inside the C++ project
#include <diagnostics.hpp>
int main() {
// ....
}#include <diagnostics.hpp>
using namespace dark;
struct DiagnosticKind {
static constexpr std::size_t InvalidFunctionDefinition = 1;
static constexpr std::size_t InvalidFunctionPrototype = 2;
};
struct TestConverter: DiagnosticConverter<unsigned> {
std::string_view source;
std::string_view filename;
auto convert_loc(unsigned loc, builder_t&) const -> DiagnosticLocation override {
return DiagnosticLocation::from_text(
filename,
source,
/*line_number=*/1,
/*line_start_offset=*/loc,
/*token_start_offset=*/loc,
/*marker=*/Span::from_size(0, 5)
);
}
};
int main() {
auto consumer = ConsoleDiagnosticConsumer();
auto converter = TokenConverter("void test( int a, int c );", "test.cpp");
auto emitter = dark::DiagnosticEmitter(
&converter,
consumer
);
static constexpr auto InvalidFunctionDefinition = dark_make_diagnostic(
DiagnosticKind::InvalidFunctionDefinition,
"Invalid function definition for {} at {}",
char const*, std::uint32_t
);
static constexpr auto InvalidFunctionPrototype = dark_make_diagnostic(
DiagnosticKind::InvalidFunctionPrototype,
"The prototype is defined here"
);
emitter
.error(Span(0, 3), InvalidFunctionDefinition, "Test", 0u)
.begin_annotation()
.insert(")", 2)
.remove(Span(4, 8))
.error(
"prototype does not match the defination",
Span(0, 2),
Span(19, 24)
)
.warn(Span(6, 10), Span(25, 27))
.note("Try to fix the error")
.end_annotation()
.emit();
emitter
.error(Span::from_size(5, 2), InvalidFunctionPrototype)
.emit();
return 0;
}You can see more examples inside the example folder.



