From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/annotate-snippets/.cargo-checksum.json | 1 + vendor/annotate-snippets/CHANGELOG.md | 39 ++ vendor/annotate-snippets/Cargo.lock | 631 +++++++++++++++++++ vendor/annotate-snippets/Cargo.toml | 65 ++ vendor/annotate-snippets/LICENSE-APACHE | 201 ++++++ vendor/annotate-snippets/LICENSE-MIT | 19 + vendor/annotate-snippets/README.md | 90 +++ vendor/annotate-snippets/benches/simple.rs | 74 +++ vendor/annotate-snippets/examples/expected_type.rs | 43 ++ vendor/annotate-snippets/examples/footer.rs | 39 ++ vendor/annotate-snippets/examples/format.rs | 61 ++ vendor/annotate-snippets/examples/multislice.rs | 38 ++ .../src/display_list/from_snippet.rs | 594 ++++++++++++++++++ vendor/annotate-snippets/src/display_list/mod.rs | 37 ++ .../annotate-snippets/src/display_list/structs.rs | 308 ++++++++++ vendor/annotate-snippets/src/formatter/mod.rs | 456 ++++++++++++++ vendor/annotate-snippets/src/formatter/style.rs | 51 ++ vendor/annotate-snippets/src/lib.rs | 54 ++ vendor/annotate-snippets/src/snippet.rs | 88 +++ vendor/annotate-snippets/src/stylesheets/color.rs | 50 ++ vendor/annotate-snippets/src/stylesheets/mod.rs | 11 + .../annotate-snippets/src/stylesheets/no_color.rs | 31 + vendor/annotate-snippets/tests/diff/mod.rs | 43 ++ vendor/annotate-snippets/tests/dl_from_snippet.rs | 407 +++++++++++++ .../tests/fixtures/no-color/issue_9.toml | 28 + .../tests/fixtures/no-color/issue_9.txt | 12 + .../fixtures/no-color/multiline_annotation.toml | 40 ++ .../fixtures/no-color/multiline_annotation.txt | 14 + .../fixtures/no-color/multiline_annotation2.toml | 18 + .../fixtures/no-color/multiline_annotation2.txt | 9 + .../fixtures/no-color/multiline_annotation3.toml | 18 + .../fixtures/no-color/multiline_annotation3.txt | 9 + .../fixtures/no-color/multiple_annotations.toml | 25 + .../fixtures/no-color/multiple_annotations.txt | 14 + .../tests/fixtures/no-color/simple.toml | 18 + .../tests/fixtures/no-color/simple.txt | 9 + .../tests/fixtures/no-color/strip_line.toml | 25 + .../tests/fixtures/no-color/strip_line.txt | 6 + .../tests/fixtures/no-color/strip_line_char.toml | 25 + .../tests/fixtures/no-color/strip_line_char.txt | 6 + .../tests/fixtures/no-color/strip_line_non_ws.toml | 25 + .../tests/fixtures/no-color/strip_line_non_ws.txt | 6 + vendor/annotate-snippets/tests/fixtures_test.rs | 45 ++ vendor/annotate-snippets/tests/formatter.rs | 675 +++++++++++++++++++++ vendor/annotate-snippets/tests/snippet/mod.rs | 208 +++++++ 45 files changed, 4666 insertions(+) create mode 100644 vendor/annotate-snippets/.cargo-checksum.json create mode 100644 vendor/annotate-snippets/CHANGELOG.md create mode 100644 vendor/annotate-snippets/Cargo.lock create mode 100644 vendor/annotate-snippets/Cargo.toml create mode 100644 vendor/annotate-snippets/LICENSE-APACHE create mode 100644 vendor/annotate-snippets/LICENSE-MIT create mode 100644 vendor/annotate-snippets/README.md create mode 100644 vendor/annotate-snippets/benches/simple.rs create mode 100644 vendor/annotate-snippets/examples/expected_type.rs create mode 100644 vendor/annotate-snippets/examples/footer.rs create mode 100644 vendor/annotate-snippets/examples/format.rs create mode 100644 vendor/annotate-snippets/examples/multislice.rs create mode 100644 vendor/annotate-snippets/src/display_list/from_snippet.rs create mode 100644 vendor/annotate-snippets/src/display_list/mod.rs create mode 100644 vendor/annotate-snippets/src/display_list/structs.rs create mode 100644 vendor/annotate-snippets/src/formatter/mod.rs create mode 100644 vendor/annotate-snippets/src/formatter/style.rs create mode 100644 vendor/annotate-snippets/src/lib.rs create mode 100644 vendor/annotate-snippets/src/snippet.rs create mode 100644 vendor/annotate-snippets/src/stylesheets/color.rs create mode 100644 vendor/annotate-snippets/src/stylesheets/mod.rs create mode 100644 vendor/annotate-snippets/src/stylesheets/no_color.rs create mode 100644 vendor/annotate-snippets/tests/diff/mod.rs create mode 100644 vendor/annotate-snippets/tests/dl_from_snippet.rs create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/issue_9.toml create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/issue_9.txt create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation.toml create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation.txt create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation2.toml create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation2.txt create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation3.toml create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation3.txt create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/multiple_annotations.toml create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/multiple_annotations.txt create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/simple.toml create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/simple.txt create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/strip_line.toml create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/strip_line.txt create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/strip_line_char.toml create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/strip_line_char.txt create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/strip_line_non_ws.toml create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/strip_line_non_ws.txt create mode 100644 vendor/annotate-snippets/tests/fixtures_test.rs create mode 100644 vendor/annotate-snippets/tests/formatter.rs create mode 100644 vendor/annotate-snippets/tests/snippet/mod.rs (limited to 'vendor/annotate-snippets') diff --git a/vendor/annotate-snippets/.cargo-checksum.json b/vendor/annotate-snippets/.cargo-checksum.json new file mode 100644 index 000000000..14ba1bf1d --- /dev/null +++ b/vendor/annotate-snippets/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"e3cf6a35ca22d7898f1b14938a189a767f6fe430fc6b1595c0876b001f7a52de","Cargo.lock":"e5575e69ba2ee2b78aaa1674598bad77826eb49f1e8bcf20686b5223f372136c","Cargo.toml":"a5d510a1dbb1161e583a3bab5843af210c4d11370e1ca88e4cc105e5d2f1a003","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-MIT":"49c0b000c03731d9e3970dc059ad4ca345d773681f4a612b0024435b663e0220","README.md":"c174167ec0fee28675ff9af5073c6e760cb9874193e7f9efb0165778d0607aff","benches/simple.rs":"f85dd74583e3addba780b2c136f250197155e173f09472ae106ebca96006ae76","examples/expected_type.rs":"23690a4b176e4aa82abe4d009a291b076c9ca58f2adf57ecbd1a207261b863d2","examples/footer.rs":"77bcb981711091d93b4fbfbbe318f262d90996485aa012ba3ff95ebd4dc3085f","examples/format.rs":"72f47847ce0b0a1025b56642a5b3fe191aaac775c16f42d76417362234298393","examples/multislice.rs":"bf10fc20f1948e6b0f325ed486ddf1b44e9a99fd22226012b81c5608846de983","src/display_list/from_snippet.rs":"c89f76e5c2de521de43b57031cf413899764f66f81808df0b02574f5f82012a6","src/display_list/mod.rs":"a6aebdc9d666801280623b72798cfaae9172cb6f686ab9ef6c79a31dab6ef044","src/display_list/structs.rs":"c970617ace1ea3968c906a0d71f189665b9b6607960e2482ee4c8bb92f520c61","src/formatter/mod.rs":"a5d24305bd1514bd00021ca87296e601f721cbd2b32337b9ec149d308b3ec951","src/formatter/style.rs":"7b038f6ce86d4fb2aa66b00d27ecfe5603dda838f06b2089f8c6869331543d93","src/lib.rs":"31c052d00b1ac1a05ae357dc2d8bf089c3c5ecdbee51713c89403856eb13b884","src/snippet.rs":"14a875640ac81eca9a29c351b5a99bb8e88a2970bcdddcf2ce1658de2fcbab85","src/stylesheets/color.rs":"5f8049f41a8d9636e55975e999e7c149d4b54b65b2518ea88be1ae69323b21a1","src/stylesheets/mod.rs":"852914a13832d777f2ddd7489af9e9d80cf2b6df09b1be7401e8f2947f4baf72","src/stylesheets/no_color.rs":"854529529a061df5cab0bf889ac43cb6d0203e674be38ae1cfb6724729beac31","tests/diff/mod.rs":"6e760d4bfda064934646da1461b940ef5ca1416a57428bda47871bb116f7add0","tests/dl_from_snippet.rs":"a0b0c13bb05ee7d03703a57b35c01485d178ad2bea331bfcbc5151d88a72648e","tests/fixtures/no-color/issue_9.toml":"e25ee4d92cc1009d9f66bf952872136e42ba4845076aff542c799c950641a115","tests/fixtures/no-color/issue_9.txt":"b4b464c7042d68b5517086d0f1088fda46fa35f7830864ee91574bdefe3a3018","tests/fixtures/no-color/multiline_annotation.toml":"e7f93a11beed9b32db16c326f66e0fa08dccdc01230a4785d3c35fec8acee085","tests/fixtures/no-color/multiline_annotation.txt":"ee33c4a17fc72095f217a78f479c3718ad5499d745e4248937f7eaa028ee4328","tests/fixtures/no-color/multiline_annotation2.toml":"0a833999fc0bf9b6ee7eab77a9cdf5343f7ba8f4243190a61b9adaa60fc425ac","tests/fixtures/no-color/multiline_annotation2.txt":"4cdd277194e08b8f38b3045e08f3c180982b576029af66cae7519f43bfd81ca6","tests/fixtures/no-color/multiline_annotation3.toml":"93badadaaffca9382c25ac9286006b4aa59747a1e2cc2c717e003dbdd841c1a5","tests/fixtures/no-color/multiline_annotation3.txt":"66ee253f2566e40e69e8fdfb9837ee803c26bce2275d1cb950de28862bb8e0fe","tests/fixtures/no-color/multiple_annotations.toml":"c570a67e211c324edb2a1427148dba3a62cb2af0aaf5a522d1dd6a03594489b5","tests/fixtures/no-color/multiple_annotations.txt":"b284ab83d9de3aa9d014d3d04ac199517967885bc064f0462c15d6a4d71554aa","tests/fixtures/no-color/simple.toml":"6ef667b5e736fc112a1fb4722a2828aaf8049b8bbf6aacdb730a8f3427900f10","tests/fixtures/no-color/simple.txt":"2a8e4036837503bb53fca8ef761b658090e7869bf9b87197612530ca4e71b7f2","tests/fixtures/no-color/strip_line.toml":"a94309544d46693452f8c9c5b04fcc7412e5fd3e24daf361231a52053331c563","tests/fixtures/no-color/strip_line.txt":"2ff4c8feaf88fae9f1da8013b8f40d80ac43ddcfff9fae46cb3acd7d1dc8610d","tests/fixtures/no-color/strip_line_char.toml":"0635b7c3cc4f79edd891689194b0f5c5288e9ed6de8329cc7891b3793221f7f0","tests/fixtures/no-color/strip_line_char.txt":"22f6ac6a36ae96a366c0a8a9b1bd07b2bc6a70239d3732789e18a0a0bb611cac","tests/fixtures/no-color/strip_line_non_ws.toml":"82d9d12177e19a682fc2412fa733241bd4a7740b8c2d4a2f41042a45a9ec3550","tests/fixtures/no-color/strip_line_non_ws.txt":"036ebfeb9b3530be177dc5e52887bb8bb6d93a09d0072e1dc26a380e3b4dfbf9","tests/fixtures_test.rs":"903f56c24c500135fed3fc0e40c77a89b98f72ce2e99322658242a6bfbf89a14","tests/formatter.rs":"9a608541ac130eaef21fb6288d4559380944405626ce77ef1484d74bbe1f134a","tests/snippet/mod.rs":"68a0af016410b1ad15d60951133bf6152021fb8f3dcad6ab32b1375f191c3130"},"package":"c3b9d411ecbaf79885c6df4d75fff75858d5995ff25385657a28af47e82f9c36"} \ No newline at end of file diff --git a/vendor/annotate-snippets/CHANGELOG.md b/vendor/annotate-snippets/CHANGELOG.md new file mode 100644 index 000000000..21e5f2fe2 --- /dev/null +++ b/vendor/annotate-snippets/CHANGELOG.md @@ -0,0 +1,39 @@ +# Changelog + +## Unreleased + + - … + +## annotate-snippets 0.9.1 (September 4, 2021) + + - Fix character split when strip code. (#37) + - Fix off by one error in multiline highlighting. (#42) + - Fix display of annotation for double width characters. (#46) + +## annotate-snippets 0.9.0 (June 28, 2020) + + - Add strip code to the left and right of long lines. (#36) + +## annotate-snippets 0.8.0 (April 14, 2020) + + - Replace `ansi_term` with `yansi-term` for improved performance. (#30) + - Turn `Snippet` and `Slice` to work on borrowed slices, rather than Strings. (#32) + - Fix `\r\n` end of lines. (#29) + +## annotate-snippets 0.7.0 (March 30, 2020) + + - Refactor API to use `fmt::Display` (#27) + - Fix SourceAnnotation range (#27) + - Fix column numbers (#22) + - Derive `PartialEq` for `AnnotationType` (#19) + - Update `ansi_term` to 0.12. + +## annotate-snippets 0.6.1 (July 23, 2019) + + - Fix too many anonymized line numbers (#5) + +## annotate-snippets 0.6.0 (June 26, 2019) + + - Add an option to anonymize line numbers (#3) + - Transition the crate to rust-lang org. + - Update the syntax to Rust 2018 idioms. (#4) diff --git a/vendor/annotate-snippets/Cargo.lock b/vendor/annotate-snippets/Cargo.lock new file mode 100644 index 000000000..33b807577 --- /dev/null +++ b/vendor/annotate-snippets/Cargo.lock @@ -0,0 +1,631 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "annotate-snippets" +version = "0.9.1" +dependencies = [ + "criterion", + "difference", + "glob", + "serde", + "toml", + "unicode-width", + "yansi-term", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "bstr" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + +[[package]] +name = "cast" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +dependencies = [ + "bitflags", + "textwrap", + "unicode-width", +] + +[[package]] +name = "criterion" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc755679c12bda8e5523a71e4d654b6bf2e14bd838dfc48cde6559a05caf7d1" +dependencies = [ + "atty", + "cast", + "clap", + "criterion-plot", + "csv", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01e15e0ea58e8234f96146b1f91fa9d0e4dd7a38da93ff7a75d42c0b9d3a545" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "maybe-uninit", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg", + "cfg-if", + "lazy_static", +] + +[[package]] +name = "csv" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279" +dependencies = [ + "bstr", + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + +[[package]] +name = "difference" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" + +[[package]] +name = "either" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "hermit-abi" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e" +dependencies = [ + "libc", +] + +[[package]] +name = "itertools" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" + +[[package]] +name = "js-sys" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055" +dependencies = [ + "wasm-bindgen", +] + +[[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.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + +[[package]] +name = "memchr" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" + +[[package]] +name = "memoffset" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num-traits" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "oorandom" +version = "11.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcec7c9c2a95cacc7cd0ecb89d8a8454eca13906f6deb55258ffff0adeb9405" + +[[package]] +name = "plotters" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3bb8da247d27ae212529352020f3e5ee16e83c0c258061d27b08ab92675eeb" +dependencies = [ + "js-sys", + "num-traits", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "proc-macro2" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" +dependencies = [ + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" +dependencies = [ + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils", + "lazy_static", + "num_cpus", +] + +[[package]] +name = "regex" +version = "1.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" +dependencies = [ + "byteorder", +] + +[[package]] +name = "regex-syntax" +version = "0.6.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78a7a12c167809363ec3bd7329fc0a3369056996de43c4b37ef3cd54a6ce4867" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "tinytemplate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a3c6667d3e65eb1bc3aed6fd14011c6cbc3a0665218ab7f5daf040b9ec371a" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "toml" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" + +[[package]] +name = "walkdir" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639" + +[[package]] +name = "web-sys" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80" +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 = "yansi-term" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e44ab40470a13c8746f6a9b5e042ba56dbd55e5a48921e131779b4575935bc7" +dependencies = [ + "winapi", +] diff --git a/vendor/annotate-snippets/Cargo.toml b/vendor/annotate-snippets/Cargo.toml new file mode 100644 index 000000000..e2bccd904 --- /dev/null +++ b/vendor/annotate-snippets/Cargo.toml @@ -0,0 +1,65 @@ +# 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 believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +edition = "2018" +name = "annotate-snippets" +version = "0.9.1" +authors = ["Zibi Braniecki "] +description = "Library for building code annotations" +readme = "README.md" +keywords = ["code", "analysis", "ascii", "errors", "debug"] +license = "Apache-2.0/MIT" +repository = "https://github.com/rust-lang/annotate-snippets-rs" + +[[bench]] +name = "simple" +harness = false +[dependencies.unicode-width] +version = "0.1" + +[dependencies.yansi-term] +version = "0.1" +optional = true +[dev-dependencies.criterion] +version = "0.3" + +[dev-dependencies.difference] +version = "2.0" + +[dev-dependencies.glob] +version = "0.3" + +[dev-dependencies.serde] +version = "1.0" +features = ["derive"] + +[dev-dependencies.toml] +version = "0.5" + +[dev-dependencies.yansi-term] +version = "0.1" + +[features] +color = ["yansi-term"] +default = [] +[badges.coveralls] +branch = "master" +repository = "rust-lang/annotate-snippets-rs" +service = "github" + +[badges.maintenance] +status = "actively-developed" + +[badges.travis-ci] +branch = "master" +repository = "rust-lang/annotate-snippets-rs" diff --git a/vendor/annotate-snippets/LICENSE-APACHE b/vendor/annotate-snippets/LICENSE-APACHE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/vendor/annotate-snippets/LICENSE-APACHE @@ -0,0 +1,201 @@ + 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. diff --git a/vendor/annotate-snippets/LICENSE-MIT b/vendor/annotate-snippets/LICENSE-MIT new file mode 100644 index 000000000..5655fa311 --- /dev/null +++ b/vendor/annotate-snippets/LICENSE-MIT @@ -0,0 +1,19 @@ +Copyright 2017 Mozilla + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/annotate-snippets/README.md b/vendor/annotate-snippets/README.md new file mode 100644 index 000000000..a3e1683f8 --- /dev/null +++ b/vendor/annotate-snippets/README.md @@ -0,0 +1,90 @@ +# annotate-snippets + +`annotate-snippets` is a Rust library for annotation of programming code slices. + +[![crates.io](https://img.shields.io/crates/v/annotate-snippets.svg)](https://crates.io/crates/annotate-snippets) +[![Build Status](https://travis-ci.com/rust-lang/annotate-snippets-rs.svg?branch=master)](https://travis-ci.com/rust-lang/annotate-snippets-rs) +[![Coverage Status](https://coveralls.io/repos/github/rust-lang/annotate-snippets-rs/badge.svg?branch=master)](https://coveralls.io/github/rust-lang/annotate-snippets-rs?branch=master) + +The library helps visualize meta information annotating source code slices. +It takes a data structure called `Snippet` on the input and produces a `String` +which may look like this: + +```text +error[E0308]: mismatched types + --> src/format.rs:52:1 + | +51 | ) -> Option { + | -------------- expected `Option` because of return type +52 | / for ann in annotations { +53 | | match (ann.range.0, ann.range.1) { +54 | | (None, None) => continue, +55 | | (Some(start), Some(end)) if start > end_index => continue, +... | +71 | | } +72 | | } + | |_____^ expected enum `std::option::Option`, found () +``` + +[Documentation][] + +[Documentation]: https://docs.rs/annotate-snippets/ + +Usage +----- + +```rust +use annotate_snippets::{ + display_list::{DisplayList, FormatOptions}, + snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}, +}; + +fn main() { + let snippet = Snippet { + title: Some(Annotation { + label: Some("expected type, found `22`"), + id: None, + annotation_type: AnnotationType::Error, + }), + footer: vec![], + slices: vec![Slice { + source: r#" annotations: vec![SourceAnnotation { + label: "expected struct `annotate_snippets::snippet::Slice`, found reference" + , + range: <22, 25>,"#, + line_start: 26, + origin: Some("examples/footer.rs"), + fold: true, + annotations: vec![ + SourceAnnotation { + label: "", + annotation_type: AnnotationType::Error, + range: (187, 189), + }, + SourceAnnotation { + label: "while parsing this struct", + annotation_type: AnnotationType::Info, + range: (34, 50), + }, + ], + }], + opt: FormatOptions { + color: true, + ..Default::default() + }, + }; + + let dl = DisplayList::from(snippet); + println!("{}", dl); +} +``` + +Local Development +----------------- + + cargo build + cargo test + +When submitting a PR please use [`cargo fmt`][] (nightly). + +[`cargo fmt`]: https://github.com/rust-lang/rustfmt diff --git a/vendor/annotate-snippets/benches/simple.rs b/vendor/annotate-snippets/benches/simple.rs new file mode 100644 index 000000000..4c13a8f00 --- /dev/null +++ b/vendor/annotate-snippets/benches/simple.rs @@ -0,0 +1,74 @@ +#![allow(clippy::unit_arg)] +#[macro_use] +extern crate criterion; + +use criterion::{black_box, Criterion}; + +use annotate_snippets::{ + display_list::{DisplayList, FormatOptions}, + snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}, +}; + +fn create_snippet() { + let snippet = Snippet { + slices: vec![Slice { + source: r#") -> Option { + for ann in annotations { + match (ann.range.0, ann.range.1) { + (None, None) => continue, + (Some(start), Some(end)) if start > end_index => continue, + (Some(start), Some(end)) if start >= start_index => { + let label = if let Some(ref label) = ann.label { + format!(" {}", label) + } else { + String::from("") + }; + + return Some(format!( + "{}{}{}", + " ".repeat(start - start_index), + "^".repeat(end - start), + label + )); + } + _ => continue, + } + }"#, + line_start: 51, + origin: Some("src/format.rs"), + fold: false, + annotations: vec![ + SourceAnnotation { + label: "expected `Option` because of return type", + annotation_type: AnnotationType::Warning, + range: (5, 19), + }, + SourceAnnotation { + label: "expected enum `std::option::Option`", + annotation_type: AnnotationType::Error, + range: (26, 724), + }, + ], + }], + title: Some(Annotation { + label: Some("mismatched types"), + id: Some("E0308"), + annotation_type: AnnotationType::Error, + }), + footer: vec![], + opt: FormatOptions { + color: true, + ..Default::default() + }, + }; + + let dl = DisplayList::from(snippet); + let _result = dl.to_string(); +} + +pub fn criterion_benchmark(c: &mut Criterion) { + c.bench_function("format", |b| b.iter(|| black_box(create_snippet()))); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/vendor/annotate-snippets/examples/expected_type.rs b/vendor/annotate-snippets/examples/expected_type.rs new file mode 100644 index 000000000..6f2a0d9a0 --- /dev/null +++ b/vendor/annotate-snippets/examples/expected_type.rs @@ -0,0 +1,43 @@ +use annotate_snippets::{ + display_list::{DisplayList, FormatOptions}, + snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}, +}; + +fn main() { + let snippet = Snippet { + title: Some(Annotation { + label: Some("expected type, found `22`"), + id: None, + annotation_type: AnnotationType::Error, + }), + footer: vec![], + slices: vec![Slice { + source: r#" annotations: vec![SourceAnnotation { + label: "expected struct `annotate_snippets::snippet::Slice`, found reference" + , + range: <22, 25>,"#, + line_start: 26, + origin: Some("examples/footer.rs"), + fold: true, + annotations: vec![ + SourceAnnotation { + label: "", + annotation_type: AnnotationType::Error, + range: (193, 195), + }, + SourceAnnotation { + label: "while parsing this struct", + annotation_type: AnnotationType::Info, + range: (34, 50), + }, + ], + }], + opt: FormatOptions { + color: true, + ..Default::default() + }, + }; + + let dl = DisplayList::from(snippet); + println!("{}", dl); +} diff --git a/vendor/annotate-snippets/examples/footer.rs b/vendor/annotate-snippets/examples/footer.rs new file mode 100644 index 000000000..f3c15c410 --- /dev/null +++ b/vendor/annotate-snippets/examples/footer.rs @@ -0,0 +1,39 @@ +use annotate_snippets::{ + display_list::{DisplayList, FormatOptions}, + snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}, +}; + +fn main() { + let snippet = Snippet { + title: Some(Annotation { + label: Some("mismatched types"), + id: Some("E0308"), + annotation_type: AnnotationType::Error, + }), + footer: vec![Annotation { + label: Some( + "expected type: `snippet::Annotation`\n found type: `__&__snippet::Annotation`", + ), + id: None, + annotation_type: AnnotationType::Note, + }], + slices: vec![Slice { + source: " slices: vec![\"A\",", + line_start: 13, + origin: Some("src/multislice.rs"), + fold: false, + annotations: vec![SourceAnnotation { + label: "expected struct `annotate_snippets::snippet::Slice`, found reference", + range: (21, 24), + annotation_type: AnnotationType::Error, + }], + }], + opt: FormatOptions { + color: true, + ..Default::default() + }, + }; + + let dl = DisplayList::from(snippet); + println!("{}", dl); +} diff --git a/vendor/annotate-snippets/examples/format.rs b/vendor/annotate-snippets/examples/format.rs new file mode 100644 index 000000000..98b77a140 --- /dev/null +++ b/vendor/annotate-snippets/examples/format.rs @@ -0,0 +1,61 @@ +use annotate_snippets::{ + display_list::{DisplayList, FormatOptions}, + snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}, +}; + +fn main() { + let snippet = Snippet { + slices: vec![Slice { + source: r#") -> Option { + for ann in annotations { + match (ann.range.0, ann.range.1) { + (None, None) => continue, + (Some(start), Some(end)) if start > end_index => continue, + (Some(start), Some(end)) if start >= start_index => { + let label = if let Some(ref label) = ann.label { + format!(" {}", label) + } else { + String::from("") + }; + + return Some(format!( + "{}{}{}", + " ".repeat(start - start_index), + "^".repeat(end - start), + label + )); + } + _ => continue, + } + }"#, + line_start: 51, + origin: Some("src/format.rs"), + fold: false, + annotations: vec![ + SourceAnnotation { + label: "expected `Option` because of return type", + annotation_type: AnnotationType::Warning, + range: (5, 19), + }, + SourceAnnotation { + label: "expected enum `std::option::Option`", + annotation_type: AnnotationType::Error, + range: (26, 724), + }, + ], + }], + title: Some(Annotation { + label: Some("mismatched types"), + id: Some("E0308"), + annotation_type: AnnotationType::Error, + }), + footer: vec![], + opt: FormatOptions { + color: true, + ..Default::default() + }, + }; + + let dl = DisplayList::from(snippet); + println!("{}", dl); +} diff --git a/vendor/annotate-snippets/examples/multislice.rs b/vendor/annotate-snippets/examples/multislice.rs new file mode 100644 index 000000000..5675a07da --- /dev/null +++ b/vendor/annotate-snippets/examples/multislice.rs @@ -0,0 +1,38 @@ +use annotate_snippets::{ + display_list::{DisplayList, FormatOptions}, + snippet::{Annotation, AnnotationType, Slice, Snippet}, +}; + +fn main() { + let snippet = Snippet { + title: Some(Annotation { + label: Some("mismatched types"), + id: None, + annotation_type: AnnotationType::Error, + }), + footer: vec![], + slices: vec![ + Slice { + source: "Foo", + line_start: 51, + origin: Some("src/format.rs"), + fold: false, + annotations: vec![], + }, + Slice { + source: "Faa", + line_start: 129, + origin: Some("src/display.rs"), + fold: false, + annotations: vec![], + }, + ], + opt: FormatOptions { + color: true, + ..Default::default() + }, + }; + + let dl = DisplayList::from(snippet); + println!("{}", dl); +} diff --git a/vendor/annotate-snippets/src/display_list/from_snippet.rs b/vendor/annotate-snippets/src/display_list/from_snippet.rs new file mode 100644 index 000000000..faf48f2a1 --- /dev/null +++ b/vendor/annotate-snippets/src/display_list/from_snippet.rs @@ -0,0 +1,594 @@ +//! Trait for converting `Snippet` to `DisplayList`. +use super::*; +use crate::{formatter::get_term_style, snippet}; + +struct CursorLines<'a>(&'a str); + +impl<'a> CursorLines<'a> { + fn new(src: &str) -> CursorLines<'_> { + CursorLines(src) + } +} + +enum EndLine { + EOF = 0, + CRLF = 1, + LF = 2, +} + +impl<'a> Iterator for CursorLines<'a> { + type Item = (&'a str, EndLine); + + fn next(&mut self) -> Option { + if self.0.is_empty() { + None + } else { + self.0 + .find('\n') + .map(|x| { + let ret = if 0 < x { + if self.0.as_bytes()[x - 1] == b'\r' { + (&self.0[..x - 1], EndLine::LF) + } else { + (&self.0[..x], EndLine::CRLF) + } + } else { + ("", EndLine::CRLF) + }; + self.0 = &self.0[x + 1..]; + ret + }) + .or_else(|| { + let ret = Some((self.0, EndLine::EOF)); + self.0 = ""; + ret + }) + } + } +} + +fn format_label( + label: Option<&str>, + style: Option, +) -> Vec> { + let mut result = vec![]; + if let Some(label) = label { + for (idx, element) in label.split("__").enumerate() { + let element_style = match style { + Some(s) => s, + None => { + if idx % 2 == 0 { + DisplayTextStyle::Regular + } else { + DisplayTextStyle::Emphasis + } + } + }; + result.push(DisplayTextFragment { + content: element, + style: element_style, + }); + } + } + result +} + +fn format_title(annotation: snippet::Annotation<'_>) -> DisplayLine<'_> { + let label = annotation.label.unwrap_or_default(); + DisplayLine::Raw(DisplayRawLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::from(annotation.annotation_type), + id: annotation.id, + label: format_label(Some(label), Some(DisplayTextStyle::Emphasis)), + }, + source_aligned: false, + continuation: false, + }) +} + +fn format_annotation(annotation: snippet::Annotation<'_>) -> Vec> { + let mut result = vec![]; + let label = annotation.label.unwrap_or_default(); + for (i, line) in label.lines().enumerate() { + result.push(DisplayLine::Raw(DisplayRawLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::from(annotation.annotation_type), + id: None, + label: format_label(Some(line), None), + }, + source_aligned: true, + continuation: i != 0, + })); + } + result +} + +fn format_slice( + slice: snippet::Slice<'_>, + is_first: bool, + has_footer: bool, + margin: Option, +) -> Vec> { + let main_range = slice.annotations.get(0).map(|x| x.range.0); + let origin = slice.origin; + let line_start = slice.line_start; + let need_empty_header = origin.is_some() || is_first; + let mut body = format_body(slice, need_empty_header, has_footer, margin); + let header = format_header(origin, main_range, line_start, &body, is_first); + let mut result = vec![]; + + if let Some(header) = header { + result.push(header); + } + result.append(&mut body); + result +} + +#[inline] +// TODO: option_zip +fn zip_opt(a: Option, b: Option) -> Option<(A, B)> { + a.and_then(|a| b.map(|b| (a, b))) +} + +fn format_header<'a>( + origin: Option<&'a str>, + main_range: Option, + mut row: usize, + body: &[DisplayLine<'_>], + is_first: bool, +) -> Option> { + let display_header = if is_first { + DisplayHeaderType::Initial + } else { + DisplayHeaderType::Continuation + }; + + if let Some((main_range, path)) = zip_opt(main_range, origin) { + let mut col = 1; + + for item in body { + if let DisplayLine::Source { + line: DisplaySourceLine::Content { range, .. }, + .. + } = item + { + if main_range >= range.0 && main_range <= range.1 { + col = main_range - range.0 + 1; + break; + } + row += 1; + } + } + + return Some(DisplayLine::Raw(DisplayRawLine::Origin { + path, + pos: Some((row, col)), + header_type: display_header, + })); + } + + if let Some(path) = origin { + return Some(DisplayLine::Raw(DisplayRawLine::Origin { + path, + pos: None, + header_type: display_header, + })); + } + + None +} + +fn fold_body(mut body: Vec>) -> Vec> { + enum Line { + Fold(usize), + Source(usize), + } + + let mut lines = vec![]; + let mut no_annotation_lines_counter = 0; + + for (idx, line) in body.iter().enumerate() { + match line { + DisplayLine::Source { + line: DisplaySourceLine::Annotation { .. }, + .. + } => { + let fold_start = idx - no_annotation_lines_counter; + if no_annotation_lines_counter > 2 { + let fold_end = idx; + let pre_len = if no_annotation_lines_counter > 8 { + 4 + } else { + 0 + }; + let post_len = if no_annotation_lines_counter > 8 { + 2 + } else { + 1 + }; + for (i, _) in body + .iter() + .enumerate() + .take(fold_start + pre_len) + .skip(fold_start) + { + lines.push(Line::Source(i)); + } + lines.push(Line::Fold(idx)); + for (i, _) in body + .iter() + .enumerate() + .take(fold_end) + .skip(fold_end - post_len) + { + lines.push(Line::Source(i)); + } + } else { + for (i, _) in body.iter().enumerate().take(idx).skip(fold_start) { + lines.push(Line::Source(i)); + } + } + no_annotation_lines_counter = 0; + } + DisplayLine::Source { .. } => { + no_annotation_lines_counter += 1; + continue; + } + _ => { + no_annotation_lines_counter += 1; + } + } + lines.push(Line::Source(idx)); + } + + let mut new_body = vec![]; + let mut removed = 0; + for line in lines { + match line { + Line::Source(i) => { + new_body.push(body.remove(i - removed)); + removed += 1; + } + Line::Fold(i) => { + if let DisplayLine::Source { + line: DisplaySourceLine::Annotation { .. }, + ref inline_marks, + .. + } = body.get(i - removed).unwrap() + { + new_body.push(DisplayLine::Fold { + inline_marks: inline_marks.clone(), + }) + } else { + unreachable!() + } + } + } + } + + new_body +} + +fn format_body( + slice: snippet::Slice<'_>, + need_empty_header: bool, + has_footer: bool, + margin: Option, +) -> Vec> { + let source_len = slice.source.chars().count(); + if let Some(bigger) = slice.annotations.iter().find_map(|x| { + if source_len < x.range.1 { + Some(x.range) + } else { + None + } + }) { + panic!( + "SourceAnnotation range `{:?}` is bigger than source length `{}`", + bigger, source_len + ) + } + + let mut body = vec![]; + let mut current_line = slice.line_start; + let mut current_index = 0; + let mut line_info = vec![]; + + struct LineInfo { + line_start_index: usize, + line_end_index: usize, + // How many spaces each character in the line take up when displayed + char_widths: Vec, + } + + for (line, end_line) in CursorLines::new(slice.source) { + let line_length = line.chars().count(); + let line_range = (current_index, current_index + line_length); + let char_widths = line + .chars() + .map(|c| unicode_width::UnicodeWidthChar::width(c).unwrap_or(0)) + .chain(std::iter::once(1)) // treat the end of line as signle-width + .collect::>(); + body.push(DisplayLine::Source { + lineno: Some(current_line), + inline_marks: vec![], + line: DisplaySourceLine::Content { + text: line, + range: line_range, + }, + }); + line_info.push(LineInfo { + line_start_index: line_range.0, + line_end_index: line_range.1, + char_widths, + }); + current_line += 1; + current_index += line_length + end_line as usize; + } + + let mut annotation_line_count = 0; + let mut annotations = slice.annotations; + for ( + idx, + LineInfo { + line_start_index, + line_end_index, + char_widths, + }, + ) in line_info.into_iter().enumerate() + { + let margin_left = margin + .map(|m| m.left(line_end_index - line_start_index)) + .unwrap_or_default(); + // It would be nice to use filter_drain here once it's stable. + annotations = annotations + .into_iter() + .filter(|annotation| { + let body_idx = idx + annotation_line_count; + let annotation_type = match annotation.annotation_type { + snippet::AnnotationType::Error => DisplayAnnotationType::None, + snippet::AnnotationType::Warning => DisplayAnnotationType::None, + _ => DisplayAnnotationType::from(annotation.annotation_type), + }; + match annotation.range { + (start, _) if start > line_end_index => true, + (start, end) + if start >= line_start_index && end <= line_end_index + || start == line_end_index && end - start <= 1 => + { + let annotation_start_col = char_widths + .iter() + .take(start - line_start_index) + .sum::() + - margin_left; + let annotation_end_col = char_widths + .iter() + .take(end - line_start_index) + .sum::() + - margin_left; + let range = (annotation_start_col, annotation_end_col); + body.insert( + body_idx + 1, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Annotation { + annotation: Annotation { + annotation_type, + id: None, + label: format_label(Some(annotation.label), None), + }, + range, + annotation_type: DisplayAnnotationType::from( + annotation.annotation_type, + ), + annotation_part: DisplayAnnotationPart::Standalone, + }, + }, + ); + annotation_line_count += 1; + false + } + (start, end) + if start >= line_start_index + && start <= line_end_index + && end > line_end_index => + { + if start - line_start_index == 0 { + if let DisplayLine::Source { + ref mut inline_marks, + .. + } = body[body_idx] + { + inline_marks.push(DisplayMark { + mark_type: DisplayMarkType::AnnotationStart, + annotation_type: DisplayAnnotationType::from( + annotation.annotation_type, + ), + }); + } + } else { + let annotation_start_col = char_widths + .iter() + .take(start - line_start_index) + .sum::(); + let range = (annotation_start_col, annotation_start_col + 1); + body.insert( + body_idx + 1, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::None, + id: None, + label: vec![], + }, + range, + annotation_type: DisplayAnnotationType::from( + annotation.annotation_type, + ), + annotation_part: DisplayAnnotationPart::MultilineStart, + }, + }, + ); + annotation_line_count += 1; + } + true + } + (start, end) if start < line_start_index && end > line_end_index => { + if let DisplayLine::Source { + ref mut inline_marks, + .. + } = body[body_idx] + { + inline_marks.push(DisplayMark { + mark_type: DisplayMarkType::AnnotationThrough, + annotation_type: DisplayAnnotationType::from( + annotation.annotation_type, + ), + }); + } + true + } + (start, end) + if start < line_start_index + && end >= line_start_index + && end <= line_end_index => + { + if let DisplayLine::Source { + ref mut inline_marks, + .. + } = body[body_idx] + { + inline_marks.push(DisplayMark { + mark_type: DisplayMarkType::AnnotationThrough, + annotation_type: DisplayAnnotationType::from( + annotation.annotation_type, + ), + }); + } + + let end_mark = char_widths + .iter() + .take(end - line_start_index) + .sum::() + .saturating_sub(1); + let range = (end_mark - margin_left, (end_mark + 1) - margin_left); + body.insert( + body_idx + 1, + DisplayLine::Source { + lineno: None, + inline_marks: vec![DisplayMark { + mark_type: DisplayMarkType::AnnotationThrough, + annotation_type: DisplayAnnotationType::from( + annotation.annotation_type, + ), + }], + line: DisplaySourceLine::Annotation { + annotation: Annotation { + annotation_type, + id: None, + label: format_label(Some(annotation.label), None), + }, + range, + annotation_type: DisplayAnnotationType::from( + annotation.annotation_type, + ), + annotation_part: DisplayAnnotationPart::MultilineEnd, + }, + }, + ); + annotation_line_count += 1; + false + } + _ => true, + } + }) + .collect(); + } + + if slice.fold { + body = fold_body(body); + } + + if need_empty_header { + body.insert( + 0, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Empty, + }, + ); + } + + if has_footer { + body.push(DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Empty, + }); + } else if let Some(DisplayLine::Source { .. }) = body.last() { + body.push(DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Empty, + }); + } + body +} + +impl<'a> From> for DisplayList<'a> { + fn from( + snippet::Snippet { + title, + footer, + slices, + opt, + }: snippet::Snippet<'a>, + ) -> DisplayList<'a> { + let mut body = vec![]; + if let Some(annotation) = title { + body.push(format_title(annotation)); + } + + for (idx, slice) in slices.into_iter().enumerate() { + body.append(&mut format_slice( + slice, + idx == 0, + !footer.is_empty(), + opt.margin, + )); + } + + for annotation in footer { + body.append(&mut format_annotation(annotation)); + } + + let FormatOptions { + color, + anonymized_line_numbers, + margin, + } = opt; + + Self { + body, + stylesheet: get_term_style(color), + anonymized_line_numbers, + margin, + } + } +} + +impl From for DisplayAnnotationType { + fn from(at: snippet::AnnotationType) -> Self { + match at { + snippet::AnnotationType::Error => DisplayAnnotationType::Error, + snippet::AnnotationType::Warning => DisplayAnnotationType::Warning, + snippet::AnnotationType::Info => DisplayAnnotationType::Info, + snippet::AnnotationType::Note => DisplayAnnotationType::Note, + snippet::AnnotationType::Help => DisplayAnnotationType::Help, + } + } +} diff --git a/vendor/annotate-snippets/src/display_list/mod.rs b/vendor/annotate-snippets/src/display_list/mod.rs new file mode 100644 index 000000000..224a9f580 --- /dev/null +++ b/vendor/annotate-snippets/src/display_list/mod.rs @@ -0,0 +1,37 @@ +//! display_list module stores the output model for the snippet. +//! +//! `DisplayList` is a central structure in the crate, which contains +//! the structured list of lines to be displayed. +//! +//! It is made of two types of lines: `Source` and `Raw`. All `Source` lines +//! are structured using four columns: +//! +//! ```text +//! /------------ (1) Line number column. +//! | /--------- (2) Line number column delimiter. +//! | | /------- (3) Inline marks column. +//! | | | /--- (4) Content column with the source and annotations for slices. +//! | | | | +//! ============================================================================= +//! error[E0308]: mismatched types +//! --> src/format.rs:51:5 +//! | +//! 151 | / fn test() -> String { +//! 152 | | return "test"; +//! 153 | | } +//! | |___^ error: expected `String`, for `&str`. +//! | +//! ``` +//! +//! The first two lines of the example above are `Raw` lines, while the rest +//! are `Source` lines. +//! +//! `DisplayList` does not store column alignment information, and those are +//! only calculated by the implementation of `std::fmt::Display` using information such as +//! styling. +//! +//! The above snippet has been built out of the following structure: +mod from_snippet; +mod structs; + +pub use self::structs::*; diff --git a/vendor/annotate-snippets/src/display_list/structs.rs b/vendor/annotate-snippets/src/display_list/structs.rs new file mode 100644 index 000000000..7941d5fca --- /dev/null +++ b/vendor/annotate-snippets/src/display_list/structs.rs @@ -0,0 +1,308 @@ +use std::cmp::{max, min}; +use std::fmt; + +use crate::formatter::{get_term_style, style::Stylesheet}; + +/// List of lines to be displayed. +pub struct DisplayList<'a> { + pub body: Vec>, + pub stylesheet: Box, + pub anonymized_line_numbers: bool, + pub margin: Option, +} + +impl<'a> From>> for DisplayList<'a> { + fn from(body: Vec>) -> DisplayList<'a> { + Self { + body, + anonymized_line_numbers: false, + stylesheet: get_term_style(false), + margin: None, + } + } +} + +impl<'a> PartialEq for DisplayList<'a> { + fn eq(&self, other: &Self) -> bool { + self.body == other.body && self.anonymized_line_numbers == other.anonymized_line_numbers + } +} + +impl<'a> fmt::Debug for DisplayList<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("DisplayList") + .field("body", &self.body) + .field("anonymized_line_numbers", &self.anonymized_line_numbers) + .finish() + } +} + +#[derive(Debug, Default, Copy, Clone)] +pub struct FormatOptions { + pub color: bool, + pub anonymized_line_numbers: bool, + pub margin: Option, +} + +#[derive(Clone, Copy, Debug)] +pub struct Margin { + /// The available whitespace in the left that can be consumed when centering. + whitespace_left: usize, + /// The column of the beginning of left-most span. + span_left: usize, + /// The column of the end of right-most span. + span_right: usize, + /// The beginning of the line to be displayed. + computed_left: usize, + /// The end of the line to be displayed. + computed_right: usize, + /// The current width of the terminal. 140 by default and in tests. + column_width: usize, + /// The end column of a span label, including the span. Doesn't account for labels not in the + /// same line as the span. + label_right: usize, +} + +impl Margin { + pub fn new( + whitespace_left: usize, + span_left: usize, + span_right: usize, + label_right: usize, + column_width: usize, + max_line_len: usize, + ) -> Self { + // The 6 is padding to give a bit of room for `...` when displaying: + // ``` + // error: message + // --> file.rs:16:58 + // | + // 16 | ... fn foo(self) -> Self::Bar { + // | ^^^^^^^^^ + // ``` + + let mut m = Margin { + whitespace_left: whitespace_left.saturating_sub(6), + span_left: span_left.saturating_sub(6), + span_right: span_right + 6, + computed_left: 0, + computed_right: 0, + column_width, + label_right: label_right + 6, + }; + m.compute(max_line_len); + m + } + + pub(crate) fn was_cut_left(&self) -> bool { + self.computed_left > 0 + } + + pub(crate) fn was_cut_right(&self, line_len: usize) -> bool { + let right = + if self.computed_right == self.span_right || self.computed_right == self.label_right { + // Account for the "..." padding given above. Otherwise we end up with code lines that + // do fit but end in "..." as if they were trimmed. + self.computed_right - 6 + } else { + self.computed_right + }; + right < line_len && self.computed_left + self.column_width < line_len + } + + fn compute(&mut self, max_line_len: usize) { + // When there's a lot of whitespace (>20), we want to trim it as it is useless. + self.computed_left = if self.whitespace_left > 20 { + self.whitespace_left - 16 // We want some padding. + } else { + 0 + }; + // We want to show as much as possible, max_line_len is the right-most boundary for the + // relevant code. + self.computed_right = max(max_line_len, self.computed_left); + + if self.computed_right - self.computed_left > self.column_width { + // Trimming only whitespace isn't enough, let's get craftier. + if self.label_right - self.whitespace_left <= self.column_width { + // Attempt to fit the code window only trimming whitespace. + self.computed_left = self.whitespace_left; + self.computed_right = self.computed_left + self.column_width; + } else if self.label_right - self.span_left <= self.column_width { + // Attempt to fit the code window considering only the spans and labels. + let padding_left = (self.column_width - (self.label_right - self.span_left)) / 2; + self.computed_left = self.span_left.saturating_sub(padding_left); + self.computed_right = self.computed_left + self.column_width; + } else if self.span_right - self.span_left <= self.column_width { + // Attempt to fit the code window considering the spans and labels plus padding. + let padding_left = (self.column_width - (self.span_right - self.span_left)) / 5 * 2; + self.computed_left = self.span_left.saturating_sub(padding_left); + self.computed_right = self.computed_left + self.column_width; + } else { + // Mostly give up but still don't show the full line. + self.computed_left = self.span_left; + self.computed_right = self.span_right; + } + } + } + + pub(crate) fn left(&self, line_len: usize) -> usize { + min(self.computed_left, line_len) + } + + pub(crate) fn right(&self, line_len: usize) -> usize { + if line_len.saturating_sub(self.computed_left) <= self.column_width { + line_len + } else { + min(line_len, self.computed_right) + } + } +} + +/// Inline annotation which can be used in either Raw or Source line. +#[derive(Debug, PartialEq)] +pub struct Annotation<'a> { + pub annotation_type: DisplayAnnotationType, + pub id: Option<&'a str>, + pub label: Vec>, +} + +/// A single line used in `DisplayList`. +#[derive(Debug, PartialEq)] +pub enum DisplayLine<'a> { + /// A line with `lineno` portion of the slice. + Source { + lineno: Option, + inline_marks: Vec, + line: DisplaySourceLine<'a>, + }, + + /// A line indicating a folded part of the slice. + Fold { inline_marks: Vec }, + + /// A line which is displayed outside of slices. + Raw(DisplayRawLine<'a>), +} + +/// A source line. +#[derive(Debug, PartialEq)] +pub enum DisplaySourceLine<'a> { + /// A line with the content of the Slice. + Content { + text: &'a str, + range: (usize, usize), // meta information for annotation placement. + }, + + /// An annotation line which is displayed in context of the slice. + Annotation { + annotation: Annotation<'a>, + range: (usize, usize), + annotation_type: DisplayAnnotationType, + annotation_part: DisplayAnnotationPart, + }, + + /// An empty source line. + Empty, +} + +/// Raw line - a line which does not have the `lineno` part and is not considered +/// a part of the snippet. +#[derive(Debug, PartialEq)] +pub enum DisplayRawLine<'a> { + /// A line which provides information about the location of the given + /// slice in the project structure. + Origin { + path: &'a str, + pos: Option<(usize, usize)>, + header_type: DisplayHeaderType, + }, + + /// An annotation line which is not part of any snippet. + Annotation { + annotation: Annotation<'a>, + + /// If set to `true`, the annotation will be aligned to the + /// lineno delimiter of the snippet. + source_aligned: bool, + /// If set to `true`, only the label of the `Annotation` will be + /// displayed. It allows for a multiline annotation to be aligned + /// without displaing the meta information (`type` and `id`) to be + /// displayed on each line. + continuation: bool, + }, +} + +/// An inline text fragment which any label is composed of. +#[derive(Debug, PartialEq)] +pub struct DisplayTextFragment<'a> { + pub content: &'a str, + pub style: DisplayTextStyle, +} + +/// A style for the `DisplayTextFragment` which can be visually formatted. +/// +/// This information may be used to emphasis parts of the label. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum DisplayTextStyle { + Regular, + Emphasis, +} + +/// An indicator of what part of the annotation a given `Annotation` is. +#[derive(Debug, Clone, PartialEq)] +pub enum DisplayAnnotationPart { + /// A standalone, single-line annotation. + Standalone, + /// A continuation of a multi-line label of an annotation. + LabelContinuation, + /// A consequitive annotation in case multiple annotations annotate a single line. + Consequitive, + /// A line starting a multiline annotation. + MultilineStart, + /// A line ending a multiline annotation. + MultilineEnd, +} + +/// A visual mark used in `inline_marks` field of the `DisplaySourceLine`. +#[derive(Debug, Clone, PartialEq)] +pub struct DisplayMark { + pub mark_type: DisplayMarkType, + pub annotation_type: DisplayAnnotationType, +} + +/// A type of the `DisplayMark`. +#[derive(Debug, Clone, PartialEq)] +pub enum DisplayMarkType { + /// A mark indicating a multiline annotation going through the current line. + AnnotationThrough, + /// A mark indicating a multiline annotation starting on the given line. + AnnotationStart, +} + +/// A type of the `Annotation` which may impact the sigils, style or text displayed. +/// +/// There are several ways to uses this information when formatting the `DisplayList`: +/// +/// * An annotation may display the name of the type like `error` or `info`. +/// * An underline for `Error` may be `^^^` while for `Warning` it coule be `---`. +/// * `ColorStylesheet` may use different colors for different annotations. +#[derive(Debug, Clone, PartialEq)] +pub enum DisplayAnnotationType { + None, + Error, + Warning, + Info, + Note, + Help, +} + +/// Information whether the header is the initial one or a consequitive one +/// for multi-slice cases. +// TODO: private +#[derive(Debug, Clone, PartialEq)] +pub enum DisplayHeaderType { + /// Initial header is the first header in the snippet. + Initial, + + /// Continuation marks all headers of following slices in the snippet. + Continuation, +} diff --git a/vendor/annotate-snippets/src/formatter/mod.rs b/vendor/annotate-snippets/src/formatter/mod.rs new file mode 100644 index 000000000..16889baa9 --- /dev/null +++ b/vendor/annotate-snippets/src/formatter/mod.rs @@ -0,0 +1,456 @@ +use std::{ + cmp, + fmt::{self, Display, Write}, + iter::once, +}; + +pub mod style; + +use self::style::{Style, StyleClass, Stylesheet}; + +#[cfg(feature = "color")] +use crate::stylesheets::color::AnsiTermStylesheet; +use crate::{display_list::*, stylesheets::no_color::NoColorStylesheet}; + +fn format_repeat_char(c: char, n: usize, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for _ in 0..n { + f.write_char(c)?; + } + Ok(()) +} + +#[inline] +fn is_annotation_empty(annotation: &Annotation<'_>) -> bool { + annotation + .label + .iter() + .all(|fragment| fragment.content.is_empty()) +} + +#[cfg(feature = "color")] +#[inline] +pub fn get_term_style(color: bool) -> Box { + if color { + Box::new(AnsiTermStylesheet) + } else { + Box::new(NoColorStylesheet) + } +} + +#[cfg(not(feature = "color"))] +#[inline] +pub fn get_term_style(_color: bool) -> Box { + Box::new(NoColorStylesheet) +} + +impl<'a> fmt::Display for DisplayList<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let lineno_width = self.body.iter().fold(0, |max, line| match line { + DisplayLine::Source { + lineno: Some(lineno), + .. + } => { + // The largest line is the largest width. + cmp::max(*lineno, max) + } + _ => max, + }); + let lineno_width = if lineno_width == 0 { + lineno_width + } else if self.anonymized_line_numbers { + Self::ANONYMIZED_LINE_NUM.len() + } else { + ((lineno_width as f64).log10().floor() as usize) + 1 + }; + let inline_marks_width = self.body.iter().fold(0, |max, line| match line { + DisplayLine::Source { inline_marks, .. } => cmp::max(inline_marks.len(), max), + _ => max, + }); + + for (i, line) in self.body.iter().enumerate() { + self.format_line(line, lineno_width, inline_marks_width, f)?; + if i + 1 < self.body.len() { + f.write_char('\n')?; + } + } + Ok(()) + } +} + +impl<'a> DisplayList<'a> { + const ANONYMIZED_LINE_NUM: &'static str = "LL"; + const ERROR_TXT: &'static str = "error"; + const HELP_TXT: &'static str = "help"; + const INFO_TXT: &'static str = "info"; + const NOTE_TXT: &'static str = "note"; + const WARNING_TXT: &'static str = "warning"; + + #[inline] + fn format_annotation_type( + annotation_type: &DisplayAnnotationType, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + match annotation_type { + DisplayAnnotationType::Error => f.write_str(Self::ERROR_TXT), + DisplayAnnotationType::Help => f.write_str(Self::HELP_TXT), + DisplayAnnotationType::Info => f.write_str(Self::INFO_TXT), + DisplayAnnotationType::Note => f.write_str(Self::NOTE_TXT), + DisplayAnnotationType::Warning => f.write_str(Self::WARNING_TXT), + DisplayAnnotationType::None => Ok(()), + } + } + + fn annotation_type_len(annotation_type: &DisplayAnnotationType) -> usize { + match annotation_type { + DisplayAnnotationType::Error => Self::ERROR_TXT.len(), + DisplayAnnotationType::Help => Self::HELP_TXT.len(), + DisplayAnnotationType::Info => Self::INFO_TXT.len(), + DisplayAnnotationType::Note => Self::NOTE_TXT.len(), + DisplayAnnotationType::Warning => Self::WARNING_TXT.len(), + DisplayAnnotationType::None => 0, + } + } + + fn get_annotation_style(&self, annotation_type: &DisplayAnnotationType) -> Box { + self.stylesheet.get_style(match annotation_type { + DisplayAnnotationType::Error => StyleClass::Error, + DisplayAnnotationType::Warning => StyleClass::Warning, + DisplayAnnotationType::Info => StyleClass::Info, + DisplayAnnotationType::Note => StyleClass::Note, + DisplayAnnotationType::Help => StyleClass::Help, + DisplayAnnotationType::None => StyleClass::None, + }) + } + + fn format_label( + &self, + label: &[DisplayTextFragment<'_>], + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + let emphasis_style = self.stylesheet.get_style(StyleClass::Emphasis); + + for fragment in label { + match fragment.style { + DisplayTextStyle::Regular => fragment.content.fmt(f)?, + DisplayTextStyle::Emphasis => emphasis_style.paint(fragment.content, f)?, + } + } + Ok(()) + } + + fn format_annotation( + &self, + annotation: &Annotation<'_>, + continuation: bool, + in_source: bool, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + let color = self.get_annotation_style(&annotation.annotation_type); + let formatted_len = if let Some(id) = &annotation.id { + 2 + id.len() + Self::annotation_type_len(&annotation.annotation_type) + } else { + Self::annotation_type_len(&annotation.annotation_type) + }; + + if continuation { + format_repeat_char(' ', formatted_len + 2, f)?; + return self.format_label(&annotation.label, f); + } + if formatted_len == 0 { + self.format_label(&annotation.label, f) + } else { + color.paint_fn( + Box::new(|f| { + Self::format_annotation_type(&annotation.annotation_type, f)?; + if let Some(id) = &annotation.id { + f.write_char('[')?; + f.write_str(id)?; + f.write_char(']')?; + } + Ok(()) + }), + f, + )?; + if !is_annotation_empty(annotation) { + if in_source { + color.paint_fn( + Box::new(|f| { + f.write_str(": ")?; + self.format_label(&annotation.label, f) + }), + f, + )?; + } else { + f.write_str(": ")?; + self.format_label(&annotation.label, f)?; + } + } + Ok(()) + } + } + + #[inline] + fn format_source_line( + &self, + line: &DisplaySourceLine<'_>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + match line { + DisplaySourceLine::Empty => Ok(()), + DisplaySourceLine::Content { text, .. } => { + f.write_char(' ')?; + if let Some(margin) = self.margin { + let line_len = text.chars().count(); + let mut left = margin.left(line_len); + let right = margin.right(line_len); + + if margin.was_cut_left() { + // We have stripped some code/whitespace from the beginning, make it clear. + "...".fmt(f)?; + left += 3; + } + + // On long lines, we strip the source line, accounting for unicode. + let mut taken = 0; + let cut_right = if margin.was_cut_right(line_len) { + taken += 3; + true + } else { + false + }; + // Specifies that it will end on the next character, so it will return + // until the next one to the final condition. + let mut ended = false; + let range = text + .char_indices() + .skip(left) + // Complete char iterator with final character + .chain(once((text.len(), '\0'))) + // Take until the next one to the final condition + .take_while(|(_, ch)| { + // Fast return to iterate over final byte position + if ended { + return false; + } + // Make sure that the trimming on the right will fall within the terminal width. + // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. + // For now, just accept that sometimes the code line will be longer than desired. + taken += unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1); + if taken > right - left { + ended = true; + } + true + }) + // Reduce to start and end byte position + .fold((None, 0), |acc, (i, _)| { + if acc.0.is_some() { + (acc.0, i) + } else { + (Some(i), i) + } + }); + + // Format text with margins + text[range.0.expect("One character at line")..range.1].fmt(f)?; + + if cut_right { + // We have stripped some code after the right-most span end, make it clear we did so. + "...".fmt(f)?; + } + Ok(()) + } else { + text.fmt(f) + } + } + DisplaySourceLine::Annotation { + range, + annotation, + annotation_type, + annotation_part, + } => { + let indent_char = match annotation_part { + DisplayAnnotationPart::Standalone => ' ', + DisplayAnnotationPart::LabelContinuation => ' ', + DisplayAnnotationPart::Consequitive => ' ', + DisplayAnnotationPart::MultilineStart => '_', + DisplayAnnotationPart::MultilineEnd => '_', + }; + let mark = match annotation_type { + DisplayAnnotationType::Error => '^', + DisplayAnnotationType::Warning => '-', + DisplayAnnotationType::Info => '-', + DisplayAnnotationType::Note => '-', + DisplayAnnotationType::Help => '-', + DisplayAnnotationType::None => ' ', + }; + let color = self.get_annotation_style(annotation_type); + let indent_length = match annotation_part { + DisplayAnnotationPart::LabelContinuation => range.1, + DisplayAnnotationPart::Consequitive => range.1, + _ => range.0, + }; + + color.paint_fn( + Box::new(|f| { + format_repeat_char(indent_char, indent_length + 1, f)?; + format_repeat_char(mark, range.1 - indent_length, f) + }), + f, + )?; + + if !is_annotation_empty(annotation) { + f.write_char(' ')?; + color.paint_fn( + Box::new(|f| { + self.format_annotation( + annotation, + annotation_part == &DisplayAnnotationPart::LabelContinuation, + true, + f, + ) + }), + f, + )?; + } + + Ok(()) + } + } + } + + #[inline] + fn format_raw_line( + &self, + line: &DisplayRawLine<'_>, + lineno_width: usize, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + match line { + DisplayRawLine::Origin { + path, + pos, + header_type, + } => { + let header_sigil = match header_type { + DisplayHeaderType::Initial => "-->", + DisplayHeaderType::Continuation => ":::", + }; + let lineno_color = self.stylesheet.get_style(StyleClass::LineNo); + + if let Some((col, row)) = pos { + format_repeat_char(' ', lineno_width, f)?; + lineno_color.paint(header_sigil, f)?; + f.write_char(' ')?; + path.fmt(f)?; + f.write_char(':')?; + col.fmt(f)?; + f.write_char(':')?; + row.fmt(f) + } else { + format_repeat_char(' ', lineno_width, f)?; + lineno_color.paint(header_sigil, f)?; + f.write_char(' ')?; + path.fmt(f) + } + } + DisplayRawLine::Annotation { + annotation, + source_aligned, + continuation, + } => { + if *source_aligned { + if *continuation { + format_repeat_char(' ', lineno_width + 3, f)?; + } else { + let lineno_color = self.stylesheet.get_style(StyleClass::LineNo); + format_repeat_char(' ', lineno_width, f)?; + f.write_char(' ')?; + lineno_color.paint("=", f)?; + f.write_char(' ')?; + } + } + self.format_annotation(annotation, *continuation, false, f) + } + } + } + + #[inline] + fn format_line( + &self, + dl: &DisplayLine<'_>, + lineno_width: usize, + inline_marks_width: usize, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + match dl { + DisplayLine::Source { + lineno, + inline_marks, + line, + } => { + let lineno_color = self.stylesheet.get_style(StyleClass::LineNo); + if self.anonymized_line_numbers && lineno.is_some() { + lineno_color.paint_fn( + Box::new(|f| { + f.write_str(Self::ANONYMIZED_LINE_NUM)?; + f.write_str(" |") + }), + f, + )?; + } else { + lineno_color.paint_fn( + Box::new(|f| { + match lineno { + Some(n) => write!(f, "{:>width$}", n, width = lineno_width), + None => format_repeat_char(' ', lineno_width, f), + }?; + f.write_str(" |") + }), + f, + )?; + } + if *line != DisplaySourceLine::Empty { + if !inline_marks.is_empty() || 0 < inline_marks_width { + f.write_char(' ')?; + self.format_inline_marks(inline_marks, inline_marks_width, f)?; + } + self.format_source_line(line, f)?; + } else if !inline_marks.is_empty() { + f.write_char(' ')?; + self.format_inline_marks(inline_marks, inline_marks_width, f)?; + } + Ok(()) + } + DisplayLine::Fold { inline_marks } => { + f.write_str("...")?; + if !inline_marks.is_empty() || 0 < inline_marks_width { + format_repeat_char(' ', lineno_width, f)?; + self.format_inline_marks(inline_marks, inline_marks_width, f)?; + } + Ok(()) + } + DisplayLine::Raw(line) => self.format_raw_line(line, lineno_width, f), + } + } + + fn format_inline_marks( + &self, + inline_marks: &[DisplayMark], + inline_marks_width: usize, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + format_repeat_char(' ', inline_marks_width - inline_marks.len(), f)?; + for mark in inline_marks { + self.get_annotation_style(&mark.annotation_type).paint_fn( + Box::new(|f| { + f.write_char(match mark.mark_type { + DisplayMarkType::AnnotationThrough => '|', + DisplayMarkType::AnnotationStart => '/', + }) + }), + f, + )?; + } + Ok(()) + } +} diff --git a/vendor/annotate-snippets/src/formatter/style.rs b/vendor/annotate-snippets/src/formatter/style.rs new file mode 100644 index 000000000..3fc01c191 --- /dev/null +++ b/vendor/annotate-snippets/src/formatter/style.rs @@ -0,0 +1,51 @@ +//! Set of structures required to implement a stylesheet +//! +//! In order to provide additional styling information for the +//! formatter, a structs can implement `Stylesheet` and `Style` +//! traits. +//! +use std::fmt; + +/// StyleClass is a collection of named variants of style classes +pub enum StyleClass { + /// Message indicating an error. + Error, + /// Message indicating a warning. + Warning, + /// Message indicating an information. + Info, + /// Message indicating a note. + Note, + /// Message indicating a help. + Help, + + /// Style for line numbers. + LineNo, + + /// Parts of the text that are to be emphasised. + Emphasis, + + /// Parts of the text that are regular. Usually a no-op. + None, +} + +/// This trait implements a return value for the `Stylesheet::get_style`. +pub trait Style { + /// The method used to write text with formatter + fn paint(&self, text: &str, f: &mut fmt::Formatter<'_>) -> fmt::Result; + /// The method used to write display function with formatter + fn paint_fn<'a>( + &self, + c: Box) -> fmt::Result + 'a>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result; + /// The method used by the `Formatter` to display the message in bold font. + fn bold(&self) -> Box; +} + +/// Trait to annotate structs that can provide `Style` implementations for +/// every `StyleClass` variant. +pub trait Stylesheet { + /// Returns a `Style` implementer based on the requested `StyleClass` variant. + fn get_style(&self, class: StyleClass) -> Box; +} diff --git a/vendor/annotate-snippets/src/lib.rs b/vendor/annotate-snippets/src/lib.rs new file mode 100644 index 000000000..d58136728 --- /dev/null +++ b/vendor/annotate-snippets/src/lib.rs @@ -0,0 +1,54 @@ +#![deny(rust_2018_idioms)] + +//! A library for formatting of text or programming code snippets. +//! +//! It's primary purpose is to build an ASCII-graphical representation of the snippet +//! with annotations. +//! +//! # Example +//! +//! ```text +//! error[E0308]: mismatched types +//! --> src/format.rs:52:1 +//! | +//! 51 | ) -> Option { +//! | -------------- expected `Option` because of return type +//! 52 | / for ann in annotations { +//! 53 | | match (ann.range.0, ann.range.1) { +//! 54 | | (None, None) => continue, +//! 55 | | (Some(start), Some(end)) if start > end_index => continue, +//! ... | +//! 71 | | } +//! 72 | | } +//! | |_____^ expected enum `std::option::Option`, found () +//! ``` +//! +//! The crate uses a three stage process with two conversions between states: +//! +//! ```text +//! Snippet --> DisplayList --> String +//! ``` +//! +//! The input type - [Snippet](self::snippet) is a structure designed +//! to align with likely output from any parser whose code snippet is to be +//! annotated. +//! +//! The middle structure - [DisplayList](self::display_list) is a +//! structure designed to store the snippet data converted into a vector +//! of lines containing semantic information about each line. +//! This structure is the easiest to manipulate and organize. +//! +//! Finally, `impl Display` into a final `String` output. +//! +//! A user of the crate may choose to provide their own equivalent of the input +//! structure with an `Into` trait. +//! +//! A user of the crate may also choose to provide their own formatter logic, +//! to convert a `DisplayList` into a `String`, or just a `Stylesheet` to +//! use the crate's formatting logic, but with a custom stylesheet. +// TODO: check documentation + +pub mod display_list; +pub mod formatter; +pub mod snippet; +pub mod stylesheets; diff --git a/vendor/annotate-snippets/src/snippet.rs b/vendor/annotate-snippets/src/snippet.rs new file mode 100644 index 000000000..bc7ba0099 --- /dev/null +++ b/vendor/annotate-snippets/src/snippet.rs @@ -0,0 +1,88 @@ +//! Structures used as an input for the library. +//! +//! Example: +//! +//! ``` +//! use annotate_snippets::snippet::*; +//! +//! Snippet { +//! title: Some(Annotation { +//! label: Some("mismatched types"), +//! id: None, +//! annotation_type: AnnotationType::Error, +//! }), +//! footer: vec![], +//! slices: vec![ +//! Slice { +//! source: "Foo", +//! line_start: 51, +//! origin: Some("src/format.rs"), +//! fold: false, +//! annotations: vec![], +//! }, +//! Slice { +//! source: "Faa", +//! line_start: 129, +//! origin: Some("src/display.rs"), +//! fold: false, +//! annotations: vec![], +//! }, +//! ], +//! opt: Default::default(), +//! }; +//! ``` +use crate::display_list::FormatOptions; + +/// Primary structure provided for formatting +#[derive(Debug, Default)] +pub struct Snippet<'a> { + pub title: Option>, + pub footer: Vec>, + pub slices: Vec>, + pub opt: FormatOptions, +} + +/// Structure containing the slice of text to be annotated and +/// basic information about the location of the slice. +/// +/// One `Slice` is meant to represent a single, continuous, +/// slice of source code that you want to annotate. +#[derive(Debug)] +pub struct Slice<'a> { + pub source: &'a str, + pub line_start: usize, + pub origin: Option<&'a str>, + pub annotations: Vec>, + /// If set explicitly to `true`, the snippet will fold + /// parts of the slice that don't contain any annotations. + pub fold: bool, +} + +/// Types of annotations. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum AnnotationType { + /// Error annotations are displayed using red color and "^" character. + Error, + /// Warning annotations are displayed using blue color and "-" character. + Warning, + Info, + Note, + Help, +} + +/// An annotation for a `Slice`. +#[derive(Debug)] +pub struct SourceAnnotation<'a> { + pub range: (usize, usize), + pub label: &'a str, + pub annotation_type: AnnotationType, +} + +/// An annotation for a `Snippet`. +#[derive(Debug)] +pub struct Annotation<'a> { + /// Identifier of the annotation. Usually error code like "E0308". + pub id: Option<&'a str>, + pub label: Option<&'a str>, + pub annotation_type: AnnotationType, +} diff --git a/vendor/annotate-snippets/src/stylesheets/color.rs b/vendor/annotate-snippets/src/stylesheets/color.rs new file mode 100644 index 000000000..024dd06f6 --- /dev/null +++ b/vendor/annotate-snippets/src/stylesheets/color.rs @@ -0,0 +1,50 @@ +use std::fmt::{self, Display}; + +use yansi_term::{Color::Fixed, Style as AnsiTermStyle}; + +use crate::formatter::style::{Style, StyleClass, Stylesheet}; + +struct AnsiTermStyleWrapper { + style: AnsiTermStyle, +} + +impl Style for AnsiTermStyleWrapper { + fn paint(&self, text: &str, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.style.paint(text).fmt(f) + } + + fn paint_fn<'a>( + &self, + c: Box) -> fmt::Result + 'a>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + self.style.paint_fn(c).fmt(f) + } + + fn bold(&self) -> Box { + Box::new(AnsiTermStyleWrapper { style: self.style }) + } +} + +pub struct AnsiTermStylesheet; + +impl Stylesheet for AnsiTermStylesheet { + fn get_style(&self, class: StyleClass) -> Box { + let ansi_term_style = match class { + StyleClass::Error => Fixed(9).bold(), + StyleClass::Warning => Fixed(11).bold(), + StyleClass::Info => Fixed(12).bold(), + StyleClass::Note => AnsiTermStyle::new().bold(), + StyleClass::Help => Fixed(14).bold(), + + StyleClass::LineNo => Fixed(12).bold(), + + StyleClass::Emphasis => AnsiTermStyle::new().bold(), + + StyleClass::None => AnsiTermStyle::new(), + }; + Box::new(AnsiTermStyleWrapper { + style: ansi_term_style, + }) + } +} diff --git a/vendor/annotate-snippets/src/stylesheets/mod.rs b/vendor/annotate-snippets/src/stylesheets/mod.rs new file mode 100644 index 000000000..4648852ad --- /dev/null +++ b/vendor/annotate-snippets/src/stylesheets/mod.rs @@ -0,0 +1,11 @@ +//! List of stylesheets +//! +//! The list depends on what optional dependencies the crate has been +//! compiled with. +//! +//! By default the `no_color` is available. If the crate gets compiled +//! with `ansi_term`, the `color` stylesheet is added. + +#[cfg(feature = "color")] +pub mod color; +pub mod no_color; diff --git a/vendor/annotate-snippets/src/stylesheets/no_color.rs b/vendor/annotate-snippets/src/stylesheets/no_color.rs new file mode 100644 index 000000000..21cb26955 --- /dev/null +++ b/vendor/annotate-snippets/src/stylesheets/no_color.rs @@ -0,0 +1,31 @@ +use std::fmt; + +use crate::formatter::style::{Style, StyleClass, Stylesheet}; + +pub struct NoOpStyle {} + +impl Style for NoOpStyle { + fn paint(&self, text: &str, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(text) + } + + fn paint_fn<'a>( + &self, + c: Box) -> fmt::Result + 'a>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + c(f) + } + + fn bold(&self) -> Box { + Box::new(NoOpStyle {}) + } +} + +pub struct NoColorStylesheet; + +impl Stylesheet for NoColorStylesheet { + fn get_style(&self, _class: StyleClass) -> Box { + Box::new(NoOpStyle {}) + } +} diff --git a/vendor/annotate-snippets/tests/diff/mod.rs b/vendor/annotate-snippets/tests/diff/mod.rs new file mode 100644 index 000000000..576c6c4d6 --- /dev/null +++ b/vendor/annotate-snippets/tests/diff/mod.rs @@ -0,0 +1,43 @@ +use difference::{Changeset, Difference}; +use yansi_term::Color::{Black, Green, Red}; + +pub fn get_diff(left: &str, right: &str) -> String { + let mut output = String::new(); + + let Changeset { diffs, .. } = Changeset::new(left, right, "\n"); + + for i in 0..diffs.len() { + match diffs[i] { + Difference::Same(ref x) => { + output += &format!(" {}\n", x); + } + Difference::Add(ref x) => { + match diffs[i - 1] { + Difference::Rem(ref y) => { + output += &format!("{}", Green.paint("+")); + let Changeset { diffs, .. } = Changeset::new(y, x, " "); + for c in diffs { + match c { + Difference::Same(ref z) => { + output += &format!("{} ", Green.paint(z.as_str())); + } + Difference::Add(ref z) => { + output += &format!("{} ", Black.on(Green).paint(z.as_str())); + } + _ => (), + } + } + output += "\n"; + } + _ => { + output += &format!("+{}\n", Green.paint(x.as_str())); + } + }; + } + Difference::Rem(ref x) => { + output += &format!("-{}\n", Red.paint(x.as_str())); + } + } + } + output +} diff --git a/vendor/annotate-snippets/tests/dl_from_snippet.rs b/vendor/annotate-snippets/tests/dl_from_snippet.rs new file mode 100644 index 000000000..0dcfcfa31 --- /dev/null +++ b/vendor/annotate-snippets/tests/dl_from_snippet.rs @@ -0,0 +1,407 @@ +use annotate_snippets::display_list::DisplayList; +use annotate_snippets::{display_list as dl, formatter::get_term_style, snippet}; + +#[test] +fn test_format_title() { + let input = snippet::Snippet { + title: Some(snippet::Annotation { + id: Some("E0001"), + label: Some("This is a title"), + annotation_type: snippet::AnnotationType::Error, + }), + footer: vec![], + slices: vec![], + opt: Default::default(), + }; + let output = dl::DisplayList { + body: vec![dl::DisplayLine::Raw(dl::DisplayRawLine::Annotation { + annotation: dl::Annotation { + annotation_type: dl::DisplayAnnotationType::Error, + id: Some("E0001"), + label: vec![dl::DisplayTextFragment { + content: "This is a title", + style: dl::DisplayTextStyle::Emphasis, + }], + }, + source_aligned: false, + continuation: false, + })], + stylesheet: get_term_style(input.opt.color), + anonymized_line_numbers: input.opt.anonymized_line_numbers, + margin: None, + }; + assert_eq!(dl::DisplayList::from(input), output); +} + +#[test] +fn test_format_slice() { + let line_1 = "This is line 1"; + let line_2 = "This is line 2"; + let source = vec![line_1, line_2].join("\n"); + let input = snippet::Snippet { + title: None, + footer: vec![], + slices: vec![snippet::Slice { + source: &source, + line_start: 5402, + origin: None, + annotations: vec![], + fold: false, + }], + opt: Default::default(), + }; + let output = dl::DisplayList { + body: vec![ + dl::DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: dl::DisplaySourceLine::Empty, + }, + dl::DisplayLine::Source { + lineno: Some(5402), + inline_marks: vec![], + line: dl::DisplaySourceLine::Content { + text: line_1, + range: (0, line_1.len()), + }, + }, + dl::DisplayLine::Source { + lineno: Some(5403), + inline_marks: vec![], + line: dl::DisplaySourceLine::Content { + range: (line_1.len() + 1, source.len()), + text: line_2, + }, + }, + dl::DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: dl::DisplaySourceLine::Empty, + }, + ], + stylesheet: get_term_style(input.opt.color), + anonymized_line_numbers: input.opt.anonymized_line_numbers, + margin: None, + }; + assert_eq!(dl::DisplayList::from(input), output); +} + +#[test] +fn test_format_slices_continuation() { + let src_0 = "This is slice 1"; + let src_0_len = src_0.len(); + let src_1 = "This is slice 2"; + let src_1_len = src_1.len(); + let input = snippet::Snippet { + title: None, + footer: vec![], + slices: vec![ + snippet::Slice { + source: src_0, + line_start: 5402, + origin: Some("file1.rs"), + annotations: vec![], + fold: false, + }, + snippet::Slice { + source: src_1, + line_start: 2, + origin: Some("file2.rs"), + annotations: vec![], + fold: false, + }, + ], + opt: Default::default(), + }; + let output = dl::DisplayList { + body: vec![ + dl::DisplayLine::Raw(dl::DisplayRawLine::Origin { + path: "file1.rs", + pos: None, + header_type: dl::DisplayHeaderType::Initial, + }), + dl::DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: dl::DisplaySourceLine::Empty, + }, + dl::DisplayLine::Source { + lineno: Some(5402), + inline_marks: vec![], + line: dl::DisplaySourceLine::Content { + text: src_0, + range: (0, src_0_len), + }, + }, + dl::DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: dl::DisplaySourceLine::Empty, + }, + dl::DisplayLine::Raw(dl::DisplayRawLine::Origin { + path: "file2.rs", + pos: None, + header_type: dl::DisplayHeaderType::Continuation, + }), + dl::DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: dl::DisplaySourceLine::Empty, + }, + dl::DisplayLine::Source { + lineno: Some(2), + inline_marks: vec![], + line: dl::DisplaySourceLine::Content { + text: src_1, + range: (0, src_1_len), + }, + }, + dl::DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: dl::DisplaySourceLine::Empty, + }, + ], + stylesheet: get_term_style(input.opt.color), + anonymized_line_numbers: input.opt.anonymized_line_numbers, + margin: None, + }; + assert_eq!(dl::DisplayList::from(input), output); +} + +#[test] +fn test_format_slice_annotation_standalone() { + let line_1 = "This is line 1"; + let line_2 = "This is line 2"; + let source = vec![line_1, line_2].join("\n"); + // In line 2 + let range = (22, 24); + let input = snippet::Snippet { + title: None, + footer: vec![], + slices: vec![snippet::Slice { + source: &source, + line_start: 5402, + origin: None, + annotations: vec![snippet::SourceAnnotation { + range, + label: "Test annotation", + annotation_type: snippet::AnnotationType::Info, + }], + fold: false, + }], + opt: Default::default(), + }; + let output = dl::DisplayList { + body: vec![ + dl::DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: dl::DisplaySourceLine::Empty, + }, + dl::DisplayLine::Source { + lineno: Some(5402), + inline_marks: vec![], + line: dl::DisplaySourceLine::Content { + range: (0, line_1.len()), + text: line_1, + }, + }, + dl::DisplayLine::Source { + lineno: Some(5403), + inline_marks: vec![], + line: dl::DisplaySourceLine::Content { + range: (line_1.len() + 1, source.len()), + text: line_2, + }, + }, + dl::DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: dl::DisplaySourceLine::Annotation { + annotation: dl::Annotation { + annotation_type: dl::DisplayAnnotationType::Info, + id: None, + label: vec![dl::DisplayTextFragment { + content: "Test annotation", + style: dl::DisplayTextStyle::Regular, + }], + }, + range: (range.0 - (line_1.len() + 1), range.1 - (line_1.len() + 1)), + annotation_type: dl::DisplayAnnotationType::Info, + annotation_part: dl::DisplayAnnotationPart::Standalone, + }, + }, + dl::DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: dl::DisplaySourceLine::Empty, + }, + ], + stylesheet: get_term_style(input.opt.color), + anonymized_line_numbers: input.opt.anonymized_line_numbers, + margin: None, + }; + assert_eq!(dl::DisplayList::from(input), output); +} + +#[test] +fn test_format_label() { + let input = snippet::Snippet { + title: None, + footer: vec![snippet::Annotation { + id: None, + label: Some("This __is__ a title"), + annotation_type: snippet::AnnotationType::Error, + }], + slices: vec![], + opt: Default::default(), + }; + let output = dl::DisplayList { + body: vec![dl::DisplayLine::Raw(dl::DisplayRawLine::Annotation { + annotation: dl::Annotation { + annotation_type: dl::DisplayAnnotationType::Error, + id: None, + label: vec![ + dl::DisplayTextFragment { + content: "This ", + style: dl::DisplayTextStyle::Regular, + }, + dl::DisplayTextFragment { + content: "is", + style: dl::DisplayTextStyle::Emphasis, + }, + dl::DisplayTextFragment { + content: " a title", + style: dl::DisplayTextStyle::Regular, + }, + ], + }, + source_aligned: true, + continuation: false, + })], + stylesheet: get_term_style(input.opt.color), + anonymized_line_numbers: input.opt.anonymized_line_numbers, + margin: None, + }; + assert_eq!(dl::DisplayList::from(input), output); +} + +#[test] +#[should_panic] +fn test_i26() { + let source = "short"; + let label = "label"; + let input = snippet::Snippet { + title: None, + footer: vec![], + slices: vec![snippet::Slice { + annotations: vec![snippet::SourceAnnotation { + range: (0, source.len() + 1), + label, + annotation_type: snippet::AnnotationType::Error, + }], + source, + line_start: 0, + origin: None, + fold: false, + }], + opt: Default::default(), + }; + + let _ = dl::DisplayList::from(input); +} + +#[test] +fn test_i_29() { + let snippets = snippet::Snippet { + title: Some(snippet::Annotation { + id: None, + label: Some("oops"), + annotation_type: snippet::AnnotationType::Error, + }), + footer: vec![], + slices: vec![snippet::Slice { + source: "First line\r\nSecond oops line", + line_start: 1, + origin: Some(""), + annotations: vec![snippet::SourceAnnotation { + range: (19, 23), + label: "oops", + annotation_type: snippet::AnnotationType::Error, + }], + fold: true, + }], + opt: Default::default(), + }; + + let expected = DisplayList { + body: vec![ + dl::DisplayLine::Raw(dl::DisplayRawLine::Annotation { + annotation: dl::Annotation { + annotation_type: dl::DisplayAnnotationType::Error, + id: None, + label: vec![dl::DisplayTextFragment { + content: "oops", + style: dl::DisplayTextStyle::Emphasis, + }], + }, + source_aligned: false, + continuation: false, + }), + dl::DisplayLine::Raw(dl::DisplayRawLine::Origin { + path: "", + pos: Some((2, 8)), + header_type: dl::DisplayHeaderType::Initial, + }), + dl::DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: dl::DisplaySourceLine::Empty, + }, + dl::DisplayLine::Source { + lineno: Some(1), + inline_marks: vec![], + line: dl::DisplaySourceLine::Content { + text: "First line", + range: (0, 10), + }, + }, + dl::DisplayLine::Source { + lineno: Some(2), + inline_marks: vec![], + line: dl::DisplaySourceLine::Content { + text: "Second oops line", + range: (12, 28), + }, + }, + dl::DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: dl::DisplaySourceLine::Annotation { + annotation: dl::Annotation { + annotation_type: dl::DisplayAnnotationType::None, + id: None, + label: vec![dl::DisplayTextFragment { + content: "oops", + style: dl::DisplayTextStyle::Regular, + }], + }, + range: (7, 11), + annotation_type: dl::DisplayAnnotationType::Error, + annotation_part: dl::DisplayAnnotationPart::Standalone, + }, + }, + dl::DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: dl::DisplaySourceLine::Empty, + }, + ], + stylesheet: get_term_style(false), + anonymized_line_numbers: false, + margin: None, + }; + + assert_eq!(DisplayList::from(snippets), expected); +} diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/issue_9.toml b/vendor/annotate-snippets/tests/fixtures/no-color/issue_9.toml new file mode 100644 index 000000000..a30563b28 --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/issue_9.toml @@ -0,0 +1,28 @@ +[title] +label = "expected one of `.`, `;`, `?`, or an operator, found `for`" +annotation_type = "Error" + +[[slices]] +source = "let x = vec![1];" +line_start = 4 +origin = "/code/rust/src/test/ui/annotate-snippet/suggestion.rs" +[[slices.annotations]] +label = "move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait" +annotation_type = "Warning" +range = [4, 5] + +[[slices]] +source = "let y = x;" +line_start = 7 +[[slices.annotations]] +label = "value moved here" +annotation_type = "Warning" +range = [8, 9] + +[[slices]] +source = "x;" +line_start = 9 +[[slices.annotations]] +label = "value used here after move" +annotation_type = "Error" +range = [0, 1] diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/issue_9.txt b/vendor/annotate-snippets/tests/fixtures/no-color/issue_9.txt new file mode 100644 index 000000000..affe6bc42 --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/issue_9.txt @@ -0,0 +1,12 @@ +error: expected one of `.`, `;`, `?`, or an operator, found `for` + --> /code/rust/src/test/ui/annotate-snippet/suggestion.rs:4:5 + | +4 | let x = vec![1]; + | - move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait + | +7 | let y = x; + | - value moved here + | +9 | x; + | ^ value used here after move + | \ No newline at end of file diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation.toml b/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation.toml new file mode 100644 index 000000000..c3dc1e9e6 --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation.toml @@ -0,0 +1,40 @@ +[[slices]] +source = """ +) -> Option { + for ann in annotations { + match (ann.range.0, ann.range.1) { + (None, None) => continue, + (Some(start), Some(end)) if start > end_index || end < start_index => continue, + (Some(start), Some(end)) if start >= start_index && end <= end_index => { + let label = if let Some(ref label) = ann.label { + format!(" {}", label) + } else { + String::from("") + }; + + return Some(format!( + "{}{}{}", + " ".repeat(start - start_index), + "^".repeat(end - start), + label + )); + } + _ => continue, + } + } +""" +line_start = 51 +origin = "src/format.rs" +fold = true +[[slices.annotations]] +label = "expected `std::option::Option` because of return type" +annotation_type = "Warning" +range = [5, 19] +[[slices.annotations]] +label = "expected enum `std::option::Option`, found ()" +annotation_type = "Error" +range = [22, 766] +[title] +label = "mismatched types" +id = "E0308" +annotation_type = "Error" diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation.txt b/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation.txt new file mode 100644 index 000000000..bacdec10d --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation.txt @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> src/format.rs:51:6 + | +51 | ) -> Option { + | -------------- expected `std::option::Option` because of return type +52 | / for ann in annotations { +53 | | match (ann.range.0, ann.range.1) { +54 | | (None, None) => continue, +55 | | (Some(start), Some(end)) if start > end_index || end < start_index => continue, +... | +71 | | } +72 | | } + | |_____^ expected enum `std::option::Option`, found () + | diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation2.toml b/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation2.toml new file mode 100644 index 000000000..845bf9f2f --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation2.toml @@ -0,0 +1,18 @@ +[[slices]] +source = """ + if let DisplayLine::Source { + ref mut inline_marks, + } = body[body_idx] +""" +line_start = 139 +origin = "src/display_list.rs" +fold = false +[[slices.annotations]] +label = "missing fields `lineno`, `content`" +annotation_type = "Error" +range = [31, 128] + +[title] +label = "pattern does not mention fields `lineno`, `content`" +id = "E0027" +annotation_type = "Error" diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation2.txt b/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation2.txt new file mode 100644 index 000000000..8a00bfa20 --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation2.txt @@ -0,0 +1,9 @@ +error[E0027]: pattern does not mention fields `lineno`, `content` + --> src/display_list.rs:139:32 + | +139 | if let DisplayLine::Source { + | ________________________________^ +140 | | ref mut inline_marks, +141 | | } = body[body_idx] + | |_________________________^ missing fields `lineno`, `content` + | diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation3.toml b/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation3.toml new file mode 100644 index 000000000..21bbcd857 --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation3.toml @@ -0,0 +1,18 @@ +[[slices]] +source = """ +This is an exampl +e of an edge case of an annotation overflowing +to exactly one character on next line. +""" +line_start = 26 +origin = "foo.txt" +fold = false +[[slices.annotations]] +label = "this should not be on separate lines" +annotation_type = "Error" +range = [11, 18] + +[title] +label = "spacing error found" +id = "E####" +annotation_type = "Error" diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation3.txt b/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation3.txt new file mode 100644 index 000000000..12e174c56 --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation3.txt @@ -0,0 +1,9 @@ +error[E####]: spacing error found + --> foo.txt:26:12 + | +26 | This is an exampl + | ____________^ +27 | | e of an edge case of an annotation overflowing + | |_^ this should not be on separate lines +28 | to exactly one character on next line. + | \ No newline at end of file diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/multiple_annotations.toml b/vendor/annotate-snippets/tests/fixtures/no-color/multiple_annotations.toml new file mode 100644 index 000000000..84efc5f17 --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/multiple_annotations.toml @@ -0,0 +1,25 @@ +[[slices]] +source = """ +fn add_title_line(result: &mut Vec, main_annotation: Option<&Annotation>) { + if let Some(annotation) = main_annotation { + result.push(format_title_line( + &annotation.annotation_type, + None, + &annotation.label, + )); + } +} +""" +line_start = 96 +[[slices.annotations]] +label = "Variable defined here" +annotation_type = "Error" +range = [100, 110] +[[slices.annotations]] +label = "Referenced here" +annotation_type = "Error" +range = [184, 194] +[[slices.annotations]] +label = "Referenced again here" +annotation_type = "Error" +range = [243, 253] diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/multiple_annotations.txt b/vendor/annotate-snippets/tests/fixtures/no-color/multiple_annotations.txt new file mode 100644 index 000000000..26c677f7e --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/multiple_annotations.txt @@ -0,0 +1,14 @@ + | + 96 | fn add_title_line(result: &mut Vec, main_annotation: Option<&Annotation>) { + 97 | if let Some(annotation) = main_annotation { + | ^^^^^^^^^^ Variable defined here + 98 | result.push(format_title_line( + 99 | &annotation.annotation_type, + | ^^^^^^^^^^ Referenced here +100 | None, +101 | &annotation.label, + | ^^^^^^^^^^ Referenced again here +102 | )); +103 | } +104 | } + | diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/simple.toml b/vendor/annotate-snippets/tests/fixtures/no-color/simple.toml new file mode 100644 index 000000000..6c38674ac --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/simple.toml @@ -0,0 +1,18 @@ +[[slices]] +source = """ + }) + + for line in &self.body {""" +line_start = 169 +origin = "src/format_color.rs" +[[slices.annotations]] +label = "unexpected token" +annotation_type = "Error" +range = [20, 23] +[[slices.annotations]] +label = "expected one of `.`, `;`, `?`, or an operator here" +annotation_type = "Warning" +range = [10, 11] +[title] +label = "expected one of `.`, `;`, `?`, or an operator, found `for`" +annotation_type = "Error" diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/simple.txt b/vendor/annotate-snippets/tests/fixtures/no-color/simple.txt new file mode 100644 index 000000000..752cc890f --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/simple.txt @@ -0,0 +1,9 @@ +error: expected one of `.`, `;`, `?`, or an operator, found `for` + --> src/format_color.rs:171:9 + | +169 | }) + | - expected one of `.`, `;`, `?`, or an operator here +170 | +171 | for line in &self.body { + | ^^^ unexpected token + | diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/strip_line.toml b/vendor/annotate-snippets/tests/fixtures/no-color/strip_line.toml new file mode 100644 index 000000000..76d9519bd --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/strip_line.toml @@ -0,0 +1,25 @@ +[title] +id = "E0308" +label = "mismatched types" +annotation_type = "Error" + +[[slices]] +source = " let _: () = 42;" +line_start = 4 +origin = "$DIR/whitespace-trimming.rs" + +[[slices.annotations]] +label = "expected (), found integer" +annotation_type = "Error" +range = [192, 194] + +[opt] +color = false +anonymized_line_numbers = true +[opt.margin] +whitespace_left = 180 +span_left = 192 +span_right = 194 +label_right = 221 +column_width = 140 +max_line_len = 195 diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/strip_line.txt b/vendor/annotate-snippets/tests/fixtures/no-color/strip_line.txt new file mode 100644 index 000000000..65b053840 --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/strip_line.txt @@ -0,0 +1,6 @@ +error[E0308]: mismatched types + --> $DIR/whitespace-trimming.rs:4:193 + | +LL | ... let _: () = 42; + | ^^ expected (), found integer + | diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/strip_line_char.toml b/vendor/annotate-snippets/tests/fixtures/no-color/strip_line_char.toml new file mode 100644 index 000000000..5b432beb6 --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/strip_line_char.toml @@ -0,0 +1,25 @@ +[title] +id = "E0308" +label = "mismatched types" +annotation_type = "Error" + +[[slices]] +source = " let _: () = 42ñ" +line_start = 4 +origin = "$DIR/whitespace-trimming.rs" + +[[slices.annotations]] +label = "expected (), found integer" +annotation_type = "Error" +range = [192, 194] + +[opt] +color = false +anonymized_line_numbers = true +[opt.margin] +whitespace_left = 180 +span_left = 192 +span_right = 194 +label_right = 221 +column_width = 140 +max_line_len = 195 diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/strip_line_char.txt b/vendor/annotate-snippets/tests/fixtures/no-color/strip_line_char.txt new file mode 100644 index 000000000..3d4b700cd --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/strip_line_char.txt @@ -0,0 +1,6 @@ +error[E0308]: mismatched types + --> $DIR/whitespace-trimming.rs:4:193 + | +LL | ... let _: () = 42ñ + | ^^ expected (), found integer + | diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/strip_line_non_ws.toml b/vendor/annotate-snippets/tests/fixtures/no-color/strip_line_non_ws.toml new file mode 100644 index 000000000..5129f5ce7 --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/strip_line_non_ws.toml @@ -0,0 +1,25 @@ +[title] +id = "E0308" +label = "mismatched types" +annotation_type = "Error" + +[[slices]] +source = " let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = ();" +line_start = 4 +origin = "$DIR/non-whitespace-trimming.rs" + +[[slices.annotations]] +label = "expected (), found integer" +annotation_type = "Error" +range = [240, 242] + +[opt] +color = false +anonymized_line_numbers = true +[opt.margin] +whitespace_left = 4 +span_left = 240 +span_right = 242 +label_right = 271 +column_width = 140 +max_line_len = 371 diff --git a/vendor/annotate-snippets/tests/fixtures/no-color/strip_line_non_ws.txt b/vendor/annotate-snippets/tests/fixtures/no-color/strip_line_non_ws.txt new file mode 100644 index 000000000..850619ad1 --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures/no-color/strip_line_non_ws.txt @@ -0,0 +1,6 @@ +error[E0308]: mismatched types + --> $DIR/non-whitespace-trimming.rs:4:241 + | +LL | ... = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = ();... + | ^^ expected (), found integer + | diff --git a/vendor/annotate-snippets/tests/fixtures_test.rs b/vendor/annotate-snippets/tests/fixtures_test.rs new file mode 100644 index 000000000..e471521f2 --- /dev/null +++ b/vendor/annotate-snippets/tests/fixtures_test.rs @@ -0,0 +1,45 @@ +mod diff; +mod snippet; + +use crate::snippet::SnippetDef; +use annotate_snippets::{display_list::DisplayList, snippet::Snippet}; +use glob::glob; +use std::{error::Error, fs::File, io, io::prelude::*}; + +fn read_file(path: &str) -> Result { + let mut f = File::open(path)?; + let mut s = String::new(); + (f.read_to_string(&mut s))?; + Ok(s.trim_end().to_string()) +} + +fn read_fixture<'de>(src: &'de str) -> Result, Box> { + Ok(toml::from_str(src).map(|a: SnippetDef| a.into())?) +} + +#[test] +fn test_fixtures() { + for entry in glob("./tests/fixtures/no-color/**/*.toml").expect("Failed to read glob pattern") { + let p = entry.expect("Error while getting an entry"); + + let path_in = p.to_str().expect("Can't print path"); + let path_out = path_in.replace(".toml", ".txt"); + + let src = read_file(&path_in).expect("Failed to read file"); + let snippet = read_fixture(&src).expect("Failed to read file"); + let expected_out = read_file(&path_out).expect("Failed to read file"); + + let dl = DisplayList::from(snippet); + let actual_out = dl.to_string(); + println!("{}", expected_out); + println!("{}", actual_out.trim_end()); + + assert_eq!( + expected_out, + actual_out.trim_end(), + "\n\n\nWhile parsing: {}\nThe diff is:\n\n\n{}\n\n\n", + path_in, + diff::get_diff(expected_out.as_str(), actual_out.as_str()) + ); + } +} diff --git a/vendor/annotate-snippets/tests/formatter.rs b/vendor/annotate-snippets/tests/formatter.rs new file mode 100644 index 000000000..b1392a1d7 --- /dev/null +++ b/vendor/annotate-snippets/tests/formatter.rs @@ -0,0 +1,675 @@ +use annotate_snippets::display_list::*; +use annotate_snippets::snippet::{self, Snippet}; + +#[test] +fn test_source_empty() { + let dl = DisplayList::from(vec![DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Empty, + }]); + + assert_eq!(dl.to_string(), " |"); +} + +#[test] +fn test_source_content() { + let dl = DisplayList::from(vec![ + DisplayLine::Source { + lineno: Some(56), + inline_marks: vec![], + line: DisplaySourceLine::Content { + text: "This is an example", + range: (0, 19), + }, + }, + DisplayLine::Source { + lineno: Some(57), + inline_marks: vec![], + line: DisplaySourceLine::Content { + text: "of content lines", + range: (0, 19), + }, + }, + ]); + + assert_eq!( + dl.to_string(), + "56 | This is an example\n57 | of content lines" + ); +} + +#[test] +fn test_source_annotation_standalone_singleline() { + let dl = DisplayList::from(vec![DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Annotation { + range: (0, 5), + annotation: Annotation { + annotation_type: DisplayAnnotationType::None, + id: None, + label: vec![DisplayTextFragment { + content: "Example string", + style: DisplayTextStyle::Regular, + }], + }, + annotation_type: DisplayAnnotationType::Error, + annotation_part: DisplayAnnotationPart::Standalone, + }, + }]); + + assert_eq!(dl.to_string(), " | ^^^^^ Example string"); +} + +#[test] +fn test_source_annotation_standalone_multiline() { + let dl = DisplayList::from(vec![ + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Annotation { + range: (0, 5), + annotation: Annotation { + annotation_type: DisplayAnnotationType::Help, + id: None, + label: vec![DisplayTextFragment { + content: "Example string", + style: DisplayTextStyle::Regular, + }], + }, + annotation_type: DisplayAnnotationType::Warning, + annotation_part: DisplayAnnotationPart::Standalone, + }, + }, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Annotation { + range: (0, 5), + annotation: Annotation { + annotation_type: DisplayAnnotationType::Help, + id: None, + label: vec![DisplayTextFragment { + content: "Second line", + style: DisplayTextStyle::Regular, + }], + }, + annotation_type: DisplayAnnotationType::Warning, + annotation_part: DisplayAnnotationPart::LabelContinuation, + }, + }, + ]); + + assert_eq!( + dl.to_string(), + " | ----- help: Example string\n | Second line" + ); +} + +#[test] +fn test_source_annotation_standalone_multi_annotation() { + let dl = DisplayList::from(vec![ + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Annotation { + range: (0, 5), + annotation: Annotation { + annotation_type: DisplayAnnotationType::Info, + id: None, + label: vec![DisplayTextFragment { + content: "Example string", + style: DisplayTextStyle::Regular, + }], + }, + annotation_type: DisplayAnnotationType::Note, + annotation_part: DisplayAnnotationPart::Standalone, + }, + }, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Annotation { + range: (0, 5), + annotation: Annotation { + annotation_type: DisplayAnnotationType::Info, + id: None, + label: vec![DisplayTextFragment { + content: "Second line", + style: DisplayTextStyle::Regular, + }], + }, + annotation_type: DisplayAnnotationType::Note, + annotation_part: DisplayAnnotationPart::LabelContinuation, + }, + }, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Annotation { + range: (0, 5), + annotation: Annotation { + annotation_type: DisplayAnnotationType::Warning, + id: None, + label: vec![DisplayTextFragment { + content: "This is a note", + style: DisplayTextStyle::Regular, + }], + }, + annotation_type: DisplayAnnotationType::Note, + annotation_part: DisplayAnnotationPart::Consequitive, + }, + }, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Annotation { + range: (0, 5), + annotation: Annotation { + annotation_type: DisplayAnnotationType::Warning, + id: None, + label: vec![DisplayTextFragment { + content: "Second line of the warning", + style: DisplayTextStyle::Regular, + }], + }, + annotation_type: DisplayAnnotationType::Note, + annotation_part: DisplayAnnotationPart::LabelContinuation, + }, + }, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Annotation { + range: (0, 5), + annotation: Annotation { + annotation_type: DisplayAnnotationType::Info, + id: None, + label: vec![DisplayTextFragment { + content: "This is an info", + style: DisplayTextStyle::Regular, + }], + }, + annotation_type: DisplayAnnotationType::Info, + annotation_part: DisplayAnnotationPart::Standalone, + }, + }, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Annotation { + range: (0, 5), + annotation: Annotation { + annotation_type: DisplayAnnotationType::Help, + id: None, + label: vec![DisplayTextFragment { + content: "This is help", + style: DisplayTextStyle::Regular, + }], + }, + annotation_type: DisplayAnnotationType::Help, + annotation_part: DisplayAnnotationPart::Standalone, + }, + }, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Annotation { + range: (0, 0), + annotation: Annotation { + annotation_type: DisplayAnnotationType::None, + id: None, + label: vec![DisplayTextFragment { + content: "This is an annotation of type none", + style: DisplayTextStyle::Regular, + }], + }, + annotation_type: DisplayAnnotationType::None, + annotation_part: DisplayAnnotationPart::Standalone, + }, + }, + ]); + + assert_eq!(dl.to_string(), " | ----- info: Example string\n | Second line\n | warning: This is a note\n | Second line of the warning\n | ----- info: This is an info\n | ----- help: This is help\n | This is an annotation of type none"); +} + +#[test] +fn test_fold_line() { + let dl = DisplayList::from(vec![ + DisplayLine::Source { + lineno: Some(5), + inline_marks: vec![], + line: DisplaySourceLine::Content { + text: "This is line 5", + range: (0, 19), + }, + }, + DisplayLine::Fold { + inline_marks: vec![], + }, + DisplayLine::Source { + lineno: Some(10021), + inline_marks: vec![], + line: DisplaySourceLine::Content { + text: "... and now we're at line 10021", + range: (0, 19), + }, + }, + ]); + + assert_eq!( + dl.to_string(), + " 5 | This is line 5\n...\n10021 | ... and now we're at line 10021" + ); +} + +#[test] +fn test_raw_origin_initial_nopos() { + let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin { + path: "src/test.rs", + pos: None, + header_type: DisplayHeaderType::Initial, + })]); + + assert_eq!(dl.to_string(), "--> src/test.rs"); +} + +#[test] +fn test_raw_origin_initial_pos() { + let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin { + path: "src/test.rs", + pos: Some((23, 15)), + header_type: DisplayHeaderType::Initial, + })]); + + assert_eq!(dl.to_string(), "--> src/test.rs:23:15"); +} + +#[test] +fn test_raw_origin_continuation() { + let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin { + path: "src/test.rs", + pos: Some((23, 15)), + header_type: DisplayHeaderType::Continuation, + })]); + + assert_eq!(dl.to_string(), "::: src/test.rs:23:15"); +} + +#[test] +fn test_raw_annotation_unaligned() { + let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::Error, + id: Some("E0001"), + label: vec![DisplayTextFragment { + content: "This is an error", + style: DisplayTextStyle::Regular, + }], + }, + source_aligned: false, + continuation: false, + })]); + + assert_eq!(dl.to_string(), "error[E0001]: This is an error"); +} + +#[test] +fn test_raw_annotation_unaligned_multiline() { + let dl = DisplayList::from(vec![ + DisplayLine::Raw(DisplayRawLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::Warning, + id: Some("E0001"), + label: vec![DisplayTextFragment { + content: "This is an error", + style: DisplayTextStyle::Regular, + }], + }, + source_aligned: false, + continuation: false, + }), + DisplayLine::Raw(DisplayRawLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::Warning, + id: Some("E0001"), + label: vec![DisplayTextFragment { + content: "Second line of the error", + style: DisplayTextStyle::Regular, + }], + }, + source_aligned: false, + continuation: true, + }), + ]); + + assert_eq!( + dl.to_string(), + "warning[E0001]: This is an error\n Second line of the error" + ); +} + +#[test] +fn test_raw_annotation_aligned() { + let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::Error, + id: Some("E0001"), + label: vec![DisplayTextFragment { + content: "This is an error", + style: DisplayTextStyle::Regular, + }], + }, + source_aligned: true, + continuation: false, + })]); + + assert_eq!(dl.to_string(), " = error[E0001]: This is an error"); +} + +#[test] +fn test_raw_annotation_aligned_multiline() { + let dl = DisplayList::from(vec![ + DisplayLine::Raw(DisplayRawLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::Warning, + id: Some("E0001"), + label: vec![DisplayTextFragment { + content: "This is an error", + style: DisplayTextStyle::Regular, + }], + }, + source_aligned: true, + continuation: false, + }), + DisplayLine::Raw(DisplayRawLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::Warning, + id: Some("E0001"), + label: vec![DisplayTextFragment { + content: "Second line of the error", + style: DisplayTextStyle::Regular, + }], + }, + source_aligned: true, + continuation: true, + }), + ]); + + assert_eq!( + dl.to_string(), + " = warning[E0001]: This is an error\n Second line of the error" + ); +} + +#[test] +fn test_different_annotation_types() { + let dl = DisplayList::from(vec![ + DisplayLine::Raw(DisplayRawLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::Note, + id: None, + label: vec![DisplayTextFragment { + content: "This is a note", + style: DisplayTextStyle::Regular, + }], + }, + source_aligned: false, + continuation: false, + }), + DisplayLine::Raw(DisplayRawLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::None, + id: None, + label: vec![DisplayTextFragment { + content: "This is just a string", + style: DisplayTextStyle::Regular, + }], + }, + source_aligned: false, + continuation: false, + }), + DisplayLine::Raw(DisplayRawLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::None, + id: None, + label: vec![DisplayTextFragment { + content: "Second line of none type annotation", + style: DisplayTextStyle::Regular, + }], + }, + source_aligned: false, + continuation: true, + }), + ]); + + assert_eq!( + dl.to_string(), + "note: This is a note\nThis is just a string\n Second line of none type annotation", + ); +} + +#[test] +fn test_inline_marks_empty_line() { + let dl = DisplayList::from(vec![DisplayLine::Source { + lineno: None, + inline_marks: vec![DisplayMark { + mark_type: DisplayMarkType::AnnotationThrough, + annotation_type: DisplayAnnotationType::Error, + }], + line: DisplaySourceLine::Empty, + }]); + + assert_eq!(dl.to_string(), " | |",); +} + +#[test] +fn test_anon_lines() { + let mut dl = DisplayList::from(vec![ + DisplayLine::Source { + lineno: Some(56), + inline_marks: vec![], + line: DisplaySourceLine::Content { + text: "This is an example", + range: (0, 19), + }, + }, + DisplayLine::Source { + lineno: Some(57), + inline_marks: vec![], + line: DisplaySourceLine::Content { + text: "of content lines", + range: (0, 19), + }, + }, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Empty, + }, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Content { + text: "abc", + range: (0, 19), + }, + }, + ]); + + dl.anonymized_line_numbers = true; + assert_eq!( + dl.to_string(), + "LL | This is an example\nLL | of content lines\n |\n | abc" + ); +} + +#[test] +fn test_raw_origin_initial_pos_anon_lines() { + let mut dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin { + path: "src/test.rs", + pos: Some((23, 15)), + header_type: DisplayHeaderType::Initial, + })]); + + // Using anonymized_line_numbers should not affect the inital position + dl.anonymized_line_numbers = true; + assert_eq!(dl.to_string(), "--> src/test.rs:23:15"); +} + +#[test] +fn test_i_29() { + let snippets = Snippet { + title: Some(snippet::Annotation { + id: None, + label: Some("oops"), + annotation_type: snippet::AnnotationType::Error, + }), + footer: vec![], + slices: vec![snippet::Slice { + source: "First line\r\nSecond oops line", + line_start: 1, + origin: Some(""), + annotations: vec![snippet::SourceAnnotation { + range: (19, 23), + label: "oops", + annotation_type: snippet::AnnotationType::Error, + }], + fold: true, + }], + opt: Default::default(), + }; + let expected = r#"error: oops + --> :2:8 + | +1 | First line +2 | Second oops line + | ^^^^ oops + |"#; + + assert_eq!(DisplayList::from(snippets).to_string(), expected); +} + +#[test] +fn test_point_to_double_width_characters() { + let snippets = Snippet { + slices: vec![snippet::Slice { + source: "こんにちは、世界", + line_start: 1, + origin: Some(""), + annotations: vec![snippet::SourceAnnotation { + range: (6, 8), + label: "world", + annotation_type: snippet::AnnotationType::Error, + }], + fold: false, + }], + title: None, + footer: vec![], + opt: Default::default(), + }; + + let expected = r#" --> :1:7 + | +1 | こんにちは、世界 + | ^^^^ world + |"#; + + assert_eq!(DisplayList::from(snippets).to_string(), expected); +} + +#[test] +fn test_point_to_double_width_characters_across_lines() { + let snippets = Snippet { + slices: vec![snippet::Slice { + source: "おはよう\nございます", + line_start: 1, + origin: Some(""), + annotations: vec![snippet::SourceAnnotation { + range: (2, 8), + label: "Good morning", + annotation_type: snippet::AnnotationType::Error, + }], + fold: false, + }], + title: None, + footer: vec![], + opt: Default::default(), + }; + + let expected = r#" --> :1:3 + | +1 | おはよう + | _____^ +2 | | ございます + | |______^ Good morning + |"#; + + assert_eq!(DisplayList::from(snippets).to_string(), expected); +} + +#[test] +fn test_point_to_double_width_characters_multiple() { + let snippets = Snippet { + slices: vec![snippet::Slice { + source: "お寿司\n食べたい🍣", + line_start: 1, + origin: Some(""), + annotations: vec![ + snippet::SourceAnnotation { + range: (0, 3), + label: "Sushi1", + annotation_type: snippet::AnnotationType::Error, + }, + snippet::SourceAnnotation { + range: (6, 8), + label: "Sushi2", + annotation_type: snippet::AnnotationType::Note, + }, + ], + fold: false, + }], + title: None, + footer: vec![], + opt: Default::default(), + }; + + let expected = r#" --> :1:1 + | +1 | お寿司 + | ^^^^^^ Sushi1 +2 | 食べたい🍣 + | ---- note: Sushi2 + |"#; + + assert_eq!(DisplayList::from(snippets).to_string(), expected); +} + +#[test] +fn test_point_to_double_width_characters_mixed() { + let snippets = Snippet { + slices: vec![snippet::Slice { + source: "こんにちは、新しいWorld!", + line_start: 1, + origin: Some(""), + annotations: vec![snippet::SourceAnnotation { + range: (6, 14), + label: "New world", + annotation_type: snippet::AnnotationType::Error, + }], + fold: false, + }], + title: None, + footer: vec![], + opt: Default::default(), + }; + + let expected = r#" --> :1:7 + | +1 | こんにちは、新しいWorld! + | ^^^^^^^^^^^ New world + |"#; + + assert_eq!(DisplayList::from(snippets).to_string(), expected); +} diff --git a/vendor/annotate-snippets/tests/snippet/mod.rs b/vendor/annotate-snippets/tests/snippet/mod.rs new file mode 100644 index 000000000..40249f409 --- /dev/null +++ b/vendor/annotate-snippets/tests/snippet/mod.rs @@ -0,0 +1,208 @@ +use serde::{Deserialize, Deserializer, Serialize}; + +use annotate_snippets::{ + display_list::{FormatOptions, Margin}, + snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}, +}; + +#[derive(Deserialize)] +pub struct SnippetDef<'a> { + #[serde(deserialize_with = "deserialize_annotation")] + #[serde(default)] + #[serde(borrow)] + pub title: Option>, + #[serde(deserialize_with = "deserialize_annotations")] + #[serde(default)] + #[serde(borrow)] + pub footer: Vec>, + #[serde(deserialize_with = "deserialize_opt")] + #[serde(default)] + pub opt: FormatOptions, + #[serde(deserialize_with = "deserialize_slices")] + #[serde(borrow)] + pub slices: Vec>, +} + +impl<'a> Into> for SnippetDef<'a> { + fn into(self) -> Snippet<'a> { + let SnippetDef { + title, + footer, + opt, + slices, + } = self; + Snippet { + title, + footer, + slices, + opt, + } + } +} + +fn deserialize_opt<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + #[derive(Deserialize)] + struct Wrapper(#[serde(with = "FormatOptionsDef")] FormatOptions); + + Wrapper::deserialize(deserializer).map(|w| w.0) +} + +#[derive(Deserialize)] +#[serde(remote = "FormatOptions")] +pub struct FormatOptionsDef { + #[serde(default)] + pub color: bool, + #[serde(default)] + pub anonymized_line_numbers: bool, + #[serde(deserialize_with = "deserialize_margin")] + #[serde(default)] + pub margin: Option, +} + +fn deserialize_margin<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + #[derive(Deserialize)] + struct Wrapper { + whitespace_left: usize, + span_left: usize, + span_right: usize, + label_right: usize, + column_width: usize, + max_line_len: usize, + } + + Option::::deserialize(deserializer).map(|opt_wrapped: Option| { + opt_wrapped.map(|wrapped: Wrapper| { + let Wrapper { + whitespace_left, + span_left, + span_right, + label_right, + column_width, + max_line_len, + } = wrapped; + Margin::new( + whitespace_left, + span_left, + span_right, + label_right, + column_width, + max_line_len, + ) + }) + }) +} + +fn deserialize_slices<'de, D>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + #[derive(Deserialize)] + struct Wrapper<'a>( + #[serde(with = "SliceDef")] + #[serde(borrow)] + Slice<'a>, + ); + + let v = Vec::deserialize(deserializer)?; + Ok(v.into_iter().map(|Wrapper(a)| a).collect()) +} + +fn deserialize_annotation<'de, D>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + #[derive(Deserialize)] + struct Wrapper<'a>( + #[serde(with = "AnnotationDef")] + #[serde(borrow)] + Annotation<'a>, + ); + + Option::::deserialize(deserializer) + .map(|opt_wrapped: Option| opt_wrapped.map(|wrapped: Wrapper| wrapped.0)) +} + +fn deserialize_annotations<'de, D>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + #[derive(Deserialize)] + struct Wrapper<'a>( + #[serde(with = "AnnotationDef")] + #[serde(borrow)] + Annotation<'a>, + ); + + let v = Vec::deserialize(deserializer)?; + Ok(v.into_iter().map(|Wrapper(a)| a).collect()) +} + +#[derive(Deserialize)] +#[serde(remote = "Slice")] +pub struct SliceDef<'a> { + #[serde(borrow)] + pub source: &'a str, + pub line_start: usize, + #[serde(borrow)] + pub origin: Option<&'a str>, + #[serde(deserialize_with = "deserialize_source_annotations")] + #[serde(borrow)] + pub annotations: Vec>, + #[serde(default)] + pub fold: bool, +} + +fn deserialize_source_annotations<'de, D>( + deserializer: D, +) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + #[derive(Deserialize)] + struct Wrapper<'a>( + #[serde(with = "SourceAnnotationDef")] + #[serde(borrow)] + SourceAnnotation<'a>, + ); + + let v = Vec::deserialize(deserializer)?; + Ok(v.into_iter().map(|Wrapper(a)| a).collect()) +} + +#[derive(Serialize, Deserialize)] +#[serde(remote = "SourceAnnotation")] +pub struct SourceAnnotationDef<'a> { + pub range: (usize, usize), + #[serde(borrow)] + pub label: &'a str, + #[serde(with = "AnnotationTypeDef")] + pub annotation_type: AnnotationType, +} + +#[derive(Serialize, Deserialize)] +#[serde(remote = "Annotation")] +pub struct AnnotationDef<'a> { + #[serde(borrow)] + pub id: Option<&'a str>, + #[serde(borrow)] + pub label: Option<&'a str>, + #[serde(with = "AnnotationTypeDef")] + pub annotation_type: AnnotationType, +} + +#[allow(dead_code)] +#[derive(Serialize, Deserialize)] +#[serde(remote = "AnnotationType")] +enum AnnotationTypeDef { + Error, + Warning, + Info, + Note, + Help, +} -- cgit v1.2.3