codespan-reporting-0.12.0/.cargo_vcs_info.json 0000644 00000000203 00000000001 0014712 0 ustar {
"git": {
"sha1": "3d3a03a8fcc30cc10b783b16c62029d5c232059b",
"dirty": true
},
"path_in_vcs": "codespan-reporting"
} codespan-reporting-0.12.0/CHANGELOG.md 0000644 0000000 0000000 00000040211 10461020230 0015316 0 ustar 0000000 0000000 # Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
The minimum supported rustc version is now `1.67.0` (was `1.40.0`).
This is because some dependencies now require this Rust version.
### Added
- Add the option to display a configurable amount of lines in front of and after any label.
- The `Severity` enum now implements full `Ord`. (#335)
### Changed
- Broken lines are now rendered properly with multiline spans.
We used to render the wrong lines in the gutter when there were multiline spans
and there were breaks in the file.
Example
Before:
```text
error[0001]: oh noes, a cupcake has occurred!
┌─ test:4:1
│
4 │ ╭ Cupcake ipsum dolor. Sit amet marshmallow topping cheesecake
5 │ │ muffin. Halvah croissant candy canes bonbon candy. Apple pie jelly
│ ╭─│─────────'
· │
10 │ │ │ Muffin danish chocolate soufflé pastry icing bonbon oat cake.
11 │ │ │ Powder cake jujubes oat cake. Lemon drops tootsie roll marshmallow
│ │ ╰─────────────────────────────' blah blah
· │ │
19 │ │ soufflé marzipan. Chocolate bar oat cake jujubes lollipop pastry
20 │ │ cupcake. Candy canes cupcake toffee gingerbread candy canes muffin
│ ╰──────────' blah blah
```
After:
```text
error[0001]: oh noes, a cupcake has occurred!
┌─ test:4:1
│
4 │ ╭ Cupcake ipsum dolor. Sit amet marshmallow topping cheesecake
5 │ │ muffin. Halvah croissant candy canes bonbon candy. Apple pie jelly
│ ╭─│─────────'
· │ │
10 │ │ │ Muffin danish chocolate soufflé pastry icing bonbon oat cake.
11 │ │ │ Powder cake jujubes oat cake. Lemon drops tootsie roll marshmallow
│ │ ╰─────────────────────────────' blah blah
· │
19 │ │ soufflé marzipan. Chocolate bar oat cake jujubes lollipop pastry
20 │ │ cupcake. Candy canes cupcake toffee gingerbread candy canes muffin
│ ╰──────────' blah blah
```
## [0.11.1] - 2021-01-18
### Added
- Add `Chars::{box_drawing, ascii}` functions, the latter supporting a rustc-style of
output that only uses ASCII characters (not above U+007F) for use cases that do not allow
for box drawing characters, e.g. terminals that do not support them.
### Changed
- `Diagnostic::with_labels` and `Diagnostic::with_notes` now append additional
labels rather tan overwriting them, meaning that the documentation and behaviour match
more closely. The behaviour will only differ if you call the same builder methods
multiple times. If you call every builder method once only, nothing should change.
- `config::Chars::snippet_start` is now a String instead of a single `char`.
## [0.11.0] - 2020-11-30
There is now a [code of conduct](https://github.com/brendanzab/codespan/blob/master/CODE_OF_CONDUCT.md)
and a [contributing guide](https://github.com/brendanzab/codespan/blob/master/CONTRIBUTING.md).
Some versions were skipped to sync up with the `codespan-lsp` crate. The release
process has been changed so this should not happen again.
### Added
- If a label spans over multiple lines, not all lines are rendered.
The number of lines rendered at beginning and end is configurable separately.
- There is now a custom error type.
- There now is a medium rendering mode that is like the short rendering mode
but also shows notes from the diagnostic.
- `PartialEq` and `Eq` implementations for the `diagnostic::{Diagnostic, Label, Severity}` types.
### Changed
- All errors now use the error type `codespan_reporting::file::Error`.
This type also replaces the custom error type for `codespan-lsp`.
### Fixed
- Empty error codes are not rendered.
- The locus ("location of the diagnostic") is now computed so it is always at the first
primary label, or at the first secondary label if no primary labels are available.
- All `unwrap`s outside of tests and examples have been removed.
- Some internal improvements, including various code style improvements by using Clippy.
- Improved documentation, also mentioning how the ordering of labels is handled.
## [0.9.5] - 2020-06-24
### Changed
- Sections of source code that are marked with primary labels are now rendered
using the primary highlight color.
- Tab stops are now rendered properly.
We used to just render `\t` characters in source snippets with the same
number of spaces.
Example
For example, when rendering with a tab width of `3` we
would print:
```text
warning: tab test
┌─ tab_columns:1:2
│
1 │ hello
│ ^^^^^
2 │ ∙ hello
│ ^^^^^
3 │ ∙∙ hello
│ ^^^^^
4 │ ∙∙∙ hello
│ ^^^^^
5 │ ∙∙∙∙ hello
│ ^^^^^
6 │ ∙∙∙∙∙ hello
│ ^^^^^
7 │ ∙∙∙∙∙∙ hello
│ ^^^^^
```
Now we properly take into account the column of the tab character:
```text
warning: tab test
┌─ tab_columns:1:2
│
1 │ hello
│ ^^^^^
2 │ ∙ hello
│ ^^^^^
3 │ ∙∙ hello
│ ^^^^^
4 │ ∙∙∙ hello
│ ^^^^^
5 │ ∙∙∙∙ hello
│ ^^^^^
6 │ ∙∙∙∙∙ hello
│ ^^^^^
7 │ ∙∙∙∙∙∙ hello
│ ^^^^^
```
## [0.9.4] - 2020-05-18
### Changed
- We have made the caret rendering easier to read when there are multiple
labels on the same line. We also avoid printing trailing borders on the
final source source snippet if no notes are present.
Example
Instead of this:
```text
┌─ one_line.rs:3:5
│
3 │ v.push(v.pop().unwrap());
│ - first borrow later used by call
│ ---- first mutable borrow occurs here
│ ^ second mutable borrow occurs here
│
```
…we now render the following:
```text
┌─ one_line.rs:3:5
│
3 │ v.push(v.pop().unwrap());
│ - ---- ^ second mutable borrow occurs here
│ │ │
│ │ first mutable borrow occurs here
│ first borrow later used by call
```
### Fixed
- Diagnostic rendering no longer panics if label ranges are between UTF-8
character boundaries.
## [0.9.3] - 2020-04-29
### Changed
- Some panics were fixed when invalid unicode boundaries are supplied.
- Labels that marked the same span were originally rendered in reverse order.
This was a mistake! We've now fixed this.
Example
For example, this diagnostic:
```text
┌─ same_range:1:7
│
1 │ ::S { }
│ - Expected '('
│ ^ Unexpected '{'
│
```
…will now be rendered as:
```text
┌─ same_range:1:7
│
1 │ ::S { }
│ ^ Unexpected '{'
│ - Expected '('
│
```
- We've reduced the prominence of the 'locus' on source snippets by
simplifying the border and reducing the spacing around it. This is to help
focus attention on the underlined source snippet and error messages, rather
than the location, which should be a secondary focus.
Example
For example we originally rendered this:
```text
error: unknown builtin: `NATRAL`
┌── Data/Nat.fun:7:13 ───
│
7 │ {-# BUILTIN NATRAL Nat #-}
│ ^^^^^^ unknown builtin
│
= there is a builtin with a similar name: `NATURAL`
```
…and now we render this:
```text
error: unknown builtin: `NATRAL`
┌─ Data/Nat.fun:7:13
│
7 │ {-# BUILTIN NATRAL Nat #-}
│ ^^^^^^ unknown builtin
│
= there is a builtin with a similar name: `NATURAL`
```
## [0.9.2] - 2020-03-29
### Changed
- Render overlapping multiline marks on the same lines of source code.
Example
For example:
```text
error[E0308]: match arms have incompatible types
┌── codespan/src/file.rs:1:9 ───
│
1 │ ╭ match line_index.compare(self.last_line_index()) {
2 │ │ Ordering::Less => Ok(self.line_starts()[line_index.to_usize()]),
3 │ │ Ordering::Equal => Ok(self.source_span().end()),
4 │ │ Ordering::Greater => LineIndexOutOfBoundsError {
5 │ │ given: line_index,
6 │ │ max: self.last_line_index(),
7 │ │ },
8 │ │ }
│ ╰─────────' `match` arms have incompatible types
·
2 │ Ordering::Less => Ok(self.line_starts()[line_index.to_usize()]),
│ --------------------------------------------- this is found to be of type `Result`
3 │ Ordering::Equal => Ok(self.source_span().end()),
│ ---------------------------- this is found to be of type `Result`
4 │ Ordering::Greater => LineIndexOutOfBoundsError {
│ ╭──────────────────────────────────^
5 │ │ given: line_index,
6 │ │ max: self.last_line_index(),
7 │ │ },
│ ╰─────────────^ expected enum `Result`, found struct `LineIndexOutOfBoundsError`
│
= expected type `Result`
found type `LineIndexOutOfBoundsError`
```
…is now rendered as:
```text
error[E0308]: match arms have incompatible types
┌── codespan/src/file.rs:1:9 ───
│
1 │ ╭ match line_index.compare(self.last_line_index()) {
2 │ │ Ordering::Less => Ok(self.line_starts()[line_index.to_usize()]),
│ │ --------------------------------------------- this is found to be of type `Result`
3 │ │ Ordering::Equal => Ok(self.source_span().end()),
│ │ ---------------------------- this is found to be of type `Result`
4 │ │ Ordering::Greater => LineIndexOutOfBoundsError {
│ ╭─│──────────────────────────────────^
5 │ │ │ given: line_index,
6 │ │ │ max: self.last_line_index(),
7 │ │ │ },
│ ╰─│─────────────^ expected enum `Result`, found struct `LineIndexOutOfBoundsError`
8 │ │ }
│ ╰─────────' `match` arms have incompatible types
│
= expected type `Result`
found type `LineIndexOutOfBoundsError`
```
## [0.9.1] - 2020-03-23
### Added
- `codespan_reporting::diagnostic::Diagnostic` now implements `Debug`.
### Changed
- Single-line labels are now rendered together, under the same source line.
Example
For example:
```text
┌── one_line.rs:3:5 ───
│
3 │ v.push(v.pop().unwrap());
│ - first borrow later used by call
·
3 │ v.push(v.pop().unwrap());
│ ---- first mutable borrow occurs here
·
3 │ v.push(v.pop().unwrap());
│ ^ second mutable borrow occurs here
│
```
…is now rendered as:
```text
┌── one_line.rs:3:5 ───
│
3 │ v.push(v.pop().unwrap());
│ - first borrow later used by call
│ ---- first mutable borrow occurs here
│ ^ second mutable borrow occurs here
│
```
## [0.9.0] - 2020-03-11
### Added
- The `codespan_reporting::files` module was added as a way to decouple
`codespan_reporting` from `codespan`.
- `codespan_reporting::files::Files` allows users to implement custom file
databases that work with `codespan_reporting`. This should make it
easier to integrate with libraries like Salsa, and also makes it less
invasive to use `codespan_reporting` on existing projects.
- `codespan_reporting::files::SimpleFile` is a simple implementation of
`codespan_reporting::files::Files` where only a single file is needed.
- `codespan_reporting::files::SimpleFiles` is a simple implementation of
`codespan_reporting::files::Files` where multiple files are needed.
### Changed
- The `codespan_reporting::diagnostic` module has been greatly revamped,
making the builder API format more nicely with rustfmt, and allowing for
multiple primary labels.
- The output of `codespan_reporting::term::emit` was improved,
with the following changes:
- labels on consecutive lines no longer render breaks between them
- source lines are rendered when there is only one line between labels
- the inner gutter of code snippets is now aligned consistently
- the outer gutter of consecutive code snippets are now aligned consistently
- `codespan_reporting::term::emit` now takes writers as a trait object (rather
than using static dispatch) in order to reduce coda bloat and improve
compile times.
- The field names in `codespan_reporting::term::Chars` were tweaked for
consistency.
### Removed
- `codespan_reporting` no longer depends on `codespan`.
Note that `codespan` can _still_ be used with `codespan_reporting`,
as `codespan::Files` now implements `codespan_reporting::files::Files`.
## [0.8.0] - 2020-02-24
## [0.7.0] - 2020-01-06
## [0.6.0] - 2019-12-18
## [0.5.0] - 2019-10-02
## [0.4.1] - 2019-08-25
## [0.4.0] - 2019-08-22
## [0.3.0] - 2019-05-01
## [0.2.1] - 2019-02-26
## [0.2.0] - 2018-10-11
[Unreleased]: https://github.com/brendanzab/codespan/compare/v0.11.1...HEAD
[0.11.1]: https://github.com/brendanzab/codespan/compare/v0.11.0..v0.11.1
[0.11.0]: https://github.com/brendanzab/codespan/compare/v0.9.5...v0.11.0
[0.9.5]: https://github.com/brendanzab/codespan/compare/v0.9.4...v0.9.5
[0.9.4]: https://github.com/brendanzab/codespan/compare/v0.9.3...v0.9.4
[0.9.3]: https://github.com/brendanzab/codespan/compare/v0.9.2...v0.9.3
[0.9.2]: https://github.com/brendanzab/codespan/compare/v0.9.1...v0.9.2
[0.9.1]: https://github.com/brendanzab/codespan/compare/v0.9.0...v0.9.1
[0.9.0]: https://github.com/brendanzab/codespan/compare/v0.8.0...v0.9.0
[0.8.0]: https://github.com/brendanzab/codespan/compare/v0.7.0...v0.8.0
[0.7.0]: https://github.com/brendanzab/codespan/compare/v0.6.0...v0.7.0
[0.6.0]: https://github.com/brendanzab/codespan/compare/v0.5.0...v0.6.0
[0.5.0]: https://github.com/brendanzab/codespan/compare/v0.4.1...v0.5.0
[0.4.1]: https://github.com/brendanzab/codespan/compare/v0.4.0...v0.4.1
[0.4.0]: https://github.com/brendanzab/codespan/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/brendanzab/codespan/compare/v0.2.1...v0.3.0
[0.2.1]: https://github.com/brendanzab/codespan/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/brendanzab/codespan/releases/tag/v0.2.0
codespan-reporting-0.12.0/Cargo.lock 0000644 00000030100 00000000001 0012664 0 ustar # This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anyhow"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9ff2deb543832ee7b1a08060c38cc6af5816e96d3fcb6fc2e99bd15634e5c7f"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
name = "cc"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7db2f146208d7e0fbee761b09cd65a7f51ccc38705d4e7262dad4d73b12a76b1"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "codespan-reporting"
version = "0.12.0"
dependencies = [
"anyhow",
"insta",
"lazy_static",
"peg",
"pico-args",
"rustyline",
"serde",
"termcolor",
"unicode-width",
"unindent",
]
[[package]]
name = "console"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cc80946b3480f421c2f17ed1cb841753a371c7c5104f51d507e13f532c856aa"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"terminal_size",
"winapi",
]
[[package]]
name = "dirs"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
dependencies = [
"cfg-if 0.1.10",
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "dtoa"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5edd69c67b2f8e0911629b7e6b8a34cb3956613cd7c6e6414966dee349c2db4f"
[[package]]
name = "encode_unicode"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8927c1166f271b9c3950500ffada737e31321b43fba0ac2100d954974d2020b5"
[[package]]
name = "getrandom"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if 1.0.0",
"libc",
"wasi",
]
[[package]]
name = "insta"
version = "1.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd354a2c8c8083d58414597a4ecada1984f9b82ea7e87eeabddc869eaf120992"
dependencies = [
"console",
"lazy_static",
"serde",
"serde_json",
"serde_yaml",
"similar",
"uuid",
]
[[package]]
name = "itoa"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libredox"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
dependencies = [
"bitflags 2.4.2",
"libc",
"redox_syscall",
]
[[package]]
name = "linked-hash-map"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "memchr"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01e64d9017d18e7fc09d8e4fe0e28ff6931019e979fb8019319db7ca827f8a6"
dependencies = [
"libc",
]
[[package]]
name = "nix"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
dependencies = [
"bitflags 1.3.2",
"cc",
"cfg-if 0.1.10",
"libc",
"void",
]
[[package]]
name = "peg"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07c0b841ea54f523f7aa556956fbd293bcbe06f2e67d2eb732b7278aaf1d166a"
dependencies = [
"peg-macros",
"peg-runtime",
]
[[package]]
name = "peg-macros"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aa52829b8decbef693af90202711348ab001456803ba2a98eb4ec8fb70844c"
dependencies = [
"peg-runtime",
"proc-macro2",
"quote",
]
[[package]]
name = "peg-runtime"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c719dcf55f09a3a7e764c6649ab594c18a177e3599c467983cdf644bfc0a4088"
[[package]]
name = "pico-args"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
[[package]]
name = "proc-macro2"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_users"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
dependencies = [
"getrandom",
"libredox",
"thiserror",
]
[[package]]
name = "rustyline"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de64be8eecbe428b6924f1d8430369a01719fbb182c26fa431ddbb0a95f5315d"
dependencies = [
"cfg-if 0.1.10",
"dirs",
"libc",
"log",
"memchr",
"nix",
"unicode-segmentation",
"unicode-width",
"utf8parse",
"winapi",
]
[[package]]
name = "ryu"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
[[package]]
name = "serde"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_yaml"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7baae0a99f1a324984bcdc5f0718384c1f69775f1c7eec8b859b71b443e3fd7"
dependencies = [
"dtoa",
"linked-hash-map",
"serde",
"yaml-rust",
]
[[package]]
name = "similar"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a04629d2e8ecdcf30e0188e3699ed6d50d5750d0219db146a790065fe92a897"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "terminal_size"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e288a11a53da73056d3c7cbdee83b1d1ce3344c3210a1f8b56c32f9662a87e9"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "thiserror"
version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-segmentation"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946"
[[package]]
name = "unicode-width"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "unindent"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3508be0ce1bacc38d579b69bffb4b8d469f5af0c388ff4890b2b294e61671ffe"
[[package]]
name = "utf8parse"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d"
[[package]]
name = "uuid"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "yaml-rust"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57ab38ee1a4a266ed033496cf9af1828d8d6e6c1cfa5f643a2809effcae4d628"
dependencies = [
"linked-hash-map",
]
codespan-reporting-0.12.0/Cargo.toml 0000644 00000004376 00000000001 0012727 0 ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.67"
name = "codespan-reporting"
version = "0.12.0"
authors = ["Brendan Zabarauskas "]
build = false
exclude = ["assets/**"]
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Beautiful diagnostic reporting for text-based programming languages"
homepage = "https://github.com/brendanzab/codespan"
documentation = "https://docs.rs/codespan-reporting"
readme = "README.md"
license = "Apache-2.0"
repository = "https://github.com/brendanzab/codespan"
[features]
ascii-only = []
default = [
"std",
"termcolor",
]
serialization = ["serde"]
std = ["serde?/std"]
termcolor = [
"std",
"dep:termcolor",
]
[lib]
name = "codespan_reporting"
path = "src/lib.rs"
[[example]]
name = "custom_files"
path = "examples/custom_files.rs"
[[example]]
name = "peg_calculator"
path = "examples/peg_calculator.rs"
[[example]]
name = "readme_preview"
path = "examples/readme_preview.rs"
[[example]]
name = "reusable_diagnostic"
path = "examples/reusable_diagnostic.rs"
[[example]]
name = "term"
path = "examples/term.rs"
[[test]]
name = "term"
path = "tests/term.rs"
[dependencies.serde]
version = "1"
features = [
"derive",
"alloc",
]
optional = true
default-features = false
[dependencies.termcolor]
version = "1.0.4"
optional = true
[dependencies.unicode-width]
version = ">=0.1,<0.3"
[dev-dependencies.anyhow]
version = "1"
[dev-dependencies.insta]
version = "1.6.3"
[dev-dependencies.lazy_static]
version = "1.4"
[dev-dependencies.peg]
version = "0.7"
[dev-dependencies.pico-args]
version = "0.5.0"
[dev-dependencies.rustyline]
version = "6"
[dev-dependencies.unindent]
version = "0.1"
[lints.clippy]
alloc_instead_of_core = "warn"
std_instead_of_alloc = "warn"
std_instead_of_core = "warn"
codespan-reporting-0.12.0/Cargo.toml.orig 0000644 0000000 0000000 00000002524 10461020230 0016401 0 ustar 0000000 0000000 [package]
name = "codespan-reporting"
version = "0.12.0"
readme = "../README.md"
license = "Apache-2.0"
authors = ["Brendan Zabarauskas "]
description = "Beautiful diagnostic reporting for text-based programming languages"
homepage = "https://github.com/brendanzab/codespan"
repository = "https://github.com/brendanzab/codespan"
documentation = "https://docs.rs/codespan-reporting"
exclude = ["assets/**"]
edition = "2021"
rust-version = "1.67"
[dependencies]
serde = { version = "1", default-features = false, optional = true, features = ["derive", "alloc"] }
termcolor = { version = "1.0.4", optional = true }
unicode-width = ">=0.1,<0.3"
[dev-dependencies]
pico-args = "0.5.0"
anyhow = "1"
insta = "1.6.3"
lazy_static = "1.4"
peg = "0.7"
rustyline = "6"
unindent = "0.1"
[features]
default = ["std", "termcolor"]
std = ["serde?/std"]
termcolor = ["std", "dep:termcolor"]
serialization = ["serde"]
ascii-only = []
[lints.clippy]
# Certain items from `core` are re-exported in `alloc` and `std`, and likewise `alloc` has items
# re-exported in `std`.
# `core` is available on all platforms, `alloc` is available on almost all, and `std` is only
# available on some.
# These lints ensure we don't import from a "less available" crate without reason.
alloc_instead_of_core = "warn"
std_instead_of_alloc = "warn"
std_instead_of_core = "warn" codespan-reporting-0.12.0/LICENSE 0000644 0000000 0000000 00000026135 10461020230 0014523 0 ustar 0000000 0000000 Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
codespan-reporting-0.12.0/README.md 0000644 0000000 0000000 00000013403 10461020230 0014767 0 ustar 0000000 0000000 # codespan-reporting
[![Continuous integration][actions-badge]][actions-url]
[![Crates.io][crate-badge]][crate-url]
[![Docs.rs][docs-badge]][docs-url]
[![Matrix][matrix-badge]][matrix-lobby]
[actions-badge]: https://img.shields.io/github/actions/workflow/status/brendanzab/codespan/ci.yml?branch=master
[actions-url]: https://github.com/brendanzab/codespan/actions
[crate-url]: https://crates.io/crates/codespan-reporting
[crate-badge]: https://img.shields.io/crates/v/codespan-reporting.svg
[docs-url]: https://docs.rs/codespan-reporting
[docs-badge]: https://docs.rs/codespan-reporting/badge.svg
[matrix-badge]: https://img.shields.io/badge/matrix-%23codespan%3Amatrix.org-blue.svg
[matrix-lobby]: https://app.element.io/#/room/#codespan:matrix.org
Beautiful diagnostic reporting for text-based programming languages.

Languages like Rust and Elm already support beautiful error reporting output,
but it can take a significant amount work to implement this for new programming
languages! The `codespan-reporting` crate aims to make beautiful error
diagnostics easy and relatively painless for everyone!
We're still working on improving the crate to help it support broader use cases,
and improving the quality of the diagnostic rendering, so stay tuned for
updates and please give us feedback if you have it. Contributions are also very
welcome!
## Example
```rust
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::SimpleFiles;
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
// `files::SimpleFile` and `files::SimpleFiles` help you get up and running with
// `codespan-reporting` quickly! More complicated use cases can be supported
// by creating custom implementations of the `files::Files` trait.
let mut files = SimpleFiles::new();
let file_id = files.add(
"FizzBuzz.fun",
unindent::unindent(
r#"
module FizzBuzz where
fizz₁ : Nat → String
fizz₁ num = case (mod num 5) (mod num 3) of
0 0 => "FizzBuzz"
0 _ => "Fizz"
_ 0 => "Buzz"
_ _ => num
fizz₂ : Nat → String
fizz₂ num =
case (mod num 5) (mod num 3) of
0 0 => "FizzBuzz"
0 _ => "Fizz"
_ 0 => "Buzz"
_ _ => num
"#,
),
);
// We normally recommend creating a custom diagnostic data type for your
// application, and then converting that to `codespan-reporting`'s diagnostic
// type, but for the sake of this example we construct it directly.
let diagnostic = Diagnostic::error()
.with_message("`case` clauses have incompatible types")
.with_code("E0308")
.with_labels(vec![
Label::primary(file_id, 328..331).with_message("expected `String`, found `Nat`"),
Label::secondary(file_id, 211..331).with_message("`case` clauses have incompatible types"),
Label::secondary(file_id, 258..268).with_message("this is found to be of type `String`"),
Label::secondary(file_id, 284..290).with_message("this is found to be of type `String`"),
Label::secondary(file_id, 306..312).with_message("this is found to be of type `String`"),
Label::secondary(file_id, 186..192).with_message("expected type `String` found here"),
])
.with_notes(vec![unindent::unindent(
"
expected type `String`
found type `Nat`
",
)]);
// We now set up the writer and configuration, and then finally render the
// diagnostic to standard error.
let writer = StandardStream::stderr(ColorChoice::Always);
let config = codespan_reporting::term::Config::default();
term::emit(&mut writer.lock(), &config, &files, &diagnostic)?;
```
## Running the CLI example
To get an idea of what the colored CLI output looks like,
clone the [repository](https://github.com/brendanzab/codespan)
and run the following shell command:
```sh
cargo run --example term
```
More examples of using `codespan-reporting` can be found in the
[examples directory](./codespan-reporting/examples).
## Projects using codespan-reporting
`codespan-reporting` is currently used in the following projects:
- [cargo-deny](https://github.com/EmbarkStudios/cargo-deny)
- [cargo-about](https://github.com/EmbarkStudios/cargo-about)
- [CXX](https://github.com/dtolnay/cxx)
- [full_moon](https://github.com/Kampfkarren/full-moon)
- [Gleam](https://github.com/gleam-lang/gleam)
- [Gluon](https://github.com/gluon-lang/gluon)
- [MDBook LinkCheck](https://github.com/Michael-F-Bryan/mdbook-linkcheck)
- [mos](https://github.com/datatrash/mos)
- [Pikelet](https://github.com/pikelet-lang/pikelet)
- [Naga](https://github.com/gfx-rs/wgpu/tree/trunk/naga)
- [Spade](https://gitlab.com/spade-lang/spade)
... [any many more](https://crates.io/crates/codespan-reporting/reverse_dependencies)
## Alternatives to codespan-reporting
There are a number of alternatives to `codespan-reporting`, including:
- [annotate-snippets][annotate-snippets]
- [codemap][codemap]
- [language-reporting][language-reporting] (a fork of codespan)
These are all ultimately inspired by rustc's excellent [error reporting infrastructure][librustc_errors].
[annotate-snippets]: https://crates.io/crates/annotate-snippets
[codemap]: https://crates.io/crates/codemap
[language-reporting]: https://crates.io/crates/language-reporting
[librustc_errors]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_errors/src
## Contributing
A guide to contributing to codespan-reporting [can be found here](/CONTRIBUTING.md).
## Code of Conduct
Please note that this project is released with a [Code of Conduct](./CODE_OF_CONDUCT.md).
By participating in this project you agree to abide by its terms.
codespan-reporting-0.12.0/examples/custom_files.rs 0000644 0000000 0000000 00000013777 10461020230 0020406 0 ustar 0000000 0000000 //! An example that shows how to implement a simple custom file database.
//! The database uses 32-bit file-ids, which could be useful for optimizing
//! memory usage.
//!
//! To run this example, execute the following command from the top level of
//! this repository:
//!
//! ```sh
//! cargo run --example custom_files
//! ```
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::term;
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
use core::ops::Range;
fn main() -> anyhow::Result<()> {
let mut files = files::Files::new();
let file_id0 = files.add("0.greeting", "hello world!").unwrap();
let file_id1 = files.add("1.greeting", "bye world").unwrap();
let messages = vec![
Message::UnwantedGreetings {
greetings: vec![(file_id0, 0..5), (file_id1, 0..3)],
},
Message::OverTheTopExclamations {
exclamations: vec![(file_id0, 11..12)],
},
];
let writer = StandardStream::stderr(ColorChoice::Always);
let config = term::Config::default();
for message in &messages {
let writer = &mut writer.lock();
term::emit(writer, &config, &files, &message.to_diagnostic())?;
}
Ok(())
}
/// A module containing the file implementation
mod files {
use codespan_reporting::files;
use core::ops::Range;
/// A file that is backed by an `Arc`.
#[derive(Debug, Clone)]
struct File {
/// The name of the file.
name: String,
/// The source code of the file.
source: String,
/// The starting byte indices in the source code.
line_starts: Vec,
}
impl File {
fn line_start(&self, line_index: usize) -> Result {
use core::cmp::Ordering;
match line_index.cmp(&self.line_starts.len()) {
Ordering::Less => Ok(*self
.line_starts
.get(line_index)
.expect("failed despite previous check")),
Ordering::Equal => Ok(self.source.len()),
Ordering::Greater => Err(files::Error::LineTooLarge {
given: line_index,
max: self.line_starts.len() - 1,
}),
}
}
}
/// An opaque file identifier.
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct FileId(u32);
#[derive(Debug, Clone)]
pub struct Files {
files: Vec,
}
impl Files {
/// Create a new files database.
pub fn new() -> Files {
Files { files: Vec::new() }
}
/// Add a file to the database, returning the handle that can be used to
/// refer to it again.
pub fn add(
&mut self,
name: impl Into,
source: impl Into,
) -> Option {
use core::convert::TryFrom;
let file_id = FileId(u32::try_from(self.files.len()).ok()?);
let name = name.into();
let source = source.into();
let line_starts = files::line_starts(&source).collect();
self.files.push(File {
name,
line_starts,
source,
});
Some(file_id)
}
/// Get the file corresponding to the given id.
fn get(&self, file_id: FileId) -> Result<&File, files::Error> {
self.files
.get(file_id.0 as usize)
.ok_or(files::Error::FileMissing)
}
}
impl<'files> files::Files<'files> for Files {
type FileId = FileId;
type Name = &'files str;
type Source = &'files str;
fn name(&self, file_id: FileId) -> Result<&str, files::Error> {
Ok(self.get(file_id)?.name.as_ref())
}
fn source(&self, file_id: FileId) -> Result<&str, files::Error> {
Ok(&self.get(file_id)?.source)
}
fn line_index(&self, file_id: FileId, byte_index: usize) -> Result {
self.get(file_id)?
.line_starts
.binary_search(&byte_index)
.or_else(|next_line| Ok(next_line - 1))
}
fn line_range(
&self,
file_id: FileId,
line_index: usize,
) -> Result, files::Error> {
let file = self.get(file_id)?;
let line_start = file.line_start(line_index)?;
let next_line_start = file.line_start(line_index + 1)?;
Ok(line_start..next_line_start)
}
}
}
/// A Diagnostic message.
enum Message {
UnwantedGreetings {
greetings: Vec<(files::FileId, Range)>,
},
OverTheTopExclamations {
exclamations: Vec<(files::FileId, Range)>,
},
}
impl Message {
fn to_diagnostic(&self) -> Diagnostic {
match self {
Message::UnwantedGreetings { greetings } => Diagnostic::error()
.with_message("greetings are not allowed")
.with_labels(
greetings
.iter()
.map(|(file_id, range)| {
Label::primary(*file_id, range.clone()).with_message("a greeting")
})
.collect(),
)
.with_notes(vec![
"found greetings!".to_owned(),
"pleas no greetings :(".to_owned(),
]),
Message::OverTheTopExclamations { exclamations } => Diagnostic::error()
.with_message("over-the-top exclamations")
.with_labels(
exclamations
.iter()
.map(|(file_id, range)| {
Label::primary(*file_id, range.clone()).with_message("an exclamation")
})
.collect(),
)
.with_notes(vec!["ridiculous!".to_owned()]),
}
}
}
codespan-reporting-0.12.0/examples/peg_calculator.rs 0000644 0000000 0000000 00000004305 10461020230 0020661 0 ustar 0000000 0000000 //! An example of using `peg` with `codespan_reporting`.
//!
//! To run this example, execute the following command from the top level of
//! this repository:
//!
//! ```sh
//! cargo run --example peg_calculator
//! ```
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::SimpleFile;
use codespan_reporting::term;
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
use rustyline::error::ReadlineError;
use rustyline::Editor;
#[allow(clippy::redundant_closure_call)]
peg::parser! {
grammar arithmetic() for str {
rule number() -> i64
= n:$(['0'..='9']+) { n.parse().unwrap() }
pub rule calculate() -> i64 = precedence!{
x:(@) "+" y:@ { x + y }
x:(@) "-" y:@ { x - y }
"-" v:@ { - v }
--
x:(@) "*" y:@ { x * y }
x:(@) "/" y:@ { x / y }
--
x:@ "^" y:(@) { i64::pow(x, y as u32) }
v:@ "!" { (1..v+1).product() }
--
"(" v:calculate() ")" { v }
n:number() { n }
}
}
}
fn main() -> anyhow::Result<()> {
let writer = StandardStream::stderr(ColorChoice::Always);
let config = codespan_reporting::term::Config::default();
let mut editor = Editor::<()>::new();
loop {
let line = match editor.readline("> ") {
Ok(line) => line,
Err(ReadlineError::Interrupted) | Err(ReadlineError::Eof) => return Ok(()),
Err(error) => return Err(error.into()),
};
match arithmetic::calculate(&line) {
Ok(number) => println!("{}", number),
Err(error) => {
let file = SimpleFile::new("", line);
let start = error.location.offset;
let diagnostic = Diagnostic::error()
.with_message("parse error")
.with_labels(vec![
Label::primary((), start..start).with_message("parse error")
])
.with_notes(vec![format!("expected: {}", error.expected)]);
term::emit(&mut writer.lock(), &config, &file, &diagnostic)?;
}
}
}
}
codespan-reporting-0.12.0/examples/readme_preview.rs 0000644 0000000 0000000 00000026014 10461020230 0020674 0 ustar 0000000 0000000 //! Renders the preview SVG for the README.
//!
//! To update the preview, execute the following command from the top level of
//! the repository:
//!
//! ```sh
//! cargo run --example readme_preview svg > codespan-reporting/assets/readme_preview.svg
//! ```
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::SimpleFile;
use codespan_reporting::term::termcolor::{
Color, ColorChoice, ColorSpec, StandardStream, WriteColor,
};
use codespan_reporting::term::{self};
use std::io::{self, Write};
#[derive(Debug)]
pub enum Opts {
/// Render SVG output
Svg,
/// Render Stderr output
Stderr {
/// Configure coloring of output
color: ColorChoice,
},
}
fn parse_args() -> Result {
let mut pargs = pico_args::Arguments::from_env();
match pargs.subcommand()? {
Some(value) => match value.as_str() {
"svg" => Ok(Opts::Svg),
"stderr" => {
let color = pargs
.opt_value_from_str("--color")?
.unwrap_or(ColorChoice::Auto);
Ok(Opts::Stderr { color })
}
_ => Err(pico_args::Error::Utf8ArgumentParsingFailed {
value,
cause: "not a valid subcommand".to_owned(),
}),
},
None => Err(pico_args::Error::MissingArgument),
}
}
fn main() -> anyhow::Result<()> {
let file = SimpleFile::new(
"FizzBuzz.fun",
unindent::unindent(
r#"
module FizzBuzz where
fizz₁ : Nat → String
fizz₁ num = case (mod num 5) (mod num 3) of
0 0 => "FizzBuzz"
0 _ => "Fizz"
_ 0 => "Buzz"
_ _ => num
fizz₂ : Nat → String
fizz₂ num =
case (mod num 5) (mod num 3) of
0 0 => "FizzBuzz"
0 _ => "Fizz"
_ 0 => "Buzz"
_ _ => num
"#,
),
);
let diagnostics = [Diagnostic::error()
.with_message("`case` clauses have incompatible types")
.with_code("E0308")
.with_labels(vec![
Label::primary((), 328..331).with_message("expected `String`, found `Nat`"),
Label::secondary((), 211..331).with_message("`case` clauses have incompatible types"),
Label::secondary((), 258..268).with_message("this is found to be of type `String`"),
Label::secondary((), 284..290).with_message("this is found to be of type `String`"),
Label::secondary((), 306..312).with_message("this is found to be of type `String`"),
Label::secondary((), 186..192).with_message("expected type `String` found here"),
])
.with_notes(vec![unindent::unindent(
"
expected type `String`
found type `Nat`
",
)])];
match parse_args()? {
Opts::Svg => {
let mut buffer = Vec::new();
let mut writer = HtmlEscapeWriter::new(SvgWriter::new(&mut buffer));
let config = codespan_reporting::term::Config {
#[cfg(feature = "termcolor")]
styles: codespan_reporting::term::Styles::with_blue(Color::Blue),
..codespan_reporting::term::Config::default()
};
for diagnostic in &diagnostics {
term::emit(&mut writer, &config, &file, diagnostic)?;
}
let num_lines = buffer.iter().filter(|byte| **byte == b'\n').count() + 1;
let padding = 10;
let font_size = 12;
let line_spacing = 3;
let width = 882;
let height = padding + num_lines * (font_size + line_spacing) + padding;
let stdout = std::io::stdout();
let writer = &mut stdout.lock();
write!(
writer,
r#"
"
)?;
}
Opts::Stderr { color } => {
let writer = StandardStream::stderr(color);
let config = codespan_reporting::term::Config::default();
for diagnostic in &diagnostics {
term::emit(&mut writer.lock(), &config, &file, diagnostic)?;
}
}
}
Ok(())
}
/// Rudimentary HTML escaper which performs the following conversions:
///
/// - `<` ⇒ `<`
/// - `>` ⇒ `>`
/// - `&` ⇒ `&`
pub struct HtmlEscapeWriter {
upstream: W,
}
impl HtmlEscapeWriter {
pub fn new(upstream: W) -> HtmlEscapeWriter {
HtmlEscapeWriter { upstream }
}
}
impl Write for HtmlEscapeWriter {
fn write(&mut self, buf: &[u8]) -> io::Result {
let mut last_term = 0usize;
for (i, byte) in buf.iter().enumerate() {
let escape = match byte {
b'<' => &b"<"[..],
b'>' => &b">"[..],
b'&' => &b"&"[..],
_ => continue,
};
self.upstream.write_all(&buf[last_term..i])?;
last_term = i + 1;
self.upstream.write_all(escape)?;
}
self.upstream.write_all(&buf[last_term..])?;
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
self.upstream.flush()
}
}
impl WriteColor for HtmlEscapeWriter {
fn supports_color(&self) -> bool {
self.upstream.supports_color()
}
fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
self.upstream.set_color(spec)
}
fn reset(&mut self) -> io::Result<()> {
self.upstream.reset()
}
}
pub struct SvgWriter {
upstream: W,
color: ColorSpec,
}
impl SvgWriter {
pub fn new(upstream: W) -> SvgWriter {
SvgWriter {
upstream,
color: ColorSpec::new(),
}
}
}
impl Write for SvgWriter {
fn write(&mut self, buf: &[u8]) -> io::Result {
self.upstream.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.upstream.flush()
}
}
impl WriteColor for SvgWriter {
fn supports_color(&self) -> bool {
true
}
fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
#![allow(unused_assignments)]
if self.color == *spec {
return Ok(());
} else {
if !self.color.is_none() {
write!(self, "")?;
}
self.color = spec.clone();
}
if spec.is_none() {
write!(self, "")?;
return Ok(());
} else {
write!(self, "(first: bool, writer: &mut SvgWriter) -> io::Result {
if !first {
write!(writer, " ")?;
}
Ok(false)
}
fn write_color(color: &Color, writer: &mut SvgWriter) -> io::Result<()> {
match color {
Color::Black => write!(writer, "black"),
Color::Blue => write!(writer, "blue"),
Color::Green => write!(writer, "green"),
Color::Red => write!(writer, "red"),
Color::Cyan => write!(writer, "cyan"),
Color::Magenta => write!(writer, "magenta"),
Color::Yellow => write!(writer, "yellow"),
Color::White => write!(writer, "white"),
// TODO: other colors
_ => Ok(()),
}
}
if let Some(fg) = spec.fg() {
first = write_first(first, self)?;
write!(self, "fg ")?;
write_color(fg, self)?;
}
if let Some(bg) = spec.bg() {
first = write_first(first, self)?;
write!(self, "bg ")?;
write_color(bg, self)?;
}
if spec.bold() {
first = write_first(first, self)?;
write!(self, "bold")?;
}
if spec.underline() {
first = write_first(first, self)?;
write!(self, "underline")?;
}
if spec.intense() {
first = write_first(first, self)?;
write!(self, "bright")?;
}
write!(self, "\">")?;
Ok(())
}
fn reset(&mut self) -> io::Result<()> {
let color = self.color.clone();
if color != ColorSpec::new() {
write!(self, "")?;
self.color = ColorSpec::new();
}
Ok(())
}
}
codespan-reporting-0.12.0/examples/reusable_diagnostic.rs 0000644 0000000 0000000 00000006557 10461020230 0021716 0 ustar 0000000 0000000 use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::SimpleFile;
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
use codespan_reporting::term::{self};
use core::ops::Range;
#[derive(Debug)]
pub struct Opts {
color: ColorChoice,
}
fn parse_args() -> Result {
let mut pargs = pico_args::Arguments::from_env();
let color = pargs
.opt_value_from_str("--color")?
.unwrap_or(ColorChoice::Auto);
Ok(Opts { color })
}
fn main() -> anyhow::Result<()> {
let file = SimpleFile::new(
"main.rs",
unindent::unindent(
r#"
fn main() {
let foo: i32 = "hello, world";
foo += 1;
}
"#,
),
);
let errors = [
Error::MismatchType(
Item::new(20..23, "i32"),
Item::new(31..45, "\"hello, world\""),
),
Error::MutatingImmutable(Item::new(20..23, "foo"), Item::new(51..59, "foo += 1")),
];
let Opts { color } = parse_args()?;
let writer = StandardStream::stderr(color);
let config = codespan_reporting::term::Config::default();
for diagnostic in errors.iter().map(Error::report) {
term::emit(&mut writer.lock(), &config, &file, &diagnostic)?;
}
Ok(())
}
/// An error enum that represent all possible errors within your program
enum Error {
MismatchType(Item, Item),
MutatingImmutable(Item, Item),
}
impl Error {
fn report(&self) -> Diagnostic<()> {
match self {
Error::MismatchType(left, right) => Diagnostic::error()
.with_code("E0308")
.with_message("mismatch types")
.with_labels(vec![
Label::primary((), right.range.clone()).with_message(format!(
"Expected `{}`, found: `{}`",
left.content, right.content,
)),
Label::secondary((), left.range.clone()).with_message("expected due to this"),
]),
Error::MutatingImmutable(original, mutating) => Diagnostic::error()
.with_code("E0384")
.with_message(format!(
"cannot mutate immutable variable `{}`",
original.content,
))
.with_labels(vec![
Label::secondary((), original.range.clone()).with_message(unindent::unindent(
&format!(
r#"
first assignment to `{0}`
help: make this binding mutable: `mut {0}`
"#,
original.content,
),
)),
Label::primary((), mutating.range.clone())
.with_message("cannot assign twice to immutable variable"),
]),
}
}
}
/// An item in the source code to be used in the `Error` enum.
/// In a more complex program it could also contain a `files::FileId` to handle errors that occur inside multiple files.
struct Item {
range: Range,
content: String,
}
impl Item {
fn new(range: Range, content: impl Into) -> Item {
let content = content.into();
Item { range, content }
}
}
codespan-reporting-0.12.0/examples/term.rs 0000644 0000000 0000000 00000013366 10461020230 0016653 0 ustar 0000000 0000000 //! To run this example, execute the following command from the top level of
//! this repository:
//!
//! ```sh
//! cargo run --example term
//! ```
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::SimpleFiles;
use codespan_reporting::term;
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
#[derive(Debug)]
pub struct Opts {
/// Configure coloring of output
pub color: ColorChoice,
}
fn parse_args() -> Result {
let mut pargs = pico_args::Arguments::from_env();
let color = pargs
.opt_value_from_str("--color")?
.unwrap_or(ColorChoice::Auto);
Ok(Opts { color })
}
fn main() -> anyhow::Result<()> {
let Opts { color } = parse_args()?;
let mut files = SimpleFiles::new();
let file_id1 = files.add(
"Data/Nat.fun",
unindent::unindent(
"
module Data.Nat where
data Nat : Type where
zero : Nat
succ : Nat → Nat
{-# BUILTIN NATRAL Nat #-}
infixl 6 _+_ _-_
_+_ : Nat → Nat → Nat
zero + n₂ = n₂
succ n₁ + n₂ = succ (n₁ + n₂)
_-_ : Nat → Nat → Nat
n₁ - zero = n₁
zero - succ n₂ = zero
succ n₁ - succ n₂ = n₁ - n₂
",
),
);
let file_id2 = files.add(
"Test.fun",
unindent::unindent(
r#"
module Test where
_ : Nat
_ = 123 + "hello"
"#,
),
);
let file_id3 = files.add(
"FizzBuzz.fun",
unindent::unindent(
r#"
module FizzBuzz where
fizz₁ : Nat → String
fizz₁ num = case (mod num 5) (mod num 3) of
0 0 => "FizzBuzz"
0 _ => "Fizz"
_ 0 => "Buzz"
_ _ => num
fizz₂ : Nat → String
fizz₂ num =
case (mod num 5) (mod num 3) of
0 0 => "FizzBuzz"
0 _ => "Fizz"
_ 0 => "Buzz"
_ _ => num
"#,
),
);
let diagnostics = [
// Unknown builtin error
Diagnostic::error()
.with_message("unknown builtin: `NATRAL`")
.with_labels(vec![
Label::primary(file_id1, 96..102).with_message("unknown builtin")
])
.with_notes(vec![
"there is a builtin with a similar name: `NATURAL`".to_owned()
]),
// Unused parameter warning
Diagnostic::warning()
.with_message("unused parameter pattern: `n₂`")
.with_labels(vec![
Label::primary(file_id1, 285..289).with_message("unused parameter")
])
.with_notes(vec!["consider using a wildcard pattern: `_`".to_owned()]),
// Unexpected type error
Diagnostic::error()
.with_message("unexpected type in application of `_+_`")
.with_code("E0001")
.with_labels(vec![
Label::primary(file_id2, 37..44).with_message("expected `Nat`, found `String`"),
Label::secondary(file_id1, 130..155)
.with_message("based on the definition of `_+_`"),
])
.with_notes(vec![unindent::unindent(
"
expected type `Nat`
found type `String`
",
)]),
// Incompatible match clause error
Diagnostic::error()
.with_message("`case` clauses have incompatible types")
.with_code("E0308")
.with_labels(vec![
Label::primary(file_id3, 163..166).with_message("expected `String`, found `Nat`"),
Label::secondary(file_id3, 62..166)
.with_message("`case` clauses have incompatible types"),
Label::secondary(file_id3, 41..47)
.with_message("expected type `String` found here"),
])
.with_notes(vec![unindent::unindent(
"
expected type `String`
found type `Nat`
",
)]),
// Incompatible match clause error
Diagnostic::error()
.with_message("`case` clauses have incompatible types")
.with_code("E0308")
.with_labels(vec![
Label::primary(file_id3, 328..331).with_message("expected `String`, found `Nat`"),
Label::secondary(file_id3, 211..331)
.with_message("`case` clauses have incompatible types"),
Label::secondary(file_id3, 258..268)
.with_message("this is found to be of type `String`"),
Label::secondary(file_id3, 284..290)
.with_message("this is found to be of type `String`"),
Label::secondary(file_id3, 306..312)
.with_message("this is found to be of type `String`"),
Label::secondary(file_id3, 186..192)
.with_message("expected type `String` found here"),
])
.with_notes(vec![unindent::unindent(
"
expected type `String`
found type `Nat`
",
)]),
];
let writer = StandardStream::stderr(color);
let config = codespan_reporting::term::Config::default();
for diagnostic in &diagnostics {
term::emit(&mut writer.lock(), &config, &files, diagnostic)?;
}
Ok(())
}
codespan-reporting-0.12.0/src/diagnostic.rs 0000644 0000000 0000000 00000016022 10461020230 0016771 0 ustar 0000000 0000000 //! Diagnostic data structures.
use alloc::{
string::{String, ToString},
vec::Vec,
};
use core::ops::Range;
#[cfg(feature = "serialization")]
use serde::{Deserialize, Serialize};
/// A severity level for diagnostic messages.
///
/// These are ordered in the following way:
///
/// ```rust
/// use codespan_reporting::diagnostic::Severity;
///
/// assert!(Severity::Bug > Severity::Error);
/// assert!(Severity::Error > Severity::Warning);
/// assert!(Severity::Warning > Severity::Note);
/// assert!(Severity::Note > Severity::Help);
/// ```
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub enum Severity {
/// A help message.
Help,
/// A note.
Note,
/// A warning.
Warning,
/// An error.
Error,
/// An unexpected bug.
Bug,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub enum LabelStyle {
/// Labels that describe the primary cause of a diagnostic.
Primary,
/// Labels that provide additional context for a diagnostic.
Secondary,
}
/// A label describing an underlined region of code associated with a diagnostic.
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct Label {
/// The style of the label.
pub style: LabelStyle,
/// The file that we are labelling.
pub file_id: FileId,
/// The range in bytes we are going to include in the final snippet.
pub range: Range,
/// An optional message to provide some additional information for the
/// underlined code. These should not include line breaks.
pub message: String,
}
impl Label {
/// Create a new label.
pub fn new(
style: LabelStyle,
file_id: FileId,
range: impl Into>,
) -> Label {
Label {
style,
file_id,
range: range.into(),
message: String::new(),
}
}
/// Create a new label with a style of [`LabelStyle::Primary`].
///
/// [`LabelStyle::Primary`]: LabelStyle::Primary
pub fn primary(file_id: FileId, range: impl Into>) -> Label {
Label::new(LabelStyle::Primary, file_id, range)
}
/// Create a new label with a style of [`LabelStyle::Secondary`].
///
/// [`LabelStyle::Secondary`]: LabelStyle::Secondary
pub fn secondary(file_id: FileId, range: impl Into>) -> Label {
Label::new(LabelStyle::Secondary, file_id, range)
}
/// Add a message to the diagnostic.
pub fn with_message(mut self, message: impl ToString) -> Label {
self.message = message.to_string();
self
}
}
/// Represents a diagnostic message that can provide information like errors and
/// warnings to the user.
///
/// The position of a Diagnostic is considered to be the position of the [`Label`] that has the earliest starting position and has the highest style which appears in all the labels of the diagnostic.
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct Diagnostic {
/// The overall severity of the diagnostic
pub severity: Severity,
/// An optional code that identifies this diagnostic.
pub code: Option,
/// The main message associated with this diagnostic.
///
/// These should not include line breaks, and in order support the 'short'
/// diagnostic display mod, the message should be specific enough to make
/// sense on its own, without additional context provided by labels and notes.
pub message: String,
/// Source labels that describe the cause of the diagnostic.
/// The order of the labels inside the vector does not have any meaning.
/// The labels are always arranged in the order they appear in the source code.
pub labels: Vec