From e7b7555d1516d0b274e7269961fce9ec9b30bc98 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 29 Mar 2023 14:33:22 -0500 Subject: [PATCH 001/175] chore: First step --- .cargo/config | 5 + .clippy.toml | 12 ++ .github/renovate.json5 | 71 +++++++++++ .github/settings.yml | 52 ++++++++ .github/workflows/audit.yml | 49 ++++++++ .github/workflows/ci.yml | 128 ++++++++++++++++++++ .github/workflows/committed.yml | 24 ++++ .github/workflows/pre-commit.yml | 23 ++++ .github/workflows/rust-next.yml | 88 ++++++++++++++ .github/workflows/spelling.yml | 21 ++++ .gitignore | 1 + .pre-commit-config.yaml | 26 ++++ CHANGELOG.md | 11 ++ CONTRIBUTING.md | 70 +++++++++++ Cargo.lock | 7 ++ Cargo.toml | 38 ++++++ LICENSE-APACHE | 202 +++++++++++++++++++++++++++++++ LICENSE-MIT | 19 +++ README.md | 26 ++++ committed.toml | 3 + deny.toml | 135 +++++++++++++++++++++ release.toml | 6 + src/lib.rs | 2 + 23 files changed, 1019 insertions(+) create mode 100644 .cargo/config create mode 100644 .clippy.toml create mode 100644 .github/renovate.json5 create mode 100644 .github/settings.yml create mode 100644 .github/workflows/audit.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/committed.yml create mode 100644 .github/workflows/pre-commit.yml create mode 100644 .github/workflows/rust-next.yml create mode 100644 .github/workflows/spelling.yml create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT create mode 100644 README.md create mode 100644 committed.toml create mode 100644 deny.toml create mode 100644 release.toml create mode 100644 src/lib.rs diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 0000000..ba32123 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,5 @@ +[target.x86_64-pc-windows-msvc] +rustflags = ["-Ctarget-feature=+crt-static"] + +[target.i686-pc-windows-msvc] +rustflags = ["-Ctarget-feature=+crt-static"] diff --git a/.clippy.toml b/.clippy.toml new file mode 100644 index 0000000..16749ab --- /dev/null +++ b/.clippy.toml @@ -0,0 +1,12 @@ +msrv = "1.64.0" # MSRV +warn-on-all-wildcard-imports = true +allow-expect-in-tests = true +allow-unwrap-in-tests = true +allow-dbg-in-tests = true +allow-print-in-tests = true +disallowed-methods = [ + { path = "std::option::Option::map_or", reason = "use `map(..).unwrap_or(..)`" }, + { path = "std::option::Option::map_or_else", reason = "use `map(..).unwrap_or_else(..)`" }, + { path = "std::result::Result::map_or", reason = "use `map(..).unwrap_or(..)`" }, + { path = "std::result::Result::map_or_else", reason = "use `map(..).unwrap_or_else(..)`" }, +] diff --git a/.github/renovate.json5 b/.github/renovate.json5 new file mode 100644 index 0000000..51faa75 --- /dev/null +++ b/.github/renovate.json5 @@ -0,0 +1,71 @@ +{ + "schedule": [ + "before 3am on the first day of the month" + ], + "semanticCommits": "enabled", + "configMigration": true, + "dependencyDashboard": true, + "regexManagers": [ + { + "fileMatch": [ + "^rust-toolchain\\.toml$", + "Cargo.toml$", + "clippy.toml$", + "\.clippy.toml$", + "^\.github/workflows/ci.yml$", + "^\.github/workflows/rust-next.yml$", + ], + "matchStrings": [ + "MSRV.*?(?\\d+\\.\\d+(\\.\\d+)?)", + "(?\\d+\\.\\d+(\\.\\d+)?).*?MSRV", + ], + "depNameTemplate": "rust", + "packageNameTemplate": "rust-lang/rust", + "datasourceTemplate": "github-releases", + } + ], + "packageRules": [ + { + "commitMessageTopic": "MSRV", + "matchManagers": ["regex"], + "matchPackageNames": ["rust"], + "stabilityDays": 126, // 3 releases * 6 weeks per release * 7 days per week + }, + // Goals: + // - Keep version reqs low, ignoring compatible normal/build dependencies + // - Take advantage of latest dev-dependencies + // - Rollup safe upgrades to reduce CI runner load + // - Help keep number of versions down by always using latest breaking change + // - Have lockfile and manifest in-sync + { + "matchManagers": ["cargo"], + "matchDepTypes": ["build-dependencies", "dependencies"], + "matchCurrentVersion": ">=0.1.0", + "matchUpdateTypes": ["patch"], + "enabled": false, + }, + { + "matchManagers": ["cargo"], + "matchDepTypes": ["build-dependencies", "dependencies"], + "matchCurrentVersion": ">=1.0.0", + "matchUpdateTypes": ["minor"], + "enabled": false, + }, + { + "matchManagers": ["cargo"], + "matchDepTypes": ["dev-dependencies"], + "matchCurrentVersion": ">=0.1.0", + "matchUpdateTypes": ["patch"], + "automerge": true, + "groupName": "compatible (dev)", + }, + { + "matchManagers": ["cargo"], + "matchDepTypes": ["dev-dependencies"], + "matchCurrentVersion": ">=1.0.0", + "matchUpdateTypes": ["minor"], + "automerge": true, + "groupName": "compatible (dev)", + }, + ], +} diff --git a/.github/settings.yml b/.github/settings.yml new file mode 100644 index 0000000..0469378 --- /dev/null +++ b/.github/settings.yml @@ -0,0 +1,52 @@ +# These settings are synced to GitHub by https://probot.github.io/apps/settings/ + +repository: + description: "DESCRIPTION" + homepage: "https://docs.rs/PROJECT" + topics: "" + has_issues: true + has_projects: false + has_wiki: false + has_downloads: true + default_branch: main + + allow_squash_merge: true + allow_merge_commit: true + allow_rebase_merge: true + + allow_auto_merge: true + delete_branch_on_merge: true + + squash_merge_commit_title: "PR_TITLE" + squash_merge_commit_message: "PR_BODY" + merge_commit_message: "PR_BODY" + +labels: + # Type + - name: bug + color: '#b60205' + description: Not as expected + - name: enhancement + color: '#1d76db' + description: Improve the expected + # Flavor + - name: question + color: "#cc317c" + description: Uncertainty is involved + - name: breaking-change + color: "#e99695" + - name: good first issue + color: '#c2e0c6' + description: Help wanted! + +branches: + - name: main + protection: + required_pull_request_reviews: null + required_conversation_resolution: true + required_status_checks: + # Required. Require branches to be up to date before merging. + strict: false + contexts: ["CI", "Lint Commits", "Spell Check with Typos"] + enforce_admins: false + restrictions: null diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml new file mode 100644 index 0000000..5b7e83a --- /dev/null +++ b/.github/workflows/audit.yml @@ -0,0 +1,49 @@ +name: Security audit + +permissions: + contents: read + +on: + pull_request: + paths: + - '**/Cargo.toml' + - '**/Cargo.lock' + push: + branches: + - main + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + +jobs: + security_audit: + permissions: + issues: write # to create issues (actions-rs/audit-check) + checks: write # to create check (actions-rs/audit-check) + runs-on: ubuntu-latest + # Prevent sudden announcement of a new advisory from failing ci: + continue-on-error: true + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - uses: actions-rs/audit-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + cargo_deny: + permissions: + issues: write # to create issues (actions-rs/audit-check) + checks: write # to create check (actions-rs/audit-check) + runs-on: ubuntu-latest + strategy: + matrix: + checks: + - bans licenses sources + steps: + - uses: actions/checkout@v3 + - uses: EmbarkStudios/cargo-deny-action@v1 + with: + command: check ${{ matrix.checks }} + rust-version: stable diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..783247c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,128 @@ +name: CI + +permissions: + contents: read + +on: + pull_request: + push: + branches: + - main + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + +jobs: + ci: + permissions: + contents: none + name: CI + needs: [test, msrv, docs, rustfmt, clippy] + runs-on: ubuntu-latest + steps: + - name: Done + run: exit 0 + test: + name: Test + strategy: + matrix: + os: ["ubuntu-latest", "windows-latest", "macos-latest"] + rust: ["stable"] + continue-on-error: ${{ matrix.rust != 'stable' }} + runs-on: ${{ matrix.os }} + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ matrix.rust }} + - uses: Swatinem/rust-cache@v2 + - name: Build + run: cargo test --no-run --workspace --all-features + - name: Default features + run: cargo test --workspace + - name: All features + run: cargo test --workspace --all-features + - name: No-default features + run: cargo test --workspace --no-default-features + msrv: + name: "Check MSRV: 1.64.0" + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.64.0 # MSRV + - uses: Swatinem/rust-cache@v2 + - name: Default features + run: cargo check --workspace --all-targets + - name: All features + run: cargo check --workspace --all-targets --all-features + - name: No-default features + run: cargo check --workspace --all-targets --no-default-features + docs: + name: Docs + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + - uses: Swatinem/rust-cache@v2 + - name: Check documentation + env: + RUSTDOCFLAGS: -D warnings + run: cargo doc --workspace --all-features --no-deps --document-private-items + rustfmt: + name: rustfmt + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + # Not MSRV because its harder to jump between versions and people are + # more likely to have stable + toolchain: stable + components: rustfmt + - uses: Swatinem/rust-cache@v2 + - name: Check formatting + run: cargo fmt --all -- --check + clippy: + name: clippy + runs-on: ubuntu-latest + permissions: + security-events: write # to upload sarif results + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.64.0 # MSRV + components: clippy + - uses: Swatinem/rust-cache@v2 + - name: Install SARIF tools + run: cargo install clippy-sarif --version 0.3.4 --locked # Held back due to msrv + - name: Install SARIF tools + run: cargo install sarif-fmt --version 0.3.4 --locked # Held back due to msrv + - name: Check + run: > + cargo clippy --workspace --all-features --all-targets --message-format=json -- -D warnings --allow deprecated + | clippy-sarif + | tee clippy-results.sarif + | sarif-fmt + continue-on-error: true + - name: Upload + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: clippy-results.sarif + wait-for-processing: true diff --git a/.github/workflows/committed.yml b/.github/workflows/committed.yml new file mode 100644 index 0000000..509be08 --- /dev/null +++ b/.github/workflows/committed.yml @@ -0,0 +1,24 @@ +# Not run as part of pre-commit checks because they don't handle sending the correct commit +# range to `committed` +name: Lint Commits +on: [pull_request] + +permissions: + contents: read + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + +jobs: + committed: + name: Lint Commits + runs-on: ubuntu-latest + steps: + - name: Checkout Actions Repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Lint Commits + uses: crate-ci/committed@master diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..d4b0f84 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,23 @@ +name: pre-commit + +permissions: {} # none + +on: + pull_request: + push: + branches: [main] + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + +jobs: + pre-commit: + permissions: + contents: read + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + - uses: pre-commit/action@v3.0.0 diff --git a/.github/workflows/rust-next.yml b/.github/workflows/rust-next.yml new file mode 100644 index 0000000..8faba30 --- /dev/null +++ b/.github/workflows/rust-next.yml @@ -0,0 +1,88 @@ +name: rust-next + +permissions: + contents: read + +on: + schedule: + - cron: '1 1 1 * *' + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + +jobs: + test: + name: Test + strategy: + matrix: + os: ["ubuntu-latest", "windows-latest", "macos-latest"] + rust: ["stable", "beta"] + include: + - os: ubuntu-latest + rust: "nightly" + continue-on-error: ${{ matrix.rust != 'stable' }} + runs-on: ${{ matrix.os }} + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ matrix.rust }} + - uses: Swatinem/rust-cache@v2 + - name: Default features + run: cargo test --workspace + - name: All features + run: cargo test --workspace --all-features + - name: No-default features + run: cargo test --workspace --no-default-features + rustfmt: + name: rustfmt + strategy: + matrix: + rust: + - stable + - beta + continue-on-error: ${{ matrix.rust != 'stable' }} + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ matrix.rust }} + components: rustfmt + - uses: Swatinem/rust-cache@v2 + - name: Check formatting + run: cargo fmt --all -- --check + clippy: + name: clippy + runs-on: ubuntu-latest + permissions: + security-events: write # to upload sarif results + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + components: clippy + - uses: Swatinem/rust-cache@v2 + - name: Install SARIF tools + run: cargo install clippy-sarif sarif-fmt + - name: Check + run: > + cargo clippy --workspace --all-features --all-targets --message-format=json -- -D warnings --allow deprecated + | clippy-sarif + | tee clippy-results.sarif + | sarif-fmt + continue-on-error: true + - name: Upload + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: clippy-results.sarif + wait-for-processing: true diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml new file mode 100644 index 0000000..f31c7ed --- /dev/null +++ b/.github/workflows/spelling.yml @@ -0,0 +1,21 @@ +name: Spelling + +permissions: + contents: read + +on: [pull_request] + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + +jobs: + spelling: + name: Spell Check with Typos + runs-on: ubuntu-latest + steps: + - name: Checkout Actions Repository + uses: actions/checkout@v3 + - name: Spell Check Repo + uses: crate-ci/typos@master diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..f751dec --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,26 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: check-yaml + stages: [commit] + - id: check-json + stages: [commit] + - id: check-toml + stages: [commit] + - id: check-merge-conflict + stages: [commit] + - id: check-case-conflict + stages: [commit] + - id: detect-private-key + stages: [commit] + - repo: https://github.com/crate-ci/typos + rev: v1.11.1 + hooks: + - id: typos + stages: [commit] + - repo: https://github.com/crate-ci/committed + rev: v1.0.4 + hooks: + - id: committed + stages: [commit-msg] diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..23a247b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# Change Log +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + + +## [Unreleased] - ReleaseDate + + +[Unreleased]: https://github.com/rust-cli/argfile/compare/v0.1.5...HEAD diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ce840a9 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,70 @@ +# Contributing to PROJECT + +Thanks for wanting to contribute! There are many ways to contribute and we +appreciate any level you're willing to do. + +## Feature Requests + +Need some new functionality to help? You can let us know by opening an +[issue][new issue]. It's helpful to look through [all issues][all issues] in +case its already being talked about. + +## Bug Reports + +Please let us know about what problems you run into, whether in behavior or +ergonomics of API. You can do this by opening an [issue][new issue]. It's +helpful to look through [all issues][all issues] in case its already being +talked about. + +## Pull Requests + +Looking for an idea? Check our [issues][issues]. If it's look more open ended, +it is probably best to post on the issue how you are thinking of resolving the +issue so you can get feedback early in the process. We want you to be +successful and it can be discouraging to find out a lot of re-work is needed. + +Already have an idea? It might be good to first [create an issue][new issue] +to propose it so we can make sure we are aligned and lower the risk of having +to re-work some of it and the discouragement that goes along with that. + +### Process + +Before posting a PR, we request that the commit history get cleaned up. +However, we recommend avoiding this during the review to make it easier to +check how feedback was handled. Once the PR is ready, we'll ask you to clean up +the commit history from the review. Once you let us know this is done, we can +move forward with merging! If you are uncomfortable with these parts of git, +let us know and we can help. + +For commit messages, we use [Conventional](https://www.conventionalcommits.org) +style. If you already wrote your commits and don't feel comfortable changing +them, don't worry and go ahead and create your PR. We'll work with you on the +best route forward. You can check your branch locally with +[`committed`](https://github.com/crate-ci/committed). + +As a heads up, we'll be running your PR through the following gauntlet: +- warnings turned to compile errors +- `cargo test` +- `rustfmt` +- `clippy` +- `rustdoc` +- [`committed`](https://github.com/crate-ci/committed) +- [`typos`](https://github.com/crate-ci/typos) + +## Releasing + +Pre-requisites +- Running `cargo login` +- A member of `ORG:Maintainers` +- Push permission to the repo +- [`cargo-release`](https://github.com/crate-ci/cargo-release/) + +When we're ready to release, a project owner should do the following +1. Update the changelog (see `cargo release changes` for ideas) +2. Determine what the next version is, according to semver +3. Run [`cargo release -x `](https://github.com/crate-ci/cargo-release) + +[issues]: https://github.com/ORG/PROJECT/issues +[new issue]: https://github.com/ORG/PROJECT/issues/new +[all issues]: https://github.com/ORG/PROJECT/issues?utf8=%E2%9C%93&q=is%3Aissue +[travis]: https://github.com/ORG/PROJECT/blob/master/.travis.yml diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..49c1f2d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "PROJECT" +version = "0.0.1" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..55dc855 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "PROJECT" +version = "0.0.1" +description = "DESCRIPTION" +license = "MIT OR Apache-2.0" +categories = [] +keywords = [] +edition = "2021" +rust-version = "1.64.0" # MSRV +include = [ + "build.rs", + "src/**/*", + "Cargo.toml", + "LICENSE*", + "README.md", + "benches/**/*", + "examples/**/*" +] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[package.metadata.release] +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="\\.\\.\\.HEAD", replace="...{{tag_name}}", exactly=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## [Unreleased] - ReleaseDate\n", exactly=1}, + {file="CHANGELOG.md", search="", replace="\n[Unreleased]: https://github.com/ORG/PROJECT/compare/{{tag_name}}...HEAD", exactly=1}, +] + +[features] +default = [] + +[dependencies] + +[dev-dependencies] diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..8f71f43 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,202 @@ + 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/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..a2d0108 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,19 @@ +Copyright (c) Individual contributors + +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/README.md b/README.md new file mode 100644 index 0000000..41d5a97 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# PROJECT + +> DESCRIPTION + +[![Documentation](https://img.shields.io/badge/docs-master-blue.svg)][Documentation] +![License](https://img.shields.io/crates/l/PROJECT.svg) +[![Crates Status](https://img.shields.io/crates/v/PROJECT.svg)](https://crates.io/crates/PROJECT) + +## License + +Licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally +submitted for inclusion in the work by you, as defined in the Apache-2.0 +license, shall be dual licensed as above, without any additional terms or +conditions. + +[Crates.io]: https://crates.io/crates/PROJECT +[Documentation]: https://docs.rs/PROJECT diff --git a/committed.toml b/committed.toml new file mode 100644 index 0000000..4211ae3 --- /dev/null +++ b/committed.toml @@ -0,0 +1,3 @@ +style="conventional" +ignore_author_re="(dependabot|renovate)" +merge_commit = false diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..ad23fbb --- /dev/null +++ b/deny.toml @@ -0,0 +1,135 @@ +# Note that all fields that take a lint level have these possible values: +# * deny - An error will be produced and the check will fail +# * warn - A warning will be produced, but the check will not fail +# * allow - No warning or error will be produced, though in some cases a note +# will be + +# This section is considered when running `cargo deny check advisories` +# More documentation for the advisories section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html +[advisories] +# The lint level for security vulnerabilities +vulnerability = "deny" +# The lint level for unmaintained crates +unmaintained = "warn" +# The lint level for crates that have been yanked from their source registry +yanked = "warn" +# The lint level for crates with security notices. Note that as of +# 2019-12-17 there are no security notice advisories in +# https://github.com/rustsec/advisory-db +notice = "warn" +# A list of advisory IDs to ignore. Note that ignored advisories will still +# output a note when they are encountered. +# +# e.g. "RUSTSEC-0000-0000", +ignore = [ +] + +# This section is considered when running `cargo deny check licenses` +# More documentation for the licenses section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html +[licenses] +unlicensed = "deny" +# List of explicitly allowed licenses +# See https://spdx.org/licenses/ for list of possible licenses +# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. +allow = [ + "MIT", + "Apache-2.0", + #"Apache-2.0 WITH LLVM-exception", +] +# List of explicitly disallowed licenses +# See https://spdx.org/licenses/ for list of possible licenses +# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. +deny = [ +] +# Lint level for licenses considered copyleft +copyleft = "deny" +# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses +# * both - The license will be approved if it is both OSI-approved *AND* FSF +# * either - The license will be approved if it is either OSI-approved *OR* FSF +# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF +# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved +# * neither - This predicate is ignored and the default lint level is used +allow-osi-fsf-free = "neither" +# Lint level used when no other predicates are matched +# 1. License isn't in the allow or deny lists +# 2. License isn't copyleft +# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither" +default = "deny" +# The confidence threshold for detecting a license from license text. +# The higher the value, the more closely the license text must be to the +# canonical license text of a valid SPDX license file. +# [possible values: any between 0.0 and 1.0]. +confidence-threshold = 0.8 +# Allow 1 or more licenses on a per-crate basis, so that particular licenses +# aren't accepted for every possible crate as with the normal allow list +exceptions = [ + # Each entry is the crate and version constraint, and its specific allow + # list + #{ allow = ["Zlib"], name = "adler32", version = "*" }, +] + +[licenses.private] +# If true, ignores workspace crates that aren't published, or are only +# published to private registries. +# To see how to mark a crate as unpublished (to the official registry), +# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field. +ignore = true + +# This section is considered when running `cargo deny check bans`. +# More documentation about the 'bans' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html +[bans] +# Lint level for when multiple versions of the same crate are detected +multiple-versions = "warn" +# Lint level for when a crate version requirement is `*` +wildcards = "deny" +# The graph highlighting used when creating dotgraphs for crates +# with multiple versions +# * lowest-version - The path to the lowest versioned duplicate is highlighted +# * simplest-path - The path to the version with the fewest edges is highlighted +# * all - Both lowest-version and simplest-path are used +highlight = "all" +# The default lint level for `default` features for crates that are members of +# the workspace that is being checked. This can be overridden by allowing/denying +# `default` on a crate-by-crate basis if desired. +workspace-default-features = "allow" +# The default lint level for `default` features for external crates that are not +# members of the workspace. This can be overridden by allowing/denying `default` +# on a crate-by-crate basis if desired. +external-default-features = "allow" +# List of crates that are allowed. Use with care! +allow = [ + #{ name = "ansi_term", version = "=0.11.0" }, +] +# List of crates to deny +deny = [ + # Each entry the name of a crate and a version range. If version is + # not specified, all versions will be matched. + #{ name = "ansi_term", version = "=0.11.0" }, + # + # Wrapper crates can optionally be specified to allow the crate when it + # is a direct dependency of the otherwise banned crate + #{ name = "ansi_term", version = "=0.11.0", wrappers = [] }, +] + +# This section is considered when running `cargo deny check sources`. +# More documentation about the 'sources' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html +[sources] +# Lint level for what to happen when a crate from a crate registry that is not +# in the allow list is encountered +unknown-registry = "deny" +# Lint level for what to happen when a crate from a git repository that is not +# in the allow list is encountered +unknown-git = "deny" +# List of URLs for allowed crate registries. Defaults to the crates.io index +# if not specified. If it is specified but empty, no registries are allowed. +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +# List of URLs for allowed Git repositories +allow-git = [] + +[sources.allow-org] +# 1 or more github.com organizations to allow git sources for +github = [] diff --git a/release.toml b/release.toml new file mode 100644 index 0000000..16df989 --- /dev/null +++ b/release.toml @@ -0,0 +1,6 @@ +pre-release-commit-message = "chore: Release" +tag-message = "{{tag_name}}" +tag-name = "{{prefix}}v{{version}}" +consolidate-commits = true +consolidate-pushes = true +allow-branch = ["main"] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..45bf577 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,2 @@ +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![allow(non_snake_case)] // TODO: Delete me From d6b4446cd761d82313a0e69cf0da82ebfc4084cb Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 29 Mar 2023 14:33:42 -0500 Subject: [PATCH 002/175] docs: Set changelog base --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23a247b..e378dd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,4 +8,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - ReleaseDate -[Unreleased]: https://github.com/rust-cli/argfile/compare/v0.1.5...HEAD +[Unreleased]: https://github.com/rust-cli/argfile/compare/e7b7555...HEAD From fbaab420b9e4e01e60522f87e89e2e0a28250c73 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 1 Apr 2023 00:32:08 +0000 Subject: [PATCH 003/175] chore(deps): update msrv to v1.65.0 --- .clippy.toml | 2 +- .github/workflows/ci.yml | 6 +++--- Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.clippy.toml b/.clippy.toml index 16749ab..5c6f984 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1,4 +1,4 @@ -msrv = "1.64.0" # MSRV +msrv = "1.65.0" # MSRV warn-on-all-wildcard-imports = true allow-expect-in-tests = true allow-unwrap-in-tests = true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 783247c..017d45e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,7 +49,7 @@ jobs: - name: No-default features run: cargo test --workspace --no-default-features msrv: - name: "Check MSRV: 1.64.0" + name: "Check MSRV: 1.65.0" runs-on: ubuntu-latest steps: - name: Checkout repository @@ -57,7 +57,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: 1.64.0 # MSRV + toolchain: 1.65.0 # MSRV - uses: Swatinem/rust-cache@v2 - name: Default features run: cargo check --workspace --all-targets @@ -107,7 +107,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: 1.64.0 # MSRV + toolchain: 1.65.0 # MSRV components: clippy - uses: Swatinem/rust-cache@v2 - name: Install SARIF tools diff --git a/Cargo.toml b/Cargo.toml index 55dc855..1c84a5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" categories = [] keywords = [] edition = "2021" -rust-version = "1.64.0" # MSRV +rust-version = "1.65.0" # MSRV include = [ "build.rs", "src/**/*", From 614b0a2376b9ae6d95a1b768b93d06057f4b82d6 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 29 Mar 2023 14:40:57 -0500 Subject: [PATCH 004/175] docs(contrib): Remove reference to travis --- CONTRIBUTING.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ce840a9..e9d7079 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -67,4 +67,3 @@ When we're ready to release, a project owner should do the following [issues]: https://github.com/ORG/PROJECT/issues [new issue]: https://github.com/ORG/PROJECT/issues/new [all issues]: https://github.com/ORG/PROJECT/issues?utf8=%E2%9C%93&q=is%3Aissue -[travis]: https://github.com/ORG/PROJECT/blob/master/.travis.yml From afeff23549a05cd0e5997f129e5d7a564ec41866 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 29 Mar 2023 14:41:29 -0500 Subject: [PATCH 005/175] chore(ci): Quote strings in yaml --- .github/settings.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/settings.yml b/.github/settings.yml index 0469378..8ead1ba 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -25,19 +25,19 @@ labels: # Type - name: bug color: '#b60205' - description: Not as expected + description: "Not as expected" - name: enhancement color: '#1d76db' - description: Improve the expected + description: "Improve the expected" # Flavor - name: question color: "#cc317c" - description: Uncertainty is involved + description: "Uncertainty is involved" - name: breaking-change color: "#e99695" - name: good first issue color: '#c2e0c6' - description: Help wanted! + description: "Help wanted!" branches: - name: main From 2768727452315929d88dda7d0686440d8e668736 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 29 Mar 2023 14:46:23 -0500 Subject: [PATCH 006/175] chore: Don't set rustflags by default Doing so can cause unnecessary recompilation --- .cargo/config | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .cargo/config diff --git a/.cargo/config b/.cargo/config deleted file mode 100644 index ba32123..0000000 --- a/.cargo/config +++ /dev/null @@ -1,5 +0,0 @@ -[target.x86_64-pc-windows-msvc] -rustflags = ["-Ctarget-feature=+crt-static"] - -[target.i686-pc-windows-msvc] -rustflags = ["-Ctarget-feature=+crt-static"] From 083884043cc08394c6f91df81e6407721b2dc19e Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 29 Mar 2023 14:51:13 -0500 Subject: [PATCH 007/175] chore: Update release process --- release.toml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/release.toml b/release.toml index 16df989..160b061 100644 --- a/release.toml +++ b/release.toml @@ -1,6 +1,2 @@ -pre-release-commit-message = "chore: Release" -tag-message = "{{tag_name}}" -tag-name = "{{prefix}}v{{version}}" -consolidate-commits = true -consolidate-pushes = true +dependent-version = "fix" allow-branch = ["main"] From afd6a45ef73201bf5d5f3d4f0317f432b17c60d0 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 29 Mar 2023 14:53:08 -0500 Subject: [PATCH 008/175] chore: Use workspace inheritance --- Cargo.toml | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1c84a5e..6e698fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,8 @@ -[package] -name = "PROJECT" -version = "0.0.1" -description = "DESCRIPTION" +[workspace] +resolver = "2" + +[workspace.package] license = "MIT OR Apache-2.0" -categories = [] -keywords = [] edition = "2021" rust-version = "1.65.0" # MSRV include = [ @@ -17,6 +15,17 @@ include = [ "examples/**/*" ] +[package] +name = "PROJECT" +version = "0.0.1" +description = "DESCRIPTION" +categories = [] +keywords = [] +license.workspace = true +edition.workspace = true +rust-version.workspace = true +include.workspace = true + [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] From 037f37906dad6d39f9fad371bc9a8ab76e8bd5c4 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 29 Mar 2023 15:07:09 -0500 Subject: [PATCH 009/175] chore(ci): Remove rustfmt/clippy next jobs --- .github/workflows/rust-next.yml | 48 --------------------------------- 1 file changed, 48 deletions(-) diff --git a/.github/workflows/rust-next.yml b/.github/workflows/rust-next.yml index 8faba30..e90121b 100644 --- a/.github/workflows/rust-next.yml +++ b/.github/workflows/rust-next.yml @@ -38,51 +38,3 @@ jobs: run: cargo test --workspace --all-features - name: No-default features run: cargo test --workspace --no-default-features - rustfmt: - name: rustfmt - strategy: - matrix: - rust: - - stable - - beta - continue-on-error: ${{ matrix.rust != 'stable' }} - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - with: - toolchain: ${{ matrix.rust }} - components: rustfmt - - uses: Swatinem/rust-cache@v2 - - name: Check formatting - run: cargo fmt --all -- --check - clippy: - name: clippy - runs-on: ubuntu-latest - permissions: - security-events: write # to upload sarif results - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - with: - toolchain: stable - components: clippy - - uses: Swatinem/rust-cache@v2 - - name: Install SARIF tools - run: cargo install clippy-sarif sarif-fmt - - name: Check - run: > - cargo clippy --workspace --all-features --all-targets --message-format=json -- -D warnings --allow deprecated - | clippy-sarif - | tee clippy-results.sarif - | sarif-fmt - continue-on-error: true - - name: Upload - uses: github/codeql-action/upload-sarif@v2 - with: - sarif_file: clippy-results.sarif - wait-for-processing: true From d1dd4ae94067be2f3158fa46b0e78504705dfb26 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 29 Mar 2023 15:28:54 -0500 Subject: [PATCH 010/175] chore(ci): Expand approved licenses --- deny.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/deny.toml b/deny.toml index ad23fbb..942e08d 100644 --- a/deny.toml +++ b/deny.toml @@ -35,8 +35,12 @@ unlicensed = "deny" # [possible values: any SPDX 3.11 short identifier (+ optional exception)]. allow = [ "MIT", + "MIT-0", "Apache-2.0", - #"Apache-2.0 WITH LLVM-exception", + "BSD-3-Clause", + "MPL-2.0", + "Unicode-DFS-2016", + "CC0-1.0", ] # List of explicitly disallowed licenses # See https://spdx.org/licenses/ for list of possible licenses From 6c8df60dc4015279cef303cab8f4760efb5ebea8 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 29 Mar 2023 22:38:45 -0500 Subject: [PATCH 011/175] chore: Include Cargo.lock --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 6e698fb..b8ecde1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ include = [ "build.rs", "src/**/*", "Cargo.toml", + "Cargo.lock", "LICENSE*", "README.md", "benches/**/*", From f7b990b803a4aa448e81a323df3a54e66d2d8df4 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 17 Apr 2023 08:50:19 -0500 Subject: [PATCH 012/175] fix(ci): Fix Renovate regexes --- .github/renovate.json5 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 51faa75..5e8e7e2 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -11,9 +11,9 @@ "^rust-toolchain\\.toml$", "Cargo.toml$", "clippy.toml$", - "\.clippy.toml$", - "^\.github/workflows/ci.yml$", - "^\.github/workflows/rust-next.yml$", + "\\.clippy.toml$", + "^\\.github/workflows/ci.yml$", + "^\\.github/workflows/rust-next.yml$", ], "matchStrings": [ "MSRV.*?(?\\d+\\.\\d+(\\.\\d+)?)", From 4163ad78c72df3a993bea6084fc05c6a2a44b9c2 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 17 Apr 2023 08:51:48 -0500 Subject: [PATCH 013/175] style(ci): Match auto-generated style This will make reviewing auto-update PRs easier --- .github/renovate.json5 | 126 +++++++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 48 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 5e8e7e2..0393074 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -1,35 +1,39 @@ { - "schedule": [ - "before 3am on the first day of the month" + schedule: [ + 'before 3am on the first day of the month' ], - "semanticCommits": "enabled", - "configMigration": true, - "dependencyDashboard": true, - "regexManagers": [ + semanticCommits: 'enabled', + configMigration: true, + dependencyDashboard: true, + regexManagers: [ { - "fileMatch": [ - "^rust-toolchain\\.toml$", - "Cargo.toml$", - "clippy.toml$", - "\\.clippy.toml$", - "^\\.github/workflows/ci.yml$", - "^\\.github/workflows/rust-next.yml$", - ], - "matchStrings": [ - "MSRV.*?(?\\d+\\.\\d+(\\.\\d+)?)", - "(?\\d+\\.\\d+(\\.\\d+)?).*?MSRV", - ], - "depNameTemplate": "rust", - "packageNameTemplate": "rust-lang/rust", - "datasourceTemplate": "github-releases", + fileMatch: [ + '^rust-toolchain\\.toml$', + 'Cargo.toml$', + 'clippy.toml$', + '\\.clippy.toml$', + '^\\.github/workflows/ci.yml$', + '^\\.github/workflows/rust-next.yml$', + ], + matchStrings: [ + 'MSRV.*?(?\\d+\\.\\d+(\\.\\d+)?)', + '(?\\d+\\.\\d+(\\.\\d+)?).*?MSRV', + ], + depNameTemplate: 'rust', + packageNameTemplate: 'rust-lang/rust', + datasourceTemplate: 'github-releases', } ], - "packageRules": [ + packageRules: [ { - "commitMessageTopic": "MSRV", - "matchManagers": ["regex"], - "matchPackageNames": ["rust"], - "stabilityDays": 126, // 3 releases * 6 weeks per release * 7 days per week + commitMessageTopic: 'MSRV', + matchManagers: [ + 'regex', + ], + matchPackageNames: [ + 'rust', + ], + stabilityDays: 126, // 3 releases * 6 weeks per release * 7 days per week }, // Goals: // - Keep version reqs low, ignoring compatible normal/build dependencies @@ -38,34 +42,60 @@ // - Help keep number of versions down by always using latest breaking change // - Have lockfile and manifest in-sync { - "matchManagers": ["cargo"], - "matchDepTypes": ["build-dependencies", "dependencies"], - "matchCurrentVersion": ">=0.1.0", - "matchUpdateTypes": ["patch"], - "enabled": false, + matchManagers: [ + 'cargo', + ], + matchDepTypes: [ + 'build-dependencies', + 'dependencies', + ], + matchCurrentVersion: '>=0.1.0', + matchUpdateTypes: [ + 'patch', + ], + enabled: false, }, { - "matchManagers": ["cargo"], - "matchDepTypes": ["build-dependencies", "dependencies"], - "matchCurrentVersion": ">=1.0.0", - "matchUpdateTypes": ["minor"], - "enabled": false, + matchManagers: [ + 'cargo', + ], + matchDepTypes: [ + 'build-dependencies', + 'dependencies', + ], + matchCurrentVersion: '>=1.0.0', + matchUpdateTypes: [ + 'minor', + ], + enabled: false, }, { - "matchManagers": ["cargo"], - "matchDepTypes": ["dev-dependencies"], - "matchCurrentVersion": ">=0.1.0", - "matchUpdateTypes": ["patch"], - "automerge": true, - "groupName": "compatible (dev)", + matchManagers: [ + 'cargo', + ], + matchDepTypes: [ + 'dev-dependencies', + ], + matchCurrentVersion: '>=0.1.0', + matchUpdateTypes: [ + 'patch', + ], + automerge: true, + groupName: 'compatible (dev)', }, { - "matchManagers": ["cargo"], - "matchDepTypes": ["dev-dependencies"], - "matchCurrentVersion": ">=1.0.0", - "matchUpdateTypes": ["minor"], - "automerge": true, - "groupName": "compatible (dev)", + matchManagers: [ + 'cargo', + ], + matchDepTypes: [ + 'dev-dependencies', + ], + matchCurrentVersion: '>=1.0.0', + matchUpdateTypes: [ + 'minor', + ], + automerge: true, + groupName: 'compatible (dev)', }, ], } From 563de12d25e777e7244a73308090adcfb8b90014 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 17 Apr 2023 09:01:54 -0500 Subject: [PATCH 014/175] chore(ci): Update stabilidyDays to new syntax --- .github/renovate.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 0393074..d5485d2 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -33,7 +33,7 @@ matchPackageNames: [ 'rust', ], - stabilityDays: 126, // 3 releases * 6 weeks per release * 7 days per week + stabilityDays: "126 days", // 3 releases * 6 weeks per release * 7 days per week }, // Goals: // - Keep version reqs low, ignoring compatible normal/build dependencies From 2c4a7f574f6fed6655e8b2f25916c22d7bf08ad1 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 17 Apr 2023 09:02:40 -0500 Subject: [PATCH 015/175] chore(ci): Delay Renovate PRs until ready --- .github/renovate.json5 | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index d5485d2..0e8f1d6 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -34,6 +34,7 @@ 'rust', ], stabilityDays: "126 days", // 3 releases * 6 weeks per release * 7 days per week + internalChecksFilter: "strict", }, // Goals: // - Keep version reqs low, ignoring compatible normal/build dependencies From 62401b8eafb71d8a928137f6f8dfc25340e39bbf Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 17 Apr 2023 09:05:31 -0500 Subject: [PATCH 016/175] chore(ci): Lower the MSRV churn for template --- .github/renovate.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 0e8f1d6..900feaf 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -33,7 +33,7 @@ matchPackageNames: [ 'rust', ], - stabilityDays: "126 days", // 3 releases * 6 weeks per release * 7 days per week + stabilityDays: "336 days", // 8 releases * 6 weeks per release * 7 days per week internalChecksFilter: "strict", }, // Goals: From d99db2e632b25a8b020491c3e1d40bf2efd3472a Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 17 Apr 2023 09:54:05 -0500 Subject: [PATCH 017/175] style(ci): Match auto-generated style --- .github/renovate.json5 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 900feaf..54bc593 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -1,6 +1,6 @@ { schedule: [ - 'before 3am on the first day of the month' + 'before 3am on the first day of the month', ], semanticCommits: 'enabled', configMigration: true, @@ -22,7 +22,7 @@ depNameTemplate: 'rust', packageNameTemplate: 'rust-lang/rust', datasourceTemplate: 'github-releases', - } + }, ], packageRules: [ { From afaba35d39c75d13138e2928cddeb0b93601cee3 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 17 Apr 2023 09:54:21 -0500 Subject: [PATCH 018/175] chore(ci): Use new minimumReleaseAge field --- .github/renovate.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 54bc593..79e5152 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -33,7 +33,7 @@ matchPackageNames: [ 'rust', ], - stabilityDays: "336 days", // 8 releases * 6 weeks per release * 7 days per week + minimumReleaseAge: "336 days", // 8 releases * 6 weeks per release * 7 days per week internalChecksFilter: "strict", }, // Goals: From 60a8ec89e3f97baad0dbe097e03dc0cd30899e02 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 17 Apr 2023 20:03:56 -0500 Subject: [PATCH 019/175] chore(ci): Ban for_each --- .clippy.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.clippy.toml b/.clippy.toml index 5c6f984..56d269a 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -9,4 +9,6 @@ disallowed-methods = [ { path = "std::option::Option::map_or_else", reason = "use `map(..).unwrap_or_else(..)`" }, { path = "std::result::Result::map_or", reason = "use `map(..).unwrap_or(..)`" }, { path = "std::result::Result::map_or_else", reason = "use `map(..).unwrap_or_else(..)`" }, + { path = "std::iter::Iterator::for_each", reason = "prefer `for` for side-effects" }, + { path = "std::iter::Iterator::try_for_each", reason = "prefer `for` for side-effects" }, ] From 96297f038d8d931bb9d5ba4dfcdced18d7c81061 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 17 Apr 2023 20:04:56 -0500 Subject: [PATCH 020/175] chore(ci): Clarify why map_or is banned --- .clippy.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.clippy.toml b/.clippy.toml index 56d269a..22fe10b 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -5,10 +5,10 @@ allow-unwrap-in-tests = true allow-dbg-in-tests = true allow-print-in-tests = true disallowed-methods = [ - { path = "std::option::Option::map_or", reason = "use `map(..).unwrap_or(..)`" }, - { path = "std::option::Option::map_or_else", reason = "use `map(..).unwrap_or_else(..)`" }, - { path = "std::result::Result::map_or", reason = "use `map(..).unwrap_or(..)`" }, - { path = "std::result::Result::map_or_else", reason = "use `map(..).unwrap_or_else(..)`" }, + { path = "std::option::Option::map_or", reason = "prefer `map(..).unwrap_or(..)` for legibility" }, + { path = "std::option::Option::map_or_else", reason = "prefer `map(..).unwrap_or_else(..)` for legibility" }, + { path = "std::result::Result::map_or", reason = "prefer `map(..).unwrap_or(..)` for legibility" }, + { path = "std::result::Result::map_or_else", reason = "prefer `map(..).unwrap_or_else(..)` for legibility" }, { path = "std::iter::Iterator::for_each", reason = "prefer `for` for side-effects" }, { path = "std::iter::Iterator::try_for_each", reason = "prefer `for` for side-effects" }, ] From 716170eaa853ddf3032baa9b107eb3e44d6a4124 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 17 Apr 2023 20:13:36 -0500 Subject: [PATCH 021/175] chore(gh): Ban rebase merges --- .github/settings.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/settings.yml b/.github/settings.yml index 8ead1ba..7d5e4fc 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -10,9 +10,12 @@ repository: has_downloads: true default_branch: main - allow_squash_merge: true + # Preference: people do clean commits allow_merge_commit: true - allow_rebase_merge: true + # Backup in case we need to clean up commits + allow_squash_merge: true + # Not really needed + allow_rebase_merge: false allow_auto_merge: true delete_branch_on_merge: true From 80d4cdd688e88b897f384b770f9c13268ecb3793 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 18 May 2023 14:57:02 -0500 Subject: [PATCH 022/175] chore: Remove clippy lint past MSRV (needs 1.67) --- .clippy.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/.clippy.toml b/.clippy.toml index 22fe10b..090e2be 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -3,7 +3,6 @@ warn-on-all-wildcard-imports = true allow-expect-in-tests = true allow-unwrap-in-tests = true allow-dbg-in-tests = true -allow-print-in-tests = true disallowed-methods = [ { path = "std::option::Option::map_or", reason = "prefer `map(..).unwrap_or(..)` for legibility" }, { path = "std::option::Option::map_or_else", reason = "prefer `map(..).unwrap_or_else(..)` for legibility" }, From 2b6bb28cd18916a6244a2632a6abcba9362b9fd0 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 18 May 2023 14:58:59 -0500 Subject: [PATCH 023/175] chore(ci): Catch clippy config failures --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 017d45e..a7bb325 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -126,3 +126,5 @@ jobs: with: sarif_file: clippy-results.sarif wait-for-processing: true + - name: Report status + run: cargo clippy --workspace --all-features --all-targets -- -D warnings --allow deprecated From 4d44cd7ca51f05fb06185677642d73c0ff0da079 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 19 May 2023 13:12:26 -0500 Subject: [PATCH 024/175] chore: Update precommit hooks --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f751dec..fd77abb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 + rev: v4.4.0 hooks: - id: check-yaml stages: [commit] @@ -15,12 +15,12 @@ repos: - id: detect-private-key stages: [commit] - repo: https://github.com/crate-ci/typos - rev: v1.11.1 + rev: v1.14.10 hooks: - id: typos stages: [commit] - repo: https://github.com/crate-ci/committed - rev: v1.0.4 + rev: v1.0.17 hooks: - id: committed stages: [commit-msg] From d6075a44bff9073c811510e86d73216baa844a69 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 2 Aug 2023 11:11:52 -0500 Subject: [PATCH 025/175] chore: Expand update window so more likely to be hit --- .github/renovate.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 79e5152..e5733ed 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -1,6 +1,6 @@ { schedule: [ - 'before 3am on the first day of the month', + 'before 5am on the first day of the month', ], semanticCommits: 'enabled', configMigration: true, From 67eb1d9e3d396cc7f786d767e287d7e946ed3118 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 7 Aug 2023 16:16:17 -0500 Subject: [PATCH 026/175] chore(ci): Ensure lockfile isn't stale --- .github/workflows/ci.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7bb325..26c9b0f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,6 +65,18 @@ jobs: run: cargo check --workspace --all-targets --all-features - name: No-default features run: cargo check --workspace --all-targets --no-default-features + lockfile: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + - uses: Swatinem/rust-cache@v2 + - name: "Is lockfile updated?" + run: cargo fetch --locked docs: name: Docs runs-on: ubuntu-latest From ba76b8bd911b98ab78fec3cf6c8e7ee679721a6f Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 11 Aug 2023 13:29:06 -0500 Subject: [PATCH 027/175] chore(ci): Ensure latest deps are good --- .github/workflows/rust-next.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/rust-next.yml b/.github/workflows/rust-next.yml index e90121b..a540ba5 100644 --- a/.github/workflows/rust-next.yml +++ b/.github/workflows/rust-next.yml @@ -38,3 +38,22 @@ jobs: run: cargo test --workspace --all-features - name: No-default features run: cargo test --workspace --no-default-features + latest: + name: "Check latest dependencies" + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + - uses: Swatinem/rust-cache@v2 + - name: Update dependencues + run: cargo update + - name: Default features + run: cargo test --workspace --all-targets + - name: All features + run: cargo test --workspace --all-targets --all-features + - name: No-default features + run: cargo test --workspace --all-targets --no-default-features From 528638729492300730aebee283d2a837325b4a62 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 11 Aug 2023 16:04:07 -0500 Subject: [PATCH 028/175] chore: Update pre-commit hooks --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fd77abb..3d9e40f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,12 +15,12 @@ repos: - id: detect-private-key stages: [commit] - repo: https://github.com/crate-ci/typos - rev: v1.14.10 + rev: v1.16.3 hooks: - id: typos stages: [commit] - repo: https://github.com/crate-ci/committed - rev: v1.0.17 + rev: v1.0.20 hooks: - id: committed stages: [commit-msg] From efe14d60899ec75c901c88b46174ccd3fc5e14d8 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 22 Aug 2023 11:06:55 -0500 Subject: [PATCH 029/175] chore(renovate): Make style consistent --- .github/renovate.json5 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index e5733ed..8e31ad0 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -33,8 +33,8 @@ matchPackageNames: [ 'rust', ], - minimumReleaseAge: "336 days", // 8 releases * 6 weeks per release * 7 days per week - internalChecksFilter: "strict", + minimumReleaseAge: '336 days', // 8 releases * 6 weeks per release * 7 days per week + internalChecksFilter: 'strict', }, // Goals: // - Keep version reqs low, ignoring compatible normal/build dependencies From a6ecf92327e4c75e6545cdd238cc40171337c403 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 22 Aug 2023 11:07:34 -0500 Subject: [PATCH 030/175] chore(renovate): Update config --- .github/renovate.json5 | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 8e31ad0..7b75c58 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -7,6 +7,7 @@ dependencyDashboard: true, regexManagers: [ { + customType: 'regex', fileMatch: [ '^rust-toolchain\\.toml$', 'Cargo.toml$', From c8624f0538c30bb5498db489f456af6012988bdb Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 23 Aug 2023 09:24:15 -0500 Subject: [PATCH 031/175] chore(renovate): Update MSRV on release --- .github/renovate.json5 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 7b75c58..a367a47 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -36,6 +36,9 @@ ], minimumReleaseAge: '336 days', // 8 releases * 6 weeks per release * 7 days per week internalChecksFilter: 'strict', + schedule: [ + 'every day', + ], }, // Goals: // - Keep version reqs low, ignoring compatible normal/build dependencies From 44604fc1d369e255c7edd0954979310131e24fa4 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 23 Aug 2023 09:35:47 -0500 Subject: [PATCH 032/175] chore(renovate): Try to fix schedule --- .github/renovate.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index a367a47..28e23ee 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -37,7 +37,7 @@ minimumReleaseAge: '336 days', // 8 releases * 6 weeks per release * 7 days per week internalChecksFilter: 'strict', schedule: [ - 'every day', + '* * * * *', ], }, // Goals: From ff82d6960a9903e3c62414cdacc9b2fa0a7ce2cb Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 23 Aug 2023 10:43:57 -0500 Subject: [PATCH 033/175] chore(ci): Don't fail on wildcards See EmbarkStudios/cargo-deny#241 --- deny.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deny.toml b/deny.toml index 942e08d..58cc98d 100644 --- a/deny.toml +++ b/deny.toml @@ -88,7 +88,7 @@ ignore = true # Lint level for when multiple versions of the same crate are detected multiple-versions = "warn" # Lint level for when a crate version requirement is `*` -wildcards = "deny" +wildcards = "warn" # The graph highlighting used when creating dotgraphs for crates # with multiple versions # * lowest-version - The path to the lowest versioned duplicate is highlighted From 5749aa0932d42cd0ee484b6cb9fcf6f6dd026749 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 7 Sep 2023 09:33:44 -0500 Subject: [PATCH 034/175] chore: Approve ISC --- deny.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/deny.toml b/deny.toml index 58cc98d..21fa937 100644 --- a/deny.toml +++ b/deny.toml @@ -41,6 +41,7 @@ allow = [ "MPL-2.0", "Unicode-DFS-2016", "CC0-1.0", + "ISC", ] # List of explicitly disallowed licenses # See https://spdx.org/licenses/ for list of possible licenses From 4173c8f4767296f76a6eb96d70b7ca6c13bb38bd Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 20 Sep 2023 09:05:41 -0500 Subject: [PATCH 035/175] chore(ci): Don't set patch for MSRV --- .github/renovate.json5 | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 28e23ee..56cf1e3 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -36,6 +36,7 @@ ], minimumReleaseAge: '336 days', // 8 releases * 6 weeks per release * 7 days per week internalChecksFilter: 'strict', + "extractVersion": "^(?\\d+\\.\\d+)", // Drop the patch version schedule: [ '* * * * *', ], From 86c29dea384c7392a2b682fa0150f52c0f4c7f00 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 26 Sep 2023 08:16:33 -0500 Subject: [PATCH 036/175] chore(ci): Updaet Renovate schema --- .github/renovate.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 56cf1e3..4eaf67f 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -5,7 +5,7 @@ semanticCommits: 'enabled', configMigration: true, dependencyDashboard: true, - regexManagers: [ + customManagers: [ { customType: 'regex', fileMatch: [ From ac51f0925003597dec21529538597dbd7872d1ac Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 26 Sep 2023 08:16:47 -0500 Subject: [PATCH 037/175] chore(ci): Normalize json5 syntax --- .github/renovate.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 4eaf67f..72d0579 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -36,7 +36,7 @@ ], minimumReleaseAge: '336 days', // 8 releases * 6 weeks per release * 7 days per week internalChecksFilter: 'strict', - "extractVersion": "^(?\\d+\\.\\d+)", // Drop the patch version + extractVersion: '^(?\\d+\\.\\d+)', // Drop the patch version schedule: [ '* * * * *', ], From 305798083f34bb57951fb6351aa6b897790907eb Mon Sep 17 00:00:00 2001 From: Peter Kehl Date: Fri, 29 Sep 2023 22:59:44 -0700 Subject: [PATCH 038/175] README.md 'Crates Status' icon link now uses the Markdown placeholder/substitution name 'Crates.io' --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 41d5a97..6958ee0 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Documentation](https://img.shields.io/badge/docs-master-blue.svg)][Documentation] ![License](https://img.shields.io/crates/l/PROJECT.svg) -[![Crates Status](https://img.shields.io/crates/v/PROJECT.svg)](https://crates.io/crates/PROJECT) +[![Crates Status](https://img.shields.io/crates/v/PROJECT.svg)][Crates.io] ## License From cad9b4717162cc4dbd4253227fc9c5705a302758 Mon Sep 17 00:00:00 2001 From: Peter Kehl Date: Fri, 29 Sep 2023 23:04:45 -0700 Subject: [PATCH 039/175] README.md list indentation and no bare URLs, as per Markdown Lint VS Code extension. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 41d5a97..6f30768 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ Licensed under either of - * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) +* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or ) +* MIT license ([LICENSE-MIT](LICENSE-MIT) or ) at your option. From 6d3f888975aedf79e10336c8090d6aab20751b10 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 01:37:07 +0000 Subject: [PATCH 040/175] chore(deps): update actions/checkout action to v4 --- .github/workflows/audit.yml | 4 ++-- .github/workflows/ci.yml | 12 ++++++------ .github/workflows/committed.yml | 2 +- .github/workflows/pre-commit.yml | 2 +- .github/workflows/rust-next.yml | 4 ++-- .github/workflows/spelling.yml | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 5b7e83a..ccee1fe 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -27,7 +27,7 @@ jobs: continue-on-error: true steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions-rs/audit-check@v1 with: token: ${{ secrets.GITHUB_TOKEN }} @@ -42,7 +42,7 @@ jobs: checks: - bans licenses sources steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: EmbarkStudios/cargo-deny-action@v1 with: command: check ${{ matrix.checks }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 26c9b0f..1a70372 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: @@ -53,7 +53,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: @@ -69,7 +69,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: @@ -82,7 +82,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: @@ -97,7 +97,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: @@ -115,7 +115,7 @@ jobs: security-events: write # to upload sarif results steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: diff --git a/.github/workflows/committed.yml b/.github/workflows/committed.yml index 509be08..0462558 100644 --- a/.github/workflows/committed.yml +++ b/.github/workflows/committed.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Actions Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Lint Commits diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index d4b0f84..8044750 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -18,6 +18,6 @@ jobs: contents: read runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 - uses: pre-commit/action@v3.0.0 diff --git a/.github/workflows/rust-next.yml b/.github/workflows/rust-next.yml index a540ba5..d8c2d25 100644 --- a/.github/workflows/rust-next.yml +++ b/.github/workflows/rust-next.yml @@ -26,7 +26,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: @@ -43,7 +43,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml index f31c7ed..12f7585 100644 --- a/.github/workflows/spelling.yml +++ b/.github/workflows/spelling.yml @@ -16,6 +16,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Actions Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Spell Check Repo uses: crate-ci/typos@master From 5e3b324b5e6488667be2f00a424781030e37a277 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 5 Oct 2023 14:41:40 -0500 Subject: [PATCH 041/175] chore(ci): Ensure MSRV is quoted Switching from specifying patch to not, with a minor version with a trailing zero, is causing YAML to convert `1.70` to `1.7`. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a70372..19efcf9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,7 +57,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: 1.65.0 # MSRV + toolchain: "1.65.0" # MSRV - uses: Swatinem/rust-cache@v2 - name: Default features run: cargo check --workspace --all-targets @@ -119,7 +119,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: 1.65.0 # MSRV + toolchain: "1.65.0" # MSRV components: clippy - uses: Swatinem/rust-cache@v2 - name: Install SARIF tools From 5ebe30b9722ac700d414043ff099bad7f3978582 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 26 Oct 2023 09:14:51 -0500 Subject: [PATCH 042/175] chore(ci): Update pre-commit hooks --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3d9e40f..68db968 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: check-yaml stages: [commit] @@ -15,7 +15,7 @@ repos: - id: detect-private-key stages: [commit] - repo: https://github.com/crate-ci/typos - rev: v1.16.3 + rev: v1.16.20 hooks: - id: typos stages: [commit] From 598c6244983fb392457f3fbec9badf25fab6d051 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 3 Dec 2023 09:19:35 +0000 Subject: [PATCH 043/175] chore(config): migrate config .github/renovate.json5 --- .github/renovate.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 72d0579..3119c42 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -29,7 +29,7 @@ { commitMessageTopic: 'MSRV', matchManagers: [ - 'regex', + 'custom.regex', ], matchPackageNames: [ 'rust', From 69fa0268a44a9859c4db98a6692369c0e8719146 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 00:59:55 +0000 Subject: [PATCH 044/175] chore(deps): update actions/setup-python action to v5 --- .github/workflows/pre-commit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 8044750..9551407 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -19,5 +19,5 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 - uses: pre-commit/action@v3.0.0 From 82c9aa7bddef20e9705d3d404403e59b2cd7e8e1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 00:59:58 +0000 Subject: [PATCH 045/175] chore(deps): update github/codeql-action action to v3 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 19efcf9..1b09d21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -134,7 +134,7 @@ jobs: | sarif-fmt continue-on-error: true - name: Upload - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@v3 with: sarif_file: clippy-results.sarif wait-for-processing: true From a4c062667d3b0c94928d285052795637de0a7227 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 2 Jan 2024 09:56:35 -0600 Subject: [PATCH 046/175] chore: Make renovate commits to match --- .github/renovate.json5 | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 3119c42..e5a5de0 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -3,6 +3,7 @@ 'before 5am on the first day of the month', ], semanticCommits: 'enabled', + commitMessageLowerCase: 'never', configMigration: true, dependencyDashboard: true, customManagers: [ From 61250a36135d0032ceda4316b43d3a62d8b07643 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 3 Jan 2024 08:27:59 -0600 Subject: [PATCH 047/175] chore(ci): Optimize CI runs --- .github/workflows/ci.yml | 2 +- .github/workflows/rust-next.yml | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b09d21..943becf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: toolchain: ${{ matrix.rust }} - uses: Swatinem/rust-cache@v2 - name: Build - run: cargo test --no-run --workspace --all-features + run: cargo test --workspace --no-run - name: Default features run: cargo test --workspace - name: All features diff --git a/.github/workflows/rust-next.yml b/.github/workflows/rust-next.yml index d8c2d25..43b4ec8 100644 --- a/.github/workflows/rust-next.yml +++ b/.github/workflows/rust-next.yml @@ -32,6 +32,8 @@ jobs: with: toolchain: ${{ matrix.rust }} - uses: Swatinem/rust-cache@v2 + - name: Build + run: cargo test --workspace --no-run - name: Default features run: cargo test --workspace - name: All features @@ -51,9 +53,11 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: Update dependencues run: cargo update + - name: Build + run: cargo test --workspace --no-run - name: Default features - run: cargo test --workspace --all-targets + run: cargo test --workspace - name: All features - run: cargo test --workspace --all-targets --all-features + run: cargo test --workspace --all-features - name: No-default features - run: cargo test --workspace --all-targets --no-default-features + run: cargo test --workspace --no-default-features From e819db4af62e231bcedd976faa488b4e6f46f312 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 18 Jan 2024 09:22:25 -0600 Subject: [PATCH 048/175] chore(ci): Cancel prior CI runs --- .github/workflows/audit.yml | 4 ++++ .github/workflows/ci.yml | 4 ++++ .github/workflows/committed.yml | 4 ++++ .github/workflows/pre-commit.yml | 4 ++++ .github/workflows/rust-next.yml | 4 ++++ .github/workflows/spelling.yml | 4 ++++ 6 files changed, 24 insertions(+) diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index ccee1fe..07c70ee 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -17,6 +17,10 @@ env: CARGO_TERM_COLOR: always CLICOLOR: 1 +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + jobs: security_audit: permissions: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 943becf..2bbd5a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,10 @@ env: CARGO_TERM_COLOR: always CLICOLOR: 1 +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + jobs: ci: permissions: diff --git a/.github/workflows/committed.yml b/.github/workflows/committed.yml index 0462558..e7a50fb 100644 --- a/.github/workflows/committed.yml +++ b/.github/workflows/committed.yml @@ -11,6 +11,10 @@ env: CARGO_TERM_COLOR: always CLICOLOR: 1 +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + jobs: committed: name: Lint Commits diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 9551407..7d77328 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -12,6 +12,10 @@ env: CARGO_TERM_COLOR: always CLICOLOR: 1 +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + jobs: pre-commit: permissions: diff --git a/.github/workflows/rust-next.yml b/.github/workflows/rust-next.yml index 43b4ec8..f0febc9 100644 --- a/.github/workflows/rust-next.yml +++ b/.github/workflows/rust-next.yml @@ -12,6 +12,10 @@ env: CARGO_TERM_COLOR: always CLICOLOR: 1 +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + jobs: test: name: Test diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml index 12f7585..8e58d9e 100644 --- a/.github/workflows/spelling.yml +++ b/.github/workflows/spelling.yml @@ -10,6 +10,10 @@ env: CARGO_TERM_COLOR: always CLICOLOR: 1 +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + jobs: spelling: name: Spell Check with Typos From 0b029063fe83d818e3a79819b88bee8b8314f752 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 24 Jan 2024 08:40:56 -0600 Subject: [PATCH 049/175] chore(ci): Be explicit in renovate updates --- .github/renovate.json5 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index e5a5de0..32d3628 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -73,6 +73,7 @@ matchCurrentVersion: '>=1.0.0', matchUpdateTypes: [ 'minor', + 'patch', ], enabled: false, }, @@ -100,6 +101,7 @@ matchCurrentVersion: '>=1.0.0', matchUpdateTypes: [ 'minor', + 'patch', ], automerge: true, groupName: 'compatible (dev)', From 131de55d50284af7a54287d34699347b74d75709 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 31 Jan 2024 12:07:12 -0600 Subject: [PATCH 050/175] chore(ci): Add m1 runners See https://github.blog/changelog/2024-01-30-github-actions-introducing-the-new-m1-macos-runner-available-to-open-source/ --- .github/workflows/ci.yml | 2 +- .github/workflows/rust-next.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2bbd5a5..a8826b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: name: Test strategy: matrix: - os: ["ubuntu-latest", "windows-latest", "macos-latest"] + os: ["ubuntu-latest", "windows-latest", "macos-latest", "macos-14"] rust: ["stable"] continue-on-error: ${{ matrix.rust != 'stable' }} runs-on: ${{ matrix.os }} diff --git a/.github/workflows/rust-next.yml b/.github/workflows/rust-next.yml index f0febc9..49e5d8c 100644 --- a/.github/workflows/rust-next.yml +++ b/.github/workflows/rust-next.yml @@ -21,7 +21,7 @@ jobs: name: Test strategy: matrix: - os: ["ubuntu-latest", "windows-latest", "macos-latest"] + os: ["ubuntu-latest", "windows-latest", "macos-latest", "macos-14"] rust: ["stable", "beta"] include: - os: ubuntu-latest From 9a5af5c8d21d549a7eb785343ae055d931952075 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 8 Feb 2024 07:45:48 -0600 Subject: [PATCH 051/175] chore(ci): Only check intel mac on schedule --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8826b0..af065d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: name: Test strategy: matrix: - os: ["ubuntu-latest", "windows-latest", "macos-latest", "macos-14"] + os: ["ubuntu-latest", "windows-latest", "macos-14"] rust: ["stable"] continue-on-error: ${{ matrix.rust != 'stable' }} runs-on: ${{ matrix.os }} From da56001fd6cabdb744f25b021c9efd230472f671 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 8 Feb 2024 07:48:29 -0600 Subject: [PATCH 052/175] chore(ci): Gather coverage --- .github/workflows/ci.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af065d5..7849a73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -144,3 +144,22 @@ jobs: wait-for-processing: true - name: Report status run: cargo clippy --workspace --all-features --all-targets -- -D warnings --allow deprecated + coverage: + name: Coverage + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: "1.75" # STABLE + - uses: Swatinem/rust-cache@v2 + - name: Install cargo-tarpaulin + run: cargo install cargo-tarpaulin + - name: Gather coverage + run: cargo tarpaulin --output-dir coverage --out lcov + - name: Publish to Coveralls + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} From 1313256db3e9a31a3e0647abaacc9a8e4edb51b1 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 8 Feb 2024 09:07:52 -0600 Subject: [PATCH 053/175] chore(ci): Use latest for coverage --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7849a73..2e6597e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -153,7 +153,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.75" # STABLE + toolchain: stable - uses: Swatinem/rust-cache@v2 - name: Install cargo-tarpaulin run: cargo install cargo-tarpaulin From 51a98a25b6c30dd2fbdd74795432006525d1d84a Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 15 Feb 2024 09:57:26 -0600 Subject: [PATCH 054/175] chore(ci): Defer to package.rust-version for clippy --- .clippy.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/.clippy.toml b/.clippy.toml index 090e2be..293c14f 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1,4 +1,3 @@ -msrv = "1.65.0" # MSRV warn-on-all-wildcard-imports = true allow-expect-in-tests = true allow-unwrap-in-tests = true From 4db293d99b81e9c7da8fb030b1471e4e96dc91ef Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 15 Feb 2024 09:58:01 -0600 Subject: [PATCH 055/175] chore(ci): Only verify MSRV for published packages --- .github/workflows/ci.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e6597e..03a4fc0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,7 +53,7 @@ jobs: - name: No-default features run: cargo test --workspace --no-default-features msrv: - name: "Check MSRV: 1.65.0" + name: "Check MSRV" runs-on: ubuntu-latest steps: - name: Checkout repository @@ -61,14 +61,15 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.65.0" # MSRV + toolchain: stable - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@cargo-hack - name: Default features - run: cargo check --workspace --all-targets + run: cargo hack check --rust-version --ignore-private --workspace --all-targets - name: All features - run: cargo check --workspace --all-targets --all-features + run: cargo hack check --rust-version --ignore-private --workspace --all-targets --all-features - name: No-default features - run: cargo check --workspace --all-targets --no-default-features + run: cargo hack check --rust-version --ignore-private --workspace --all-targets --no-default-features lockfile: runs-on: ubuntu-latest steps: From 779496bb002837bf4e115ae3a33e7c819abdf293 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 15 Feb 2024 10:03:14 -0600 Subject: [PATCH 056/175] chore(ci): Run the latest clippy --- .github/renovate.json5 | 37 +++++++++++++++++++++++++++++++++++-- .github/workflows/ci.yml | 2 +- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 32d3628..06c1d63 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -21,7 +21,25 @@ 'MSRV.*?(?\\d+\\.\\d+(\\.\\d+)?)', '(?\\d+\\.\\d+(\\.\\d+)?).*?MSRV', ], - depNameTemplate: 'rust', + depNameTemplate: 'MSRV', + packageNameTemplate: 'rust-lang/rust', + datasourceTemplate: 'github-releases', + }, + { + customType: 'regex', + fileMatch: [ + '^rust-toolchain\\.toml$', + 'Cargo.toml$', + 'clippy.toml$', + '\\.clippy.toml$', + '^\\.github/workflows/ci.yml$', + '^\\.github/workflows/rust-next.yml$', + ], + matchStrings: [ + 'STABLE.*?(?\\d+\\.\\d+(\\.\\d+)?)', + '(?\\d+\\.\\d+(\\.\\d+)?).*?STABLE', + ], + depNameTemplate: 'STABLE', packageNameTemplate: 'rust-lang/rust', datasourceTemplate: 'github-releases', }, @@ -33,7 +51,7 @@ 'custom.regex', ], matchPackageNames: [ - 'rust', + 'MSRV', ], minimumReleaseAge: '336 days', // 8 releases * 6 weeks per release * 7 days per week internalChecksFilter: 'strict', @@ -41,6 +59,21 @@ schedule: [ '* * * * *', ], + groupName: 'rust-version', + }, + { + commitMessageTopic: 'STABLE', + matchManagers: [ + 'custom.regex', + ], + matchPackageNames: [ + 'STABLE', + ], + extractVersion: '^(?\\d+\\.\\d+)', // Drop the patch version + schedule: [ + '* * * * *', + ], + groupName: 'rust-version', }, // Goals: // - Keep version reqs low, ignoring compatible normal/build dependencies diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03a4fc0..1c18ca6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -124,7 +124,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.65.0" # MSRV + toolchain: "1.76" # STABLE components: clippy - uses: Swatinem/rust-cache@v2 - name: Install SARIF tools From c977df514987a625772ca04df9fc100ba8b7576f Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 20 Feb 2024 20:22:05 -0600 Subject: [PATCH 057/175] chore(ci): Prevent cargo-hack from blowing away our lockfile See taiki-e/cargo-hack#234 --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c18ca6..12d398c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,11 +65,11 @@ jobs: - uses: Swatinem/rust-cache@v2 - uses: taiki-e/install-action@cargo-hack - name: Default features - run: cargo hack check --rust-version --ignore-private --workspace --all-targets + run: cargo hack check --locked --rust-version --ignore-private --workspace --all-targets - name: All features - run: cargo hack check --rust-version --ignore-private --workspace --all-targets --all-features + run: cargo hack check --locked --rust-version --ignore-private --workspace --all-targets --all-features - name: No-default features - run: cargo hack check --rust-version --ignore-private --workspace --all-targets --no-default-features + run: cargo hack check --locked --rust-version --ignore-private --workspace --all-targets --no-default-features lockfile: runs-on: ubuntu-latest steps: From 7846c5130e5459ce452bd4fdb17373d83f45dff3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Mar 2024 00:30:14 +0000 Subject: [PATCH 058/175] chore(deps): Update pre-commit/action action to v3.0.1 --- .github/workflows/pre-commit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 7d77328..1b000ab 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -24,4 +24,4 @@ jobs: steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 - - uses: pre-commit/action@v3.0.0 + - uses: pre-commit/action@v3.0.1 From 3d5ead81cf3962997045915cd9b137086d35d1a9 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 21 Mar 2024 10:46:56 -0500 Subject: [PATCH 059/175] chore(ci): Configure standard lints --- Cargo.toml | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ 2 files changed, 86 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index b8ecde1..e51c5dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,87 @@ include = [ "examples/**/*" ] +[workspace.lints.rust] +missing_docs = "warn" +rust_2018_idioms = "warn" +unreachable_pub = "warn" +unsafe-op-in-unsafe-fn = "warn" +unsafe_code = "warn" +unused-crate-dependencies = "warn" +unused-lifetimes = "warn" +unused-macro-rules = "warn" +unused-qualifications = "warn" + +[workspace.lints.clippy] +bool_assert_comparison = "allow" +branches_sharing_code = "allow" +checked_conversions = "warn" +collapsible_else_if = "allow" +create_dir = "warn" +dbg_macro = "warn" +debug_assert_with_mut_call = "warn" +doc_markdown = "warn" +empty_enum = "warn" +enum_glob_use = "warn" +exhaustive_enums = "warn" +exhaustive_structs = "warn" +exit = "warn" +expl_impl_clone_on_copy = "warn" +explicit_deref_methods = "warn" +explicit_into_iter_loop = "warn" +fallible_impl_from = "warn" +filter_map_next = "warn" +flat_map_option = "warn" +float_cmp_const = "warn" +fn_params_excessive_bools = "warn" +from_iter_instead_of_collect = "warn" +if_same_then_else = "allow" +implicit_clone = "warn" +imprecise_flops = "warn" +inconsistent_struct_constructor = "warn" +inefficient_to_string = "warn" +infinite_loop = "warn" +invalid_upcast_comparisons = "warn" +items_after_statements = "warn" +large_digit_groups = "warn" +large_stack_arrays = "warn" +large_types_passed_by_value = "warn" +let_and_return = "allow" # sometimes good to name what you are returning +linkedlist = "warn" +lossy_float_literal = "warn" +macro_use_imports = "warn" +match_wildcard_for_single_variants = "warn" +mem_forget = "warn" +mutex_integer = "warn" +needless_continue = "warn" +needless_for_each = "warn" +negative_feature_names = "warn" +path_buf_push_overwrite = "warn" +print_stderr = "warn" +print_stdout = "warn" +ptr_as_ptr = "warn" +rc_mutex = "warn" +redundant_feature_names = "warn" +ref_option_ref = "warn" +rest_pat_in_fully_bound_structs = "warn" +return_self_not_must_use = "warn" +same_functions_in_if_condition = "warn" +self_named_module_files = "warn" +semicolon_if_nothing_returned = "warn" +single_match_else = "warn" +str_to_string = "warn" +string_add = "warn" +string_add_assign = "warn" +string_lit_as_bytes = "warn" +string_to_string = "warn" +tests_outside_test_module = "warn" +todo = "warn" +trait_duplication_in_bounds = "warn" +unwrap_used = "warn" +verbose_file_reads = "warn" +wildcard_imports = "warn" +zero_sized_map_values = "warn" + [package] name = "PROJECT" version = "0.0.1" @@ -46,3 +127,6 @@ default = [] [dependencies] [dev-dependencies] + +[lints] +workspace = true diff --git a/src/lib.rs b/src/lib.rs index 45bf577..8ce46b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,4 @@ +//! > DESCRIPTION + #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![allow(non_snake_case)] // TODO: Delete me From ace6e07683db64f05a237d8c833e2320a951b5d4 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 21 Mar 2024 12:20:47 -0500 Subject: [PATCH 060/175] chore(ci): Don't update stable and MSRV together We might want to hold one or the other back --- .github/renovate.json5 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 06c1d63..373fc0e 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -59,10 +59,9 @@ schedule: [ '* * * * *', ], - groupName: 'rust-version', }, { - commitMessageTopic: 'STABLE', + commitMessageTopic: 'Rust Stable', matchManagers: [ 'custom.regex', ], @@ -73,7 +72,6 @@ schedule: [ '* * * * *', ], - groupName: 'rust-version', }, // Goals: // - Keep version reqs low, ignoring compatible normal/build dependencies From 8ec86ab9a22aa7333af26113d8b725333966635f Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 25 Mar 2024 12:33:58 -0500 Subject: [PATCH 061/175] chore: Normalize clippy lint names --- Cargo.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e51c5dd..d03936f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,12 +20,12 @@ include = [ missing_docs = "warn" rust_2018_idioms = "warn" unreachable_pub = "warn" -unsafe-op-in-unsafe-fn = "warn" +unsafe_op_in_unsafe_fn = "warn" unsafe_code = "warn" -unused-crate-dependencies = "warn" -unused-lifetimes = "warn" -unused-macro-rules = "warn" -unused-qualifications = "warn" +unused_crate_dependencies = "warn" +unused_lifetimes = "warn" +unused_macro_rules = "warn" +unused_qualifications = "warn" [workspace.lints.clippy] bool_assert_comparison = "allow" From 8e647d9cd40a6891d524737d97d93a43a9e7b965 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 28 Mar 2024 09:35:59 -0500 Subject: [PATCH 062/175] chore: Encourage use of workspace.dependencies --- Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index d03936f..e07a473 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,8 @@ include = [ "examples/**/*" ] +[workspace.dependencies] + [workspace.lints.rust] missing_docs = "warn" rust_2018_idioms = "warn" From 126eb3d4dc4f59bcbee11d9d55545f01f75fb734 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 28 Mar 2024 09:48:35 -0500 Subject: [PATCH 063/175] chore: Encourage a single test binary --- Cargo.lock | 49 ++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 ++ tests/testsuite/delete_me.rs | 0 tests/testsuite/main.rs | 1 + 4 files changed, 52 insertions(+) create mode 100644 tests/testsuite/delete_me.rs create mode 100644 tests/testsuite/main.rs diff --git a/Cargo.lock b/Cargo.lock index 49c1f2d..e50f286 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,3 +5,52 @@ version = 3 [[package]] name = "PROJECT" version = "0.0.1" +dependencies = [ + "automod", +] + +[[package]] +name = "automod" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edf3ee19dbc0a46d740f6f0926bde8c50f02bdbc7b536842da28f6ac56513a8b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/Cargo.toml b/Cargo.toml index e07a473..d5e3b01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ include = [ ] [workspace.dependencies] +automod = "1.0.14" [workspace.lints.rust] missing_docs = "warn" @@ -129,6 +130,7 @@ default = [] [dependencies] [dev-dependencies] +automod.workspace = true [lints] workspace = true diff --git a/tests/testsuite/delete_me.rs b/tests/testsuite/delete_me.rs new file mode 100644 index 0000000..e69de29 diff --git a/tests/testsuite/main.rs b/tests/testsuite/main.rs new file mode 100644 index 0000000..4441374 --- /dev/null +++ b/tests/testsuite/main.rs @@ -0,0 +1 @@ +automod::dir!("tests/testsuite"); From c8b190be3a7397d63ffb175f8387ef98e7896b5a Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 28 Mar 2024 09:50:22 -0500 Subject: [PATCH 064/175] chore(ci): Use latest SARIF Now that we run clippy on stable, we can do this --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12d398c..52ce7f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -128,9 +128,9 @@ jobs: components: clippy - uses: Swatinem/rust-cache@v2 - name: Install SARIF tools - run: cargo install clippy-sarif --version 0.3.4 --locked # Held back due to msrv + run: cargo install clippy-sarif --locked - name: Install SARIF tools - run: cargo install sarif-fmt --version 0.3.4 --locked # Held back due to msrv + run: cargo install sarif-fmt --locked - name: Check run: > cargo clippy --workspace --all-features --all-targets --message-format=json -- -D warnings --allow deprecated From 9b1b56620156971664aaf0f7a693bf3bc72ca0cb Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 28 Mar 2024 09:51:51 -0500 Subject: [PATCH 065/175] chore(ci): Fix all rust-version-specific checks to stable --- .github/workflows/ci.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 52ce7f2..42c6be7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,7 +91,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: stable + toolchain: "1.76" # STABLE - uses: Swatinem/rust-cache@v2 - name: Check documentation env: @@ -106,9 +106,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - # Not MSRV because its harder to jump between versions and people are - # more likely to have stable - toolchain: stable + toolchain: "1.76" # STABLE components: rustfmt - uses: Swatinem/rust-cache@v2 - name: Check formatting From 92d486c4b03efa984a9d03aa7279a1febe84d816 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 28 Mar 2024 09:53:02 -0500 Subject: [PATCH 066/175] chore(ci): Speed up lockfile check --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 42c6be7..7a455a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,7 +81,7 @@ jobs: toolchain: stable - uses: Swatinem/rust-cache@v2 - name: "Is lockfile updated?" - run: cargo fetch --locked + run: cargo update --workspace --locked docs: name: Docs runs-on: ubuntu-latest From 9258d9af7b87bc0394ef09be7e65bf6152d99f4b Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 28 Mar 2024 09:57:23 -0500 Subject: [PATCH 067/175] chore(ci): More exhaustively check features --- .github/workflows/ci.yml | 15 ++++----------- .github/workflows/rust-next.yml | 18 ++++++------------ 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a455a4..134c317 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,14 +44,11 @@ jobs: with: toolchain: ${{ matrix.rust }} - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@cargo-hack - name: Build run: cargo test --workspace --no-run - - name: Default features - run: cargo test --workspace - - name: All features - run: cargo test --workspace --all-features - - name: No-default features - run: cargo test --workspace --no-default-features + - name: Test + run: cargo hack test --feature-powerset --workspace msrv: name: "Check MSRV" runs-on: ubuntu-latest @@ -65,11 +62,7 @@ jobs: - uses: Swatinem/rust-cache@v2 - uses: taiki-e/install-action@cargo-hack - name: Default features - run: cargo hack check --locked --rust-version --ignore-private --workspace --all-targets - - name: All features - run: cargo hack check --locked --rust-version --ignore-private --workspace --all-targets --all-features - - name: No-default features - run: cargo hack check --locked --rust-version --ignore-private --workspace --all-targets --no-default-features + run: cargo hack check --feature-powerset --locked --rust-version --ignore-private --workspace --all-targets lockfile: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/rust-next.yml b/.github/workflows/rust-next.yml index 49e5d8c..e673b65 100644 --- a/.github/workflows/rust-next.yml +++ b/.github/workflows/rust-next.yml @@ -36,14 +36,11 @@ jobs: with: toolchain: ${{ matrix.rust }} - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@cargo-hack - name: Build run: cargo test --workspace --no-run - - name: Default features - run: cargo test --workspace - - name: All features - run: cargo test --workspace --all-features - - name: No-default features - run: cargo test --workspace --no-default-features + - name: Test + run: cargo hack test --feature-powerset --workspace latest: name: "Check latest dependencies" runs-on: ubuntu-latest @@ -55,13 +52,10 @@ jobs: with: toolchain: stable - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@cargo-hack - name: Update dependencues run: cargo update - name: Build run: cargo test --workspace --no-run - - name: Default features - run: cargo test --workspace - - name: All features - run: cargo test --workspace --all-features - - name: No-default features - run: cargo test --workspace --no-default-features + - name: Test + run: cargo hack test --feature-powerset --workspace From 2714cca7c31a9c73716e88a93693c119c527d7f1 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 28 Mar 2024 09:58:31 -0500 Subject: [PATCH 068/175] chore(ci): Don't check for unused crates --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d5e3b01..4097fef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,6 @@ rust_2018_idioms = "warn" unreachable_pub = "warn" unsafe_op_in_unsafe_fn = "warn" unsafe_code = "warn" -unused_crate_dependencies = "warn" unused_lifetimes = "warn" unused_macro_rules = "warn" unused_qualifications = "warn" From 314eef7f5fb7e415e8cd92887e5e878e9bfa929b Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 28 Mar 2024 10:38:57 -0500 Subject: [PATCH 069/175] chore: Dont check must_use See https://github.com/rust-lang/rust-clippy/issues/8339 --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4097fef..666e6e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,7 +81,6 @@ rc_mutex = "warn" redundant_feature_names = "warn" ref_option_ref = "warn" rest_pat_in_fully_bound_structs = "warn" -return_self_not_must_use = "warn" same_functions_in_if_condition = "warn" self_named_module_files = "warn" semicolon_if_nothing_returned = "warn" From 6a9d2bf50fa78d8f277b77be836b48fad8c7c764 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 28 Mar 2024 12:45:57 -0500 Subject: [PATCH 070/175] chore: Don't warn on unsafe This works well when a package is a safe abstraction but to universally apply in a template to all members of a workspace doesn't make sense. --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 666e6e3..50bfea5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,6 @@ missing_docs = "warn" rust_2018_idioms = "warn" unreachable_pub = "warn" unsafe_op_in_unsafe_fn = "warn" -unsafe_code = "warn" unused_lifetimes = "warn" unused_macro_rules = "warn" unused_qualifications = "warn" From 8d4b1b6c8daf3c32828bf92725811cf433917081 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 28 Mar 2024 13:24:28 -0500 Subject: [PATCH 071/175] chore: Remove clippy::tests_outside_test_module See https://github.com/rust-lang/rust-clippy/issues/11024 --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 50bfea5..ed593eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,7 +89,6 @@ string_add = "warn" string_add_assign = "warn" string_lit_as_bytes = "warn" string_to_string = "warn" -tests_outside_test_module = "warn" todo = "warn" trait_duplication_in_bounds = "warn" unwrap_used = "warn" From 99e034bbbbae7d60bb68d68c6d0db8338a97b030 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 28 Mar 2024 15:10:58 -0500 Subject: [PATCH 072/175] chore: Move print lints to lib.rs While there is a config for ignoring these in tests, it doesn't help with examples. --- Cargo.toml | 2 -- src/lib.rs | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ed593eb..faf1e63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,8 +73,6 @@ needless_continue = "warn" needless_for_each = "warn" negative_feature_names = "warn" path_buf_push_overwrite = "warn" -print_stderr = "warn" -print_stdout = "warn" ptr_as_ptr = "warn" rc_mutex = "warn" redundant_feature_names = "warn" diff --git a/src/lib.rs b/src/lib.rs index 8ce46b5..2eabbd0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,6 @@ //! > DESCRIPTION #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![warn(clippy::print_stderr)] +#![warn(clippy::print_stdout)] #![allow(non_snake_case)] // TODO: Delete me From a516bda4adb0f367da527488697ea308fbe58b38 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 1 Apr 2024 08:58:36 -0500 Subject: [PATCH 073/175] chore: Drop workspace.dependencies Without automated checks, this will make it harder to track breaking changes. --- Cargo.toml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index faf1e63..983e090 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,9 +16,6 @@ include = [ "examples/**/*" ] -[workspace.dependencies] -automod = "1.0.14" - [workspace.lints.rust] missing_docs = "warn" rust_2018_idioms = "warn" @@ -124,7 +121,7 @@ default = [] [dependencies] [dev-dependencies] -automod.workspace = true +automod = "1.0.14" [lints] workspace = true From ebc70d00f9259146592b7987bfcb8a0cb6c16661 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 1 Apr 2024 09:11:24 -0500 Subject: [PATCH 074/175] chore: Only check missing_docs in lib This also fires in examples and other places. While docs in examples would be nice, it isn't universally applicable and `allow`s would undermine the examples. --- Cargo.toml | 1 - src/lib.rs | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 983e090..715131b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ include = [ ] [workspace.lints.rust] -missing_docs = "warn" rust_2018_idioms = "warn" unreachable_pub = "warn" unsafe_op_in_unsafe_fn = "warn" diff --git a/src/lib.rs b/src/lib.rs index 2eabbd0..39877b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ //! > DESCRIPTION #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![warn(missing_docs)] #![warn(clippy::print_stderr)] #![warn(clippy::print_stdout)] #![allow(non_snake_case)] // TODO: Delete me From 3278d49444c33ece610de3fb5547bd885124dfe7 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 1 Apr 2024 10:35:16 -0500 Subject: [PATCH 075/175] chore: Allow print in tests --- .clippy.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/.clippy.toml b/.clippy.toml index 293c14f..027eef4 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1,4 +1,5 @@ warn-on-all-wildcard-imports = true +allow-print-in-tests = true allow-expect-in-tests = true allow-unwrap-in-tests = true allow-dbg-in-tests = true From d634de649f30d5a4deade46333606bc63897d05e Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 1 Apr 2024 11:36:58 -0500 Subject: [PATCH 076/175] chore(ci): Ensure CI job always runs --- .github/workflows/ci.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 134c317..95b13b4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,11 +23,13 @@ jobs: permissions: contents: none name: CI - needs: [test, msrv, docs, rustfmt, clippy] + needs: [test, msrv, lockfile, docs, rustfmt, clippy] runs-on: ubuntu-latest + if: "always()" steps: - - name: Done - run: exit 0 + - name: Failed + run: exit 1 + if: "contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped')" test: name: Test strategy: From 2570b58a0feaf355dede9080a9f4c98f8ba5580b Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 1 Apr 2024 12:31:49 -0500 Subject: [PATCH 077/175] chore(ci): Skip branch protections --- .github/settings.yml | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/.github/settings.yml b/.github/settings.yml index 7d5e4fc..08983ae 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -42,14 +42,18 @@ labels: color: '#c2e0c6' description: "Help wanted!" -branches: - - name: main - protection: - required_pull_request_reviews: null - required_conversation_resolution: true - required_status_checks: - # Required. Require branches to be up to date before merging. - strict: false - contexts: ["CI", "Lint Commits", "Spell Check with Typos"] - enforce_admins: false - restrictions: null +# This serves more as documentation. +# Branch protection API was replaced by rulesets but settings isn't updated. +# See https://github.com/repository-settings/app/issues/825 +# +# branches: +# - name: main +# protection: +# required_pull_request_reviews: null +# required_conversation_resolution: true +# required_status_checks: +# # Required. Require branches to be up to date before merging. +# strict: false +# contexts: ["CI", "Lint Commits", "Spell Check with Typos"] +# enforce_admins: false +# restrictions: null From afd275590c5568e8f7ca60abc1f33b20e3679c03 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 1 Apr 2024 12:36:16 -0500 Subject: [PATCH 078/175] chore(ci): Don't block on Lint Commits --- .github/settings.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/settings.yml b/.github/settings.yml index 08983ae..457eed6 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -54,6 +54,6 @@ labels: # required_status_checks: # # Required. Require branches to be up to date before merging. # strict: false -# contexts: ["CI", "Lint Commits", "Spell Check with Typos"] +# contexts: ["CI", "Spell Check with Typos"] # enforce_admins: false # restrictions: null From 14225df351a4510a6fad72e716b29173347aac84 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 16 Apr 2024 21:46:56 -0500 Subject: [PATCH 079/175] chore(ci): Auto-merge linter version updates --- .github/renovate.json5 | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 373fc0e..62ca46b 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -72,6 +72,7 @@ schedule: [ '* * * * *', ], + automerge: true, }, // Goals: // - Keep version reqs low, ignoring compatible normal/build dependencies From be30b1bba034344c1a7c526b2b1898a8767471c5 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 26 Apr 2024 09:20:18 -0500 Subject: [PATCH 080/175] chore(ci): Try again with not auto-updating MSRV The overhead for MSRV bumping is a lot lower and its annoying merging all of the PRs (and I don't want these auto-merged) --- .github/renovate.json5 | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 62ca46b..c184420 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -7,24 +7,6 @@ configMigration: true, dependencyDashboard: true, customManagers: [ - { - customType: 'regex', - fileMatch: [ - '^rust-toolchain\\.toml$', - 'Cargo.toml$', - 'clippy.toml$', - '\\.clippy.toml$', - '^\\.github/workflows/ci.yml$', - '^\\.github/workflows/rust-next.yml$', - ], - matchStrings: [ - 'MSRV.*?(?\\d+\\.\\d+(\\.\\d+)?)', - '(?\\d+\\.\\d+(\\.\\d+)?).*?MSRV', - ], - depNameTemplate: 'MSRV', - packageNameTemplate: 'rust-lang/rust', - datasourceTemplate: 'github-releases', - }, { customType: 'regex', fileMatch: [ @@ -45,21 +27,6 @@ }, ], packageRules: [ - { - commitMessageTopic: 'MSRV', - matchManagers: [ - 'custom.regex', - ], - matchPackageNames: [ - 'MSRV', - ], - minimumReleaseAge: '336 days', // 8 releases * 6 weeks per release * 7 days per week - internalChecksFilter: 'strict', - extractVersion: '^(?\\d+\\.\\d+)', // Drop the patch version - schedule: [ - '* * * * *', - ], - }, { commitMessageTopic: 'Rust Stable', matchManagers: [ From a01f25da96e8bd3e216fbc19ac9883ab3bf969ce Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 26 Apr 2024 09:23:28 -0500 Subject: [PATCH 081/175] chore(ci): Reduce noisy lints Want to add this back in later but this is slowing down migration of my repos. --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 39877b7..2eabbd0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ //! > DESCRIPTION #![cfg_attr(docsrs, feature(doc_auto_cfg))] -#![warn(missing_docs)] #![warn(clippy::print_stderr)] #![warn(clippy::print_stdout)] #![allow(non_snake_case)] // TODO: Delete me From 82cf9a62b027c10c6fafdcaaee24c4e92d7da61d Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 26 Apr 2024 09:35:55 -0500 Subject: [PATCH 082/175] chore(ci): Reduce noisy lints --- Cargo.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 715131b..898251e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,9 +35,6 @@ debug_assert_with_mut_call = "warn" doc_markdown = "warn" empty_enum = "warn" enum_glob_use = "warn" -exhaustive_enums = "warn" -exhaustive_structs = "warn" -exit = "warn" expl_impl_clone_on_copy = "warn" explicit_deref_methods = "warn" explicit_into_iter_loop = "warn" @@ -85,7 +82,6 @@ string_lit_as_bytes = "warn" string_to_string = "warn" todo = "warn" trait_duplication_in_bounds = "warn" -unwrap_used = "warn" verbose_file_reads = "warn" wildcard_imports = "warn" zero_sized_map_values = "warn" From 181a2cf5e673d0f6f42133a5b30ccafd86b0106d Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 26 Apr 2024 11:36:19 -0500 Subject: [PATCH 083/175] chore(ci): Allow prelude wildcard imports --- .clippy.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/.clippy.toml b/.clippy.toml index 027eef4..1d4c5dc 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1,4 +1,3 @@ -warn-on-all-wildcard-imports = true allow-print-in-tests = true allow-expect-in-tests = true allow-unwrap-in-tests = true From 51de731521efb05c5503e05c33036d8fa439bc5a Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 26 Apr 2024 15:59:46 -0500 Subject: [PATCH 084/175] chore(ci): Lint clippy::items_after_statements seems too strict --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 898251e..5a90580 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,6 @@ inconsistent_struct_constructor = "warn" inefficient_to_string = "warn" infinite_loop = "warn" invalid_upcast_comparisons = "warn" -items_after_statements = "warn" large_digit_groups = "warn" large_stack_arrays = "warn" large_types_passed_by_value = "warn" From 78741e51bbbe6c83aaa98305623a8ffc6226493f Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 27 May 2024 21:45:38 -0500 Subject: [PATCH 085/175] chore: Remove lints that lead to bad code --- Cargo.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5a90580..8090691 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,7 +58,6 @@ let_and_return = "allow" # sometimes good to name what you are returning linkedlist = "warn" lossy_float_literal = "warn" macro_use_imports = "warn" -match_wildcard_for_single_variants = "warn" mem_forget = "warn" mutex_integer = "warn" needless_continue = "warn" @@ -73,7 +72,6 @@ rest_pat_in_fully_bound_structs = "warn" same_functions_in_if_condition = "warn" self_named_module_files = "warn" semicolon_if_nothing_returned = "warn" -single_match_else = "warn" str_to_string = "warn" string_add = "warn" string_add_assign = "warn" From 44916f6d2b8da4d778186083c31ff52a73187edf Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 29 May 2024 16:15:19 -0500 Subject: [PATCH 086/175] chore: Update deny config --- deny.toml | 176 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 136 insertions(+), 40 deletions(-) diff --git a/deny.toml b/deny.toml index 21fa937..b6ecbe9 100644 --- a/deny.toml +++ b/deny.toml @@ -4,32 +4,82 @@ # * allow - No warning or error will be produced, though in some cases a note # will be +# Root options + +# The graph table configures how the dependency graph is constructed and thus +# which crates the checks are performed against +[graph] +# If 1 or more target triples (and optionally, target_features) are specified, +# only the specified targets will be checked when running `cargo deny check`. +# This means, if a particular package is only ever used as a target specific +# dependency, such as, for example, the `nix` crate only being used via the +# `target_family = "unix"` configuration, that only having windows targets in +# this list would mean the nix crate, as well as any of its exclusive +# dependencies not shared by any other crates, would be ignored, as the target +# list here is effectively saying which targets you are building for. +targets = [ + # The triple can be any string, but only the target triples built in to + # rustc (as of 1.40) can be checked against actual config expressions + #"x86_64-unknown-linux-musl", + # You can also specify which target_features you promise are enabled for a + # particular target. target_features are currently not validated against + # the actual valid features supported by the target architecture. + #{ triple = "wasm32-unknown-unknown", features = ["atomics"] }, +] +# When creating the dependency graph used as the source of truth when checks are +# executed, this field can be used to prune crates from the graph, removing them +# from the view of cargo-deny. This is an extremely heavy hammer, as if a crate +# is pruned from the graph, all of its dependencies will also be pruned unless +# they are connected to another crate in the graph that hasn't been pruned, +# so it should be used with care. The identifiers are [Package ID Specifications] +# (https://doc.rust-lang.org/cargo/reference/pkgid-spec.html) +#exclude = [] +# If true, metadata will be collected with `--all-features`. Note that this can't +# be toggled off if true, if you want to conditionally enable `--all-features` it +# is recommended to pass `--all-features` on the cmd line instead +all-features = false +# If true, metadata will be collected with `--no-default-features`. The same +# caveat with `all-features` applies +no-default-features = false +# If set, these feature will be enabled when collecting metadata. If `--features` +# is specified on the cmd line they will take precedence over this option. +#features = [] + +# The output table provides options for how/if diagnostics are outputted +[output] +# When outputting inclusion graphs in diagnostics that include features, this +# option can be used to specify the depth at which feature edges will be added. +# This option is included since the graphs can be quite large and the addition +# of features from the crate(s) to all of the graph roots can be far too verbose. +# This option can be overridden via `--feature-depth` on the cmd line +feature-depth = 1 + # This section is considered when running `cargo deny check advisories` # More documentation for the advisories section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html [advisories] -# The lint level for security vulnerabilities -vulnerability = "deny" -# The lint level for unmaintained crates -unmaintained = "warn" -# The lint level for crates that have been yanked from their source registry -yanked = "warn" -# The lint level for crates with security notices. Note that as of -# 2019-12-17 there are no security notice advisories in -# https://github.com/rustsec/advisory-db -notice = "warn" +# The path where the advisory databases are cloned/fetched into +#db-path = "$CARGO_HOME/advisory-dbs" +# The url(https://github.com/s) of the advisory databases to use +#db-urls = ["https://github.com/rustsec/advisory-db"] # A list of advisory IDs to ignore. Note that ignored advisories will still # output a note when they are encountered. -# -# e.g. "RUSTSEC-0000-0000", ignore = [ + #"RUSTSEC-0000-0000", + #{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" }, + #"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish + #{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" }, ] +# If this is true, then cargo deny will use the git executable to fetch advisory database. +# If this is false, then it uses a built-in git library. +# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support. +# See Git Authentication for more information about setting up git authentication. +#git-fetch-with-cli = true # This section is considered when running `cargo deny check licenses` # More documentation for the licenses section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html [licenses] -unlicensed = "deny" # List of explicitly allowed licenses # See https://spdx.org/licenses/ for list of possible licenses # [possible values: any SPDX 3.11 short identifier (+ optional exception)]. @@ -42,26 +92,8 @@ allow = [ "Unicode-DFS-2016", "CC0-1.0", "ISC", + "OpenSSL", ] -# List of explicitly disallowed licenses -# See https://spdx.org/licenses/ for list of possible licenses -# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. -deny = [ -] -# Lint level for licenses considered copyleft -copyleft = "deny" -# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses -# * both - The license will be approved if it is both OSI-approved *AND* FSF -# * either - The license will be approved if it is either OSI-approved *OR* FSF -# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF -# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved -# * neither - This predicate is ignored and the default lint level is used -allow-osi-fsf-free = "neither" -# Lint level used when no other predicates are matched -# 1. License isn't in the allow or deny lists -# 2. License isn't copyleft -# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither" -default = "deny" # The confidence threshold for detecting a license from license text. # The higher the value, the more closely the license text must be to the # canonical license text of a valid SPDX license file. @@ -72,7 +104,25 @@ confidence-threshold = 0.8 exceptions = [ # Each entry is the crate and version constraint, and its specific allow # list - #{ allow = ["Zlib"], name = "adler32", version = "*" }, + #{ allow = ["Zlib"], crate = "adler32" }, +] + +# Some crates don't have (easily) machine readable licensing information, +# adding a clarification entry for it allows you to manually specify the +# licensing information +[[licenses.clarify]] +# The package spec the clarification applies to +crate = "ring" +# The SPDX expression for the license requirements of the crate +expression = "MIT AND ISC AND OpenSSL" +# One or more files in the crate's source used as the "source of truth" for +# the license expression. If the contents match, the clarification will be used +# when running the license check, otherwise the clarification will be ignored +# and the crate will be checked normally, which may produce warnings or errors +# depending on the rest of your configuration +license-files = [ +# Each entry is a crate relative path, and the (opaque) hash of its contents +{ path = "LICENSE", hash = 0xbd0eed23 } ] [licenses.private] @@ -81,6 +131,12 @@ exceptions = [ # To see how to mark a crate as unpublished (to the official registry), # visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field. ignore = true +# One or more private registries that you might publish crates to, if a crate +# is only published to private registries, and ignore is true, the crate will +# not have its license(s) checked +registries = [ + #"https://sekretz.com/registry+]%20%20#%20This%20section%20is%20considered%20when%20running%20%60cargo%20deny%20check%20bans%60.%20#%20More%20documentation%20about%20the'bans' section can be found here: @@ -89,7 +145,7 @@ ignore = true # Lint level for when multiple versions of the same crate are detected multiple-versions = "warn" # Lint level for when a crate version requirement is `*` -wildcards = "warn" +wildcards = "allow" # The graph highlighting used when creating dotgraphs for crates # with multiple versions # * lowest-version - The path to the lowest versioned duplicate is highlighted @@ -106,17 +162,53 @@ workspace-default-features = "allow" external-default-features = "allow" # List of crates that are allowed. Use with care! allow = [ - #{ name = "ansi_term", version = "=0.11.0" }, + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is allowed" }, ] # List of crates to deny deny = [ - # Each entry the name of a crate and a version range. If version is - # not specified, all versions will be matched. - #{ name = "ansi_term", version = "=0.11.0" }, - # + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is banned" }, # Wrapper crates can optionally be specified to allow the crate when it # is a direct dependency of the otherwise banned crate - #{ name = "ansi_term", version = "=0.11.0", wrappers = [] }, + #{ crate = "ansi_term@0.11.0", wrappers = ["this-crate-directly-depends-on-ansi_term"] }, +] + +# List of features to allow/deny +# Each entry the name of a crate and a version range. If version is +# not specified, all versions will be matched. +#[[bans.features]] +#crate = "reqwest" +# Features to not allow +#deny = ["json"] +# Features to allow +#allow = [ +# "rustls", +# "__rustls", +# "__tls", +# "hyper-rustls", +# "rustls", +# "rustls-pemfile", +# "rustls-tls-webpki-roots", +# "tokio-rustls", +# "webpki-roots", +#] +# If true, the allowed features must exactly match the enabled feature set. If +# this is set there is no point setting `deny` +#exact = true + +# Certain crates/versions that will be skipped when doing duplicate detection. +skip = [ + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason why it can't be updated/removed" }, +] +# Similarly to `skip` allows you to skip certain crates during duplicate +# detection. Unlike skip, it also includes the entire tree of transitive +# dependencies starting at the specified crate, up to a certain depth, which is +# by default infinite. +skip-tree = [ + #"ansi_term@0.11.0", # will be skipped along with _all_ of its direct and transitive dependencies + #{ crate = "ansi_term@0.11.0", depth = 20 }, ] # This section is considered when running `cargo deny check sources`. @@ -138,3 +230,7 @@ allow-git = [] [sources.allow-org] # 1 or more github.com organizations to allow git sources for github = [] +# 1 or more gitlab.com organizations to allow git sources for +gitlab = [] +# 1 or more bitbucket.org organizations to allow git sources for +bitbucket = [] From ce6badcd188650dac4b3c97b69bde86a738917a0 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 3 Jun 2024 10:29:26 -0500 Subject: [PATCH 087/175] chore: Fix typo --- .github/workflows/rust-next.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust-next.yml b/.github/workflows/rust-next.yml index e673b65..ab49963 100644 --- a/.github/workflows/rust-next.yml +++ b/.github/workflows/rust-next.yml @@ -53,7 +53,7 @@ jobs: toolchain: stable - uses: Swatinem/rust-cache@v2 - uses: taiki-e/install-action@cargo-hack - - name: Update dependencues + - name: Update dependencies run: cargo update - name: Build run: cargo test --workspace --no-run From 1353a953a527b7ebc0b0a3f267fc47f56359e886 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 4 Jun 2024 15:33:16 -0500 Subject: [PATCH 088/175] chore: Encourage use of repository --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 8090691..c9695d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,6 +87,7 @@ zero_sized_map_values = "warn" name = "PROJECT" version = "0.0.1" description = "DESCRIPTION" +repository = "REPOSITORY" categories = [] keywords = [] license.workspace = true From 7039c66c7f0a42b84136a2f166ce6446edbb9ce0 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 4 Jun 2024 15:33:50 -0500 Subject: [PATCH 089/175] chore: Encourage cloneable repositories --- Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c9695d7..96cb234 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ resolver = "2" [workspace.package] +repository = "REPOSITORY" license = "MIT OR Apache-2.0" edition = "2021" rust-version = "1.65.0" # MSRV @@ -87,9 +88,9 @@ zero_sized_map_values = "warn" name = "PROJECT" version = "0.0.1" description = "DESCRIPTION" -repository = "REPOSITORY" categories = [] keywords = [] +repository.workspace = true license.workspace = true edition.workspace = true rust-version.workspace = true From 2a274e149f7f6f7f80f08486bd34c4fc7b8d63c8 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 21 Jun 2024 14:21:41 -0400 Subject: [PATCH 090/175] chore(ci): Auto-update Mac now that latest uses m1 --- .github/workflows/ci.yml | 2 +- .github/workflows/rust-next.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 95b13b4..6e06499 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: name: Test strategy: matrix: - os: ["ubuntu-latest", "windows-latest", "macos-14"] + os: ["ubuntu-latest", "windows-latest", "macos-latest"] rust: ["stable"] continue-on-error: ${{ matrix.rust != 'stable' }} runs-on: ${{ matrix.os }} diff --git a/.github/workflows/rust-next.yml b/.github/workflows/rust-next.yml index ab49963..e98386c 100644 --- a/.github/workflows/rust-next.yml +++ b/.github/workflows/rust-next.yml @@ -21,7 +21,7 @@ jobs: name: Test strategy: matrix: - os: ["ubuntu-latest", "windows-latest", "macos-latest", "macos-14"] + os: ["ubuntu-latest", "windows-latest", "macos-latest"] rust: ["stable", "beta"] include: - os: ubuntu-latest From 0547ff2d0f135d541faef3735143b40c174b4c3a Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 4 Jul 2024 12:54:40 -0400 Subject: [PATCH 091/175] docs(contrib): Clarify our policies --- CONTRIBUTING.md | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e9d7079..1a6dd1c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,27 +29,42 @@ to re-work some of it and the discouragement that goes along with that. ### Process -Before posting a PR, we request that the commit history get cleaned up. -However, we recommend avoiding this during the review to make it easier to -check how feedback was handled. Once the PR is ready, we'll ask you to clean up -the commit history from the review. Once you let us know this is done, we can -move forward with merging! If you are uncomfortable with these parts of git, -let us know and we can help. - -For commit messages, we use [Conventional](https://www.conventionalcommits.org) -style. If you already wrote your commits and don't feel comfortable changing -them, don't worry and go ahead and create your PR. We'll work with you on the -best route forward. You can check your branch locally with -[`committed`](https://github.com/crate-ci/committed). - As a heads up, we'll be running your PR through the following gauntlet: - warnings turned to compile errors - `cargo test` - `rustfmt` - `clippy` - `rustdoc` -- [`committed`](https://github.com/crate-ci/committed) -- [`typos`](https://github.com/crate-ci/typos) +- [`committed`](https://github.com/crate-ci/committed) as we use [Conventional](https://www.conventionalcommits.org) commit styl +- [`typos`](https://github.com/crate-ci/typos) to check spelling + +Not everything can be checked automatically though. + +We request that the commit history get cleaned up. +We ask that commits are atomic, meaning they are complete and have a single responsibility. +PRs shoukd tell a cohesive story, with test and refactor commits that keep the +fix or feature commits simple and clear. + +Specifically, we would encouage +- File renames be isolated into their own commit +- Add tests in a commit before their feature or fix, showing the current behavior. + The diff for the feature/fix commit will then show how the behavior changed, + making it clearer to reviewrs and the community and showing people that the + test is verifying the expected state. + - e.g. [clap#5520](https://github.com/clap-rs/clap/pull/5520) + +Note that we are talking about ideals. +We understand having a clean history requires more advanced git skills; +feel free to ask us for help! +We might even suggest where it would work to be lax. +We also understand that editing some early commits may cause a lot of churn +with merge conflicts which can make it not worth editing all of the history. + +For code organization, we recommend +- Grouping `impl` blocks next to their type (or trait) +- Grouping private items after the `pub` item that uses them. + - The intent is to help people quickly find the "relevant" details, allowing them to "dig deeper" as needed. Or put another way, the `pub` items serve as a table-of-contents. + - The exact order is fuzzy; do what makes sense ## Releasing From eb4e999f1b679936ce1d11aa68b923066aff2ab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jalil=20David=20Salam=C3=A9=20Messina?= <60845989+jalil-salame@users.noreply.github.com> Date: Thu, 4 Jul 2024 19:06:12 +0200 Subject: [PATCH 092/175] Fix typos in CONTRIBUTING.md I found this through [mastodon][1] and found the typos jarring. [1]: https://hachyderm.io/@epage/112729287446906823 --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1a6dd1c..87d9134 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,14 +35,14 @@ As a heads up, we'll be running your PR through the following gauntlet: - `rustfmt` - `clippy` - `rustdoc` -- [`committed`](https://github.com/crate-ci/committed) as we use [Conventional](https://www.conventionalcommits.org) commit styl +- [`committed`](https://github.com/crate-ci/committed) as we use [Conventional](https://www.conventionalcommits.org) commit style - [`typos`](https://github.com/crate-ci/typos) to check spelling Not everything can be checked automatically though. -We request that the commit history get cleaned up. +We request that the commit history gets cleaned up. We ask that commits are atomic, meaning they are complete and have a single responsibility. -PRs shoukd tell a cohesive story, with test and refactor commits that keep the +PRs should tell a cohesive story, with test and refactor commits that keep the fix or feature commits simple and clear. Specifically, we would encouage From bdb06a11df6cf4d8b06848520f18609ab07c7b5e Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 9 Jul 2024 11:06:45 -0500 Subject: [PATCH 093/175] chore(ci): Verify version requirements --- .github/workflows/ci.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6e06499..d49017e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: permissions: contents: none name: CI - needs: [test, msrv, lockfile, docs, rustfmt, clippy] + needs: [test, msrv, lockfile, docs, rustfmt, clippy, minimal-versions] runs-on: ubuntu-latest if: "always()" steps: @@ -65,6 +65,24 @@ jobs: - uses: taiki-e/install-action@cargo-hack - name: Default features run: cargo hack check --feature-powerset --locked --rust-version --ignore-private --workspace --all-targets + minimal-versions: + name: Minimal versions + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install stable Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + - name: Install nightly Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: nightly + - name: Downgrade dependencies to minimal versions + run: cargo +nightly generate-lockfile -Z minimal-versions + - name: Compile with minimal versions + run: cargo +stable check --workspace --all-features --locked lockfile: runs-on: ubuntu-latest steps: From 87d9ae55c792a4f37b3f989250c1a3512df2926e Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 25 Jul 2024 15:48:09 -0500 Subject: [PATCH 094/175] chore: Fix clippy::lint_groups_priority for 1.80 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 96cb234..90d89f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ include = [ ] [workspace.lints.rust] -rust_2018_idioms = "warn" +rust_2018_idioms = { level = "warn", priority = -1 } unreachable_pub = "warn" unsafe_op_in_unsafe_fn = "warn" unused_lifetimes = "warn" From 553258af51034bc84dc9f951201e7b8f2285b57e Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 25 Jul 2024 15:35:58 -0700 Subject: [PATCH 095/175] Have clippy warn about uninlined format arguments This makes clippy warn about `format!("{}", var)`, with a machine-applicable fix converting to `format!("{var}")`. --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 90d89f6..97c7ed7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,6 +80,7 @@ string_lit_as_bytes = "warn" string_to_string = "warn" todo = "warn" trait_duplication_in_bounds = "warn" +uninlined_format_args = "warn" verbose_file_reads = "warn" wildcard_imports = "warn" zero_sized_map_values = "warn" From c5443c45979b52a7ef3790c9604681a171ee76f8 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Wed, 21 Aug 2024 15:01:07 -0600 Subject: [PATCH 096/175] test: Move all fixture tests to color --- tests/fixtures/{no-color => color}/ann_eof.svg | 0 tests/fixtures/{no-color => color}/ann_eof.toml | 0 tests/fixtures/{no-color => color}/ann_insertion.svg | 0 tests/fixtures/{no-color => color}/ann_insertion.toml | 0 tests/fixtures/{no-color => color}/ann_multiline.svg | 0 tests/fixtures/{no-color => color}/ann_multiline.toml | 0 tests/fixtures/{no-color => color}/ann_multiline2.svg | 0 tests/fixtures/{no-color => color}/ann_multiline2.toml | 0 tests/fixtures/{no-color => color}/ann_removed_nl.svg | 0 tests/fixtures/{no-color => color}/ann_removed_nl.toml | 0 .../fixtures/{no-color => color}/ensure-emoji-highlight-width.svg | 0 .../{no-color => color}/ensure-emoji-highlight-width.toml | 0 tests/fixtures/{no-color => color}/fold_ann_multiline.svg | 0 tests/fixtures/{no-color => color}/fold_ann_multiline.toml | 0 tests/fixtures/{no-color => color}/fold_bad_origin_line.svg | 0 tests/fixtures/{no-color => color}/fold_bad_origin_line.toml | 0 tests/fixtures/{no-color => color}/fold_leading.svg | 0 tests/fixtures/{no-color => color}/fold_leading.toml | 0 tests/fixtures/{no-color => color}/fold_trailing.svg | 0 tests/fixtures/{no-color => color}/fold_trailing.toml | 0 tests/fixtures/{no-color => color}/issue_9.svg | 0 tests/fixtures/{no-color => color}/issue_9.toml | 0 tests/fixtures/{no-color => color}/multiple_annotations.svg | 0 tests/fixtures/{no-color => color}/multiple_annotations.toml | 0 tests/fixtures/{no-color => color}/simple.svg | 0 tests/fixtures/{no-color => color}/simple.toml | 0 tests/fixtures/{no-color => color}/strip_line.svg | 0 tests/fixtures/{no-color => color}/strip_line.toml | 0 tests/fixtures/{no-color => color}/strip_line_char.svg | 0 tests/fixtures/{no-color => color}/strip_line_char.toml | 0 tests/fixtures/{no-color => color}/strip_line_non_ws.svg | 0 tests/fixtures/{no-color => color}/strip_line_non_ws.toml | 0 32 files changed, 0 insertions(+), 0 deletions(-) rename tests/fixtures/{no-color => color}/ann_eof.svg (100%) rename tests/fixtures/{no-color => color}/ann_eof.toml (100%) rename tests/fixtures/{no-color => color}/ann_insertion.svg (100%) rename tests/fixtures/{no-color => color}/ann_insertion.toml (100%) rename tests/fixtures/{no-color => color}/ann_multiline.svg (100%) rename tests/fixtures/{no-color => color}/ann_multiline.toml (100%) rename tests/fixtures/{no-color => color}/ann_multiline2.svg (100%) rename tests/fixtures/{no-color => color}/ann_multiline2.toml (100%) rename tests/fixtures/{no-color => color}/ann_removed_nl.svg (100%) rename tests/fixtures/{no-color => color}/ann_removed_nl.toml (100%) rename tests/fixtures/{no-color => color}/ensure-emoji-highlight-width.svg (100%) rename tests/fixtures/{no-color => color}/ensure-emoji-highlight-width.toml (100%) rename tests/fixtures/{no-color => color}/fold_ann_multiline.svg (100%) rename tests/fixtures/{no-color => color}/fold_ann_multiline.toml (100%) rename tests/fixtures/{no-color => color}/fold_bad_origin_line.svg (100%) rename tests/fixtures/{no-color => color}/fold_bad_origin_line.toml (100%) rename tests/fixtures/{no-color => color}/fold_leading.svg (100%) rename tests/fixtures/{no-color => color}/fold_leading.toml (100%) rename tests/fixtures/{no-color => color}/fold_trailing.svg (100%) rename tests/fixtures/{no-color => color}/fold_trailing.toml (100%) rename tests/fixtures/{no-color => color}/issue_9.svg (100%) rename tests/fixtures/{no-color => color}/issue_9.toml (100%) rename tests/fixtures/{no-color => color}/multiple_annotations.svg (100%) rename tests/fixtures/{no-color => color}/multiple_annotations.toml (100%) rename tests/fixtures/{no-color => color}/simple.svg (100%) rename tests/fixtures/{no-color => color}/simple.toml (100%) rename tests/fixtures/{no-color => color}/strip_line.svg (100%) rename tests/fixtures/{no-color => color}/strip_line.toml (100%) rename tests/fixtures/{no-color => color}/strip_line_char.svg (100%) rename tests/fixtures/{no-color => color}/strip_line_char.toml (100%) rename tests/fixtures/{no-color => color}/strip_line_non_ws.svg (100%) rename tests/fixtures/{no-color => color}/strip_line_non_ws.toml (100%) diff --git a/tests/fixtures/no-color/ann_eof.svg b/tests/fixtures/color/ann_eof.svg similarity index 100% rename from tests/fixtures/no-color/ann_eof.svg rename to tests/fixtures/color/ann_eof.svg diff --git a/tests/fixtures/no-color/ann_eof.toml b/tests/fixtures/color/ann_eof.toml similarity index 100% rename from tests/fixtures/no-color/ann_eof.toml rename to tests/fixtures/color/ann_eof.toml diff --git a/tests/fixtures/no-color/ann_insertion.svg b/tests/fixtures/color/ann_insertion.svg similarity index 100% rename from tests/fixtures/no-color/ann_insertion.svg rename to tests/fixtures/color/ann_insertion.svg diff --git a/tests/fixtures/no-color/ann_insertion.toml b/tests/fixtures/color/ann_insertion.toml similarity index 100% rename from tests/fixtures/no-color/ann_insertion.toml rename to tests/fixtures/color/ann_insertion.toml diff --git a/tests/fixtures/no-color/ann_multiline.svg b/tests/fixtures/color/ann_multiline.svg similarity index 100% rename from tests/fixtures/no-color/ann_multiline.svg rename to tests/fixtures/color/ann_multiline.svg diff --git a/tests/fixtures/no-color/ann_multiline.toml b/tests/fixtures/color/ann_multiline.toml similarity index 100% rename from tests/fixtures/no-color/ann_multiline.toml rename to tests/fixtures/color/ann_multiline.toml diff --git a/tests/fixtures/no-color/ann_multiline2.svg b/tests/fixtures/color/ann_multiline2.svg similarity index 100% rename from tests/fixtures/no-color/ann_multiline2.svg rename to tests/fixtures/color/ann_multiline2.svg diff --git a/tests/fixtures/no-color/ann_multiline2.toml b/tests/fixtures/color/ann_multiline2.toml similarity index 100% rename from tests/fixtures/no-color/ann_multiline2.toml rename to tests/fixtures/color/ann_multiline2.toml diff --git a/tests/fixtures/no-color/ann_removed_nl.svg b/tests/fixtures/color/ann_removed_nl.svg similarity index 100% rename from tests/fixtures/no-color/ann_removed_nl.svg rename to tests/fixtures/color/ann_removed_nl.svg diff --git a/tests/fixtures/no-color/ann_removed_nl.toml b/tests/fixtures/color/ann_removed_nl.toml similarity index 100% rename from tests/fixtures/no-color/ann_removed_nl.toml rename to tests/fixtures/color/ann_removed_nl.toml diff --git a/tests/fixtures/no-color/ensure-emoji-highlight-width.svg b/tests/fixtures/color/ensure-emoji-highlight-width.svg similarity index 100% rename from tests/fixtures/no-color/ensure-emoji-highlight-width.svg rename to tests/fixtures/color/ensure-emoji-highlight-width.svg diff --git a/tests/fixtures/no-color/ensure-emoji-highlight-width.toml b/tests/fixtures/color/ensure-emoji-highlight-width.toml similarity index 100% rename from tests/fixtures/no-color/ensure-emoji-highlight-width.toml rename to tests/fixtures/color/ensure-emoji-highlight-width.toml diff --git a/tests/fixtures/no-color/fold_ann_multiline.svg b/tests/fixtures/color/fold_ann_multiline.svg similarity index 100% rename from tests/fixtures/no-color/fold_ann_multiline.svg rename to tests/fixtures/color/fold_ann_multiline.svg diff --git a/tests/fixtures/no-color/fold_ann_multiline.toml b/tests/fixtures/color/fold_ann_multiline.toml similarity index 100% rename from tests/fixtures/no-color/fold_ann_multiline.toml rename to tests/fixtures/color/fold_ann_multiline.toml diff --git a/tests/fixtures/no-color/fold_bad_origin_line.svg b/tests/fixtures/color/fold_bad_origin_line.svg similarity index 100% rename from tests/fixtures/no-color/fold_bad_origin_line.svg rename to tests/fixtures/color/fold_bad_origin_line.svg diff --git a/tests/fixtures/no-color/fold_bad_origin_line.toml b/tests/fixtures/color/fold_bad_origin_line.toml similarity index 100% rename from tests/fixtures/no-color/fold_bad_origin_line.toml rename to tests/fixtures/color/fold_bad_origin_line.toml diff --git a/tests/fixtures/no-color/fold_leading.svg b/tests/fixtures/color/fold_leading.svg similarity index 100% rename from tests/fixtures/no-color/fold_leading.svg rename to tests/fixtures/color/fold_leading.svg diff --git a/tests/fixtures/no-color/fold_leading.toml b/tests/fixtures/color/fold_leading.toml similarity index 100% rename from tests/fixtures/no-color/fold_leading.toml rename to tests/fixtures/color/fold_leading.toml diff --git a/tests/fixtures/no-color/fold_trailing.svg b/tests/fixtures/color/fold_trailing.svg similarity index 100% rename from tests/fixtures/no-color/fold_trailing.svg rename to tests/fixtures/color/fold_trailing.svg diff --git a/tests/fixtures/no-color/fold_trailing.toml b/tests/fixtures/color/fold_trailing.toml similarity index 100% rename from tests/fixtures/no-color/fold_trailing.toml rename to tests/fixtures/color/fold_trailing.toml diff --git a/tests/fixtures/no-color/issue_9.svg b/tests/fixtures/color/issue_9.svg similarity index 100% rename from tests/fixtures/no-color/issue_9.svg rename to tests/fixtures/color/issue_9.svg diff --git a/tests/fixtures/no-color/issue_9.toml b/tests/fixtures/color/issue_9.toml similarity index 100% rename from tests/fixtures/no-color/issue_9.toml rename to tests/fixtures/color/issue_9.toml diff --git a/tests/fixtures/no-color/multiple_annotations.svg b/tests/fixtures/color/multiple_annotations.svg similarity index 100% rename from tests/fixtures/no-color/multiple_annotations.svg rename to tests/fixtures/color/multiple_annotations.svg diff --git a/tests/fixtures/no-color/multiple_annotations.toml b/tests/fixtures/color/multiple_annotations.toml similarity index 100% rename from tests/fixtures/no-color/multiple_annotations.toml rename to tests/fixtures/color/multiple_annotations.toml diff --git a/tests/fixtures/no-color/simple.svg b/tests/fixtures/color/simple.svg similarity index 100% rename from tests/fixtures/no-color/simple.svg rename to tests/fixtures/color/simple.svg diff --git a/tests/fixtures/no-color/simple.toml b/tests/fixtures/color/simple.toml similarity index 100% rename from tests/fixtures/no-color/simple.toml rename to tests/fixtures/color/simple.toml diff --git a/tests/fixtures/no-color/strip_line.svg b/tests/fixtures/color/strip_line.svg similarity index 100% rename from tests/fixtures/no-color/strip_line.svg rename to tests/fixtures/color/strip_line.svg diff --git a/tests/fixtures/no-color/strip_line.toml b/tests/fixtures/color/strip_line.toml similarity index 100% rename from tests/fixtures/no-color/strip_line.toml rename to tests/fixtures/color/strip_line.toml diff --git a/tests/fixtures/no-color/strip_line_char.svg b/tests/fixtures/color/strip_line_char.svg similarity index 100% rename from tests/fixtures/no-color/strip_line_char.svg rename to tests/fixtures/color/strip_line_char.svg diff --git a/tests/fixtures/no-color/strip_line_char.toml b/tests/fixtures/color/strip_line_char.toml similarity index 100% rename from tests/fixtures/no-color/strip_line_char.toml rename to tests/fixtures/color/strip_line_char.toml diff --git a/tests/fixtures/no-color/strip_line_non_ws.svg b/tests/fixtures/color/strip_line_non_ws.svg similarity index 100% rename from tests/fixtures/no-color/strip_line_non_ws.svg rename to tests/fixtures/color/strip_line_non_ws.svg diff --git a/tests/fixtures/no-color/strip_line_non_ws.toml b/tests/fixtures/color/strip_line_non_ws.toml similarity index 100% rename from tests/fixtures/no-color/strip_line_non_ws.toml rename to tests/fixtures/color/strip_line_non_ws.toml From a059969c14e8c10fa1799a9f8e073699cd438ade Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Wed, 21 Aug 2024 15:02:49 -0600 Subject: [PATCH 097/175] test: Make all color tests have color --- tests/fixtures/color/ann_eof.svg | 15 +++++---- tests/fixtures/color/ann_eof.toml | 3 ++ tests/fixtures/color/ann_insertion.svg | 15 +++++---- tests/fixtures/color/ann_insertion.toml | 3 ++ tests/fixtures/color/ann_multiline.svg | 21 +++++++----- tests/fixtures/color/ann_multiline.toml | 3 ++ tests/fixtures/color/ann_multiline2.svg | 19 ++++++----- tests/fixtures/color/ann_multiline2.toml | 3 ++ tests/fixtures/color/ann_removed_nl.svg | 15 +++++---- tests/fixtures/color/ann_removed_nl.toml | 3 ++ .../color/ensure-emoji-highlight-width.svg | 15 +++++---- .../color/ensure-emoji-highlight-width.toml | 3 ++ tests/fixtures/color/fold_ann_multiline.svg | 28 +++++++++------- tests/fixtures/color/fold_ann_multiline.toml | 3 ++ tests/fixtures/color/fold_bad_origin_line.svg | 16 +++++---- .../fixtures/color/fold_bad_origin_line.toml | 3 ++ tests/fixtures/color/fold_leading.svg | 15 +++++---- tests/fixtures/color/fold_leading.toml | 3 ++ tests/fixtures/color/fold_trailing.svg | 15 +++++---- tests/fixtures/color/fold_trailing.toml | 3 ++ tests/fixtures/color/issue_9.svg | 28 +++++++++------- tests/fixtures/color/issue_9.toml | 3 ++ tests/fixtures/color/multiple_annotations.svg | 33 ++++++++++--------- .../fixtures/color/multiple_annotations.toml | 3 ++ tests/fixtures/color/simple.svg | 22 ++++++++----- tests/fixtures/color/simple.toml | 3 ++ tests/fixtures/color/strip_line.svg | 15 +++++---- tests/fixtures/color/strip_line.toml | 2 +- tests/fixtures/color/strip_line_char.svg | 15 +++++---- tests/fixtures/color/strip_line_char.toml | 2 +- tests/fixtures/color/strip_line_non_ws.svg | 19 ++++++----- tests/fixtures/color/strip_line_non_ws.toml | 1 + tests/fixtures/deserialize.rs | 11 ++++++- 33 files changed, 231 insertions(+), 130 deletions(-) diff --git a/tests/fixtures/color/ann_eof.svg b/tests/fixtures/color/ann_eof.svg index c8900d0..bb12aec 100644 --- a/tests/fixtures/color/ann_eof.svg +++ b/tests/fixtures/color/ann_eof.svg @@ -2,10 +2,13 @@ + + + + + error[E0010]: allocations are not allowed in constants + + --> $DIR/E0010-teach.rs:5:23 + + | + + LL | const CON: Vec<i32> = vec![1, 2, 3]; //~ ERROR E0010 + + | ^^^^^^^^^^^^^ allocation not allowed in constants + + = note: The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created. + + + + + + diff --git a/tests/examples.rs b/tests/examples.rs index b657662..7708732 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -19,6 +19,13 @@ fn format() { assert_example(target, expected); } +#[test] +fn highlight_source() { + let target = "highlight_source"; + let expected = snapbox::file!["../examples/highlight_source.svg": TermSvg]; + assert_example(target, expected); +} + #[test] fn multislice() { let target = "multislice"; From 222c013d9cb828d1171b26811e4530dc8cb6e068 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Sun, 9 Mar 2025 05:03:55 -0600 Subject: [PATCH 156/175] feat: Add ability to highlight source code --- examples/highlight_source.rs | 1 + examples/highlight_source.svg | 2 +- src/renderer/mod.rs | 12 ++++++++++++ src/renderer/source_map.rs | 14 +++++++++++++- src/snippet.rs | 7 +++++++ 5 files changed, 34 insertions(+), 2 deletions(-) diff --git a/examples/highlight_source.rs b/examples/highlight_source.rs index d49ff76..2bb4ec2 100644 --- a/examples/highlight_source.rs +++ b/examples/highlight_source.rs @@ -22,6 +22,7 @@ fn main() {} AnnotationKind::Primary .span(72..85) .label("allocation not allowed in constants") + .highlight_source(true), ), ) .element( diff --git a/examples/highlight_source.svg b/examples/highlight_source.svg index b6f9e82..391a097 100644 --- a/examples/highlight_source.svg +++ b/examples/highlight_source.svg @@ -25,7 +25,7 @@ | - LL | const CON: Vec<i32> = vec![1, 2, 3]; //~ ERROR E0010 + LL | const CON: Vec<i32> = vec![1, 2, 3]; //~ ERROR E0010 | ^^^^^^^^^^^^^ allocation not allowed in constants diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 85de0f5..10f2b59 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -1260,6 +1260,15 @@ impl Renderer { underline.style, ); } + _ if annotation.highlight_source => { + buffer.set_style_range( + line_offset, + (code_offset + annotation.start.display).saturating_sub(left), + (code_offset + annotation.end.display).saturating_sub(left), + underline.style, + annotation.is_primary(), + ); + } _ => {} } } @@ -2471,6 +2480,9 @@ pub(crate) struct LineAnnotation<'a> { /// Is this a single line, multiline or multiline span minimized down to a /// smaller span. pub annotation_type: LineAnnotationType, + + /// Whether the source code should be highlighted + pub highlight_source: bool, } impl LineAnnotation<'_> { diff --git a/src/renderer/source_map.rs b/src/renderer/source_map.rs index 416337c..33fe189 100644 --- a/src/renderer/source_map.rs +++ b/src/renderer/source_map.rs @@ -149,7 +149,13 @@ impl<'a> SourceMap<'a> { .collect::>(); let mut multiline_annotations = vec![]; - for Annotation { range, label, kind } in annotations { + for Annotation { + range, + label, + kind, + highlight_source, + } in annotations + { let (lo, mut hi) = self.span_to_locations(range.clone()); // Watch out for "empty spans". If we get a span like 6..6, we @@ -169,6 +175,7 @@ impl<'a> SourceMap<'a> { kind, label, annotation_type: LineAnnotationType::Singleline, + highlight_source, }; self.add_annotation_to_file(&mut annotated_line_infos, lo.line, line_ann); } else { @@ -179,6 +186,7 @@ impl<'a> SourceMap<'a> { kind, label, overlaps_exactly: false, + highlight_source, }); } } @@ -502,6 +510,7 @@ pub(crate) struct MultilineAnnotation<'a> { pub kind: AnnotationKind, pub label: Option<&'a str>, pub overlaps_exactly: bool, + pub highlight_source: bool, } impl<'a> MultilineAnnotation<'a> { @@ -526,6 +535,7 @@ impl<'a> MultilineAnnotation<'a> { kind: self.kind, label: None, annotation_type: LineAnnotationType::MultilineStart(self.depth), + highlight_source: self.highlight_source, } } @@ -541,6 +551,7 @@ impl<'a> MultilineAnnotation<'a> { kind: self.kind, label: self.label, annotation_type: LineAnnotationType::MultilineEnd(self.depth), + highlight_source: self.highlight_source, } } @@ -551,6 +562,7 @@ impl<'a> MultilineAnnotation<'a> { kind: self.kind, label: None, annotation_type: LineAnnotationType::MultilineLine(self.depth), + highlight_source: self.highlight_source, } } } diff --git a/src/snippet.rs b/src/snippet.rs index d371ab8..6400284 100644 --- a/src/snippet.rs +++ b/src/snippet.rs @@ -273,6 +273,7 @@ pub struct Annotation<'a> { pub(crate) range: Range, pub(crate) label: Option<&'a str>, pub(crate) kind: AnnotationKind, + pub(crate) highlight_source: bool, } impl<'a> Annotation<'a> { @@ -280,6 +281,11 @@ impl<'a> Annotation<'a> { self.label = Some(label); self } + + pub fn highlight_source(mut self, highlight_source: bool) -> Self { + self.highlight_source = highlight_source; + self + } } #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] @@ -296,6 +302,7 @@ impl AnnotationKind { range: span, label: None, kind: self, + highlight_source: false, } } From 481920d56fd1b573dfac210ab32bd255b8f2ad84 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Tue, 15 Apr 2025 22:11:46 -0600 Subject: [PATCH 157/175] test: Add a test for passing precolored text --- examples/highlight_title.rs | 68 ++++++++++++++++++++++++++++++++++++ examples/highlight_title.svg | 44 +++++++++++++++++++++++ tests/examples.rs | 7 ++++ 3 files changed, 119 insertions(+) create mode 100644 examples/highlight_title.rs create mode 100644 examples/highlight_title.svg diff --git a/examples/highlight_title.rs b/examples/highlight_title.rs new file mode 100644 index 0000000..bb09049 --- /dev/null +++ b/examples/highlight_title.rs @@ -0,0 +1,68 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; +use anstyle::Effects; + +fn main() { + let source = r#"// Make sure "highlighted" code is colored purple + +//@ compile-flags: --error-format=human --color=always +//@ error-pattern:for<'a>  +//@ edition:2018 + +use core::pin::Pin; +use core::future::Future; +use core::any::Any; + +fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin, String>> + Send + 'static +)>>) {} + +fn wrapped_fn<'a>(_: Box<(dyn Any + Send)>) -> Pin, String>> + Send + 'static +)>> { + Box::pin(async { Err("nope".into()) }) +} + +fn main() { + query(wrapped_fn); +} +"#; + + let magenta = annotate_snippets::renderer::AnsiColor::Magenta + .on_default() + .effects(Effects::BOLD); + let title = format!( + "expected fn pointer `{}for<'a>{} fn(Box<{}(dyn Any + Send + 'a){}>) -> Pin<_>` + found fn item `fn(Box<{}(dyn Any + Send + 'static){}>) -> Pin<_> {}{{wrapped_fn}}{}`", + magenta.render(), + magenta.render_reset(), + magenta.render(), + magenta.render_reset(), + magenta.render(), + magenta.render_reset(), + magenta.render(), + magenta.render_reset() + ); + + let message = Level::Error.message("mismatched types").id("E0308").group( + Group::new() + .element( + Snippet::source(source) + .fold(true) + .origin("$DIR/highlighting.rs") + .annotation( + AnnotationKind::Primary + .span(589..599) + .label("one type is more general than the other"), + ) + .annotation( + AnnotationKind::Context + .span(583..588) + .label("arguments to this function are incorrect"), + ), + ) + .element(Level::Note.title(&title)), + ); + + let renderer = Renderer::styled().anonymized_line_numbers(true); + anstream::println!("{}", renderer.render(message)); +} diff --git a/examples/highlight_title.svg b/examples/highlight_title.svg new file mode 100644 index 0000000..763d33b --- /dev/null +++ b/examples/highlight_title.svg @@ -0,0 +1,44 @@ + + + + + + + error[E0308]: mismatched types + + --> $DIR/highlighting.rs:22:11 + + | + + LL | query(wrapped_fn); + + | ----- ^^^^^^^^^^ one type is more general than the other + + | | + + | arguments to this function are incorrect + + = note: expected fn pointer `␛[1m␛[35mfor<'a>␛[0m fn(Box<␛[1m␛[35m(dyn Any + Send + 'a)␛[0m>) -> Pin<_>` + + found fn item `fn(Box<␛[1m␛[35m(dyn Any + Send + 'static)␛[0m>) -> Pin<_> ␛[1m␛[35m{wrapped_fn}␛[0m` + + + + + + diff --git a/tests/examples.rs b/tests/examples.rs index 7708732..a0504c1 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -26,6 +26,13 @@ fn highlight_source() { assert_example(target, expected); } +#[test] +fn highlight_title() { + let target = "highlight_title"; + let expected = snapbox::file!["../examples/highlight_title.svg": TermSvg]; + assert_example(target, expected); +} + #[test] fn multislice() { let target = "multislice"; From 19f692d1f9b6c3e089556af2cd29811dfe9795cb Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Wed, 16 Apr 2025 09:56:43 -0600 Subject: [PATCH 158/175] feat: Don't normailze title text --- examples/highlight_title.svg | 7 ++++--- src/lib.rs | 7 +++++++ src/renderer/mod.rs | 7 +++---- src/snippet.rs | 4 ++++ 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/examples/highlight_title.svg b/examples/highlight_title.svg index 763d33b..ad35876 100644 --- a/examples/highlight_title.svg +++ b/examples/highlight_title.svg @@ -1,9 +1,10 @@ - + | arguments to this function are incorrect - = note: expected fn pointer `␛[1m␛[35mfor<'a>␛[0m fn(Box<␛[1m␛[35m(dyn Any + Send + 'a)␛[0m>) -> Pin<_>` + = note: expected fn pointer `for<'a> fn(Box<(dyn Any + Send + 'a)>) -> Pin<_>` - found fn item `fn(Box<␛[1m␛[35m(dyn Any + Send + 'static)␛[0m>) -> Pin<_> ␛[1m␛[35m{wrapped_fn}␛[0m` + found fn item `fn(Box<(dyn Any + Send + 'static)>) -> Pin<_> {wrapped_fn}` diff --git a/src/lib.rs b/src/lib.rs index 533e8f7..e6c49c6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,6 +45,13 @@ pub mod renderer; mod snippet; +/// Normalize the string to avoid any unicode control characters. +/// This is important for untrusted input, as it can contain +/// invalid unicode sequences. +pub fn normalize_untrusted_str(s: &str) -> String { + renderer::normalize_whitespace(s) +} + #[doc(inline)] pub use renderer::Renderer; pub use snippet::ColumnSeparator; diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 10f2b59..ab3db82 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -573,8 +573,7 @@ impl Renderer { } else { ElementStyle::NoStyle }; - let text = &normalize_whitespace(title); - let lines = text.split('\n').collect::>(); + let lines = title.split('\n').collect::>(); if lines.len() > 1 { for (i, line) in lines.iter().enumerate() { if i != 0 { @@ -584,7 +583,7 @@ impl Renderer { buffer.append(line_number, line, style); } } else { - buffer.append(line_number, text, style); + buffer.append(line_number, title, style); } line_number } @@ -2590,7 +2589,7 @@ const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ ('\u{2069}', "�"), ]; -fn normalize_whitespace(s: &str) -> String { +pub(crate) fn normalize_whitespace(s: &str) -> String { // Scan the input string for a character in the ordered table above. // If it's present, replace it with its alternative string (it can be more than 1 char!). // Otherwise, retain the input char. diff --git a/src/snippet.rs b/src/snippet.rs index 6400284..f71c392 100644 --- a/src/snippet.rs +++ b/src/snippet.rs @@ -177,6 +177,10 @@ impl Level { } } + /// Text passed to this function is allowed to be pre-styled, as such all + /// text is considered "trusted input" and has no normalizations applied to + /// it. [`normalize_untrusted_str`](crate::normalize_untrusted_str) can be + /// used to normalize untrusted text before it is passed to this function. pub fn title(self, title: &str) -> Title<'_> { Title { level: self, From b4373f3effd8a0899c496393f87eb6802d546f23 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Wed, 16 Apr 2025 10:02:22 -0600 Subject: [PATCH 159/175] docs: Add when text is normalized --- src/snippet.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/snippet.rs b/src/snippet.rs index f71c392..e8fa18c 100644 --- a/src/snippet.rs +++ b/src/snippet.rs @@ -166,6 +166,9 @@ pub enum Level { } impl Level { + /// Text passed to this function is considered "untrusted input", as such + /// all text is passed through a normalization function. Pre-styled text is + /// not allowed to be passed to this function. pub fn message(self, title: &str) -> Message<'_> { Message { id: None, @@ -222,6 +225,9 @@ pub struct Snippet<'a, T> { } impl<'a, T: Clone> Snippet<'a, T> { + /// Text passed to this function is considered "untrusted input", as such + /// all text is passed through a normalization function. Pre-styled text is + /// not allowed to be passed to this function. pub fn source(source: &'a str) -> Self { Self { origin: None, @@ -237,6 +243,9 @@ impl<'a, T: Clone> Snippet<'a, T> { self } + /// Text passed to this function is considered "untrusted input", as such + /// all text is passed through a normalization function. Pre-styled text is + /// not allowed to be passed to this function. pub fn origin(mut self, origin: &'a str) -> Self { self.origin = Some(origin); self @@ -281,6 +290,9 @@ pub struct Annotation<'a> { } impl<'a> Annotation<'a> { + /// Text passed to this function is considered "untrusted input", as such + /// all text is passed through a normalization function. Pre-styled text is + /// not allowed to be passed to this function. pub fn label(mut self, label: &'a str) -> Self { self.label = Some(label); self @@ -322,6 +334,9 @@ pub struct Patch<'a> { } impl<'a> Patch<'a> { + /// Text passed to this function is considered "untrusted input", as such + /// all text is passed through a normalization function. Pre-styled text is + /// not allowed to be passed to this function. pub fn new(range: Range, replacement: &'a str) -> Self { Self { range, replacement } } @@ -384,6 +399,9 @@ pub struct Origin<'a> { } impl<'a> Origin<'a> { + /// Text passed to this function is considered "untrusted input", as such + /// all text is passed through a normalization function. Pre-styled text is + /// not allowed to be passed to this function. pub fn new(origin: &'a str) -> Self { Self { origin, @@ -409,6 +427,9 @@ impl<'a> Origin<'a> { self } + /// Text passed to this function is considered "untrusted input", as such + /// all text is passed through a normalization function. Pre-styled text is + /// not allowed to be passed to this function. pub fn label(mut self, label: &'a str) -> Self { self.label = Some(label); self From 15fbf20cbc84c822378fa5b5cf8d33dd9aeb9e59 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Sat, 29 Mar 2025 22:31:44 -0600 Subject: [PATCH 160/175] test: Add tests margin cutting --- tests/formatter.rs | 273 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) diff --git a/tests/formatter.rs b/tests/formatter.rs index 6304cf4..df6f965 100644 --- a/tests/formatter.rs +++ b/tests/formatter.rs @@ -2112,3 +2112,276 @@ LL │ ┃ )>>) {} .anonymized_line_numbers(true); assert_data_eq!(renderer.render(input_new), expected); } + +// This tests that an ellipsis is not inserted into Unicode text when a line +// wasn't actually trimmed. +// +// This is a regression test where `...` was inserted because the code wasn't +// properly accounting for the *rendered* length versus the length in bytes in +// all cases. +#[test] +fn unicode_cut_handling() { + let source = "version = \"0.1.0\"\n# Ensure that the spans from toml handle utf-8 correctly\nauthors = [\n { name = \"Z\u{351}\u{36b}\u{343}\u{36a}\u{302}\u{36b}\u{33d}\u{34f}\u{334}\u{319}\u{324}\u{31e}\u{349}\u{35a}\u{32f}\u{31e}\u{320}\u{34d}A\u{36b}\u{357}\u{334}\u{362}\u{335}\u{31c}\u{330}\u{354}L\u{368}\u{367}\u{369}\u{358}\u{320}G\u{311}\u{357}\u{30e}\u{305}\u{35b}\u{341}\u{334}\u{33b}\u{348}\u{34d}\u{354}\u{339}O\u{342}\u{30c}\u{30c}\u{358}\u{328}\u{335}\u{339}\u{33b}\u{31d}\u{333}\", email = 1 }\n]\n"; + let input = Level::Error.message("title").group( + Group::new().element( + Snippet::source(source) + .fold(false) + .annotation(AnnotationKind::Primary.span(85..228).label("annotation")), + ), + ); + let expected = str![[r#" +error: title + | +1 | version = "0.1.0" +2 | # Ensure that the spans from toml handle utf-8 correctly +3 | authors = [ + | ___________^ +4 | | { name = "Z͑ͫ̓ͪ̂ͫ̽͏̴̙̤̞͉͚̯...A̴̵̜̰͔ͫ͗͢L̠ͨͧͩ͘G̴̻͈͍͔̹̑͗̎̅͛́Ǫ̵̹̻̝̳͂̌̌͘", email = 1 } +5 | | ] + | |_^ annotation +"#]]; + let renderer = Renderer::plain(); + assert_data_eq!(renderer.render(input), expected); +} + +#[test] +fn unicode_cut_handling2() { + let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?"; + let input = Level::Error + .message("expected item, found `?`") + .group( + Group::new().element( + Snippet::source(source) + .fold(false) + .annotation(AnnotationKind::Primary.span(499..500).label("expected item")) + ).element( + Level::Note.title("for a full list of items that can appear in modules, see ") + ) + ); + + let expected = str![[r#" +error: expected item, found `?` + | +1.|.... + |^ expected item + = note: for a full list of items that can appear in modules, see +"#]]; + + let renderer = Renderer::plain(); + assert_data_eq!(renderer.render(input), expected); +} + +#[test] +fn unicode_cut_handling3() { + let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?"; + let input = Level::Error + .message("expected item, found `?`") + .group( + Group::new().element( + Snippet::source(source) + .fold(false) + .annotation(AnnotationKind::Primary.span(251..254).label("expected item")) + ).element( + Level::Note.title("for a full list of items that can appear in modules, see ") + ) + ); + + let expected = str![[r#" +error: expected item, found `?` + | +1 | ...的。这是宽的。*/? ... +^ | expected item + = note: for a full list of items that can appear in modules, see +"#]]; + + let renderer = Renderer::plain().term_width(43); + assert_data_eq!(renderer.render(input), expected); +} + +#[test] +fn unicode_cut_handling4() { + let source = "/*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/?"; + let input = Level::Error + .message("expected item, found `?`") + .group( + Group::new().element( + Snippet::source(source) + .fold(false) + .annotation(AnnotationKind::Primary.span(334..335).label("expected item")) + ).element( + Level::Note.title("for a full list of items that can appear in modules, see ") + ) + ); + + let expected = str![[r#" +error: expected item, found `?` + | +1 | ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/? + | ^ expected item + = note: for a full list of items that can appear in modules, see +"#]]; + + let renderer = Renderer::plain(); + assert_data_eq!(renderer.render(input), expected); +} + +#[test] +fn diagnostic_width() { + let source = r##"// ignore-tidy-linelength + +fn main() { + let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀🦀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀🦀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; +//~^ ERROR mismatched types +} +"##; + let input = Level::Error.message("mismatched types").id("E0308").group( + Group::new().element( + Snippet::source(source) + .origin("$DIR/non-whitespace-trimming-unicode.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(1207..1209) + .label("expected `()`, found integer"), + ) + .annotation( + AnnotationKind::Context + .span(1202..1204) + .label("expected due to this"), + ), + ), + ); + + let expected = str![[r#" +error[E0308]: mismatched types + --> $DIR/non-whitespace-trimming-unicode.rs:4:415 + | +LL | ...♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂... + | -- ^^ expected `()`, found integer + | | + | expected due to this +"#]]; + + let renderer = Renderer::plain().anonymized_line_numbers(true); + assert_data_eq!(renderer.render(input), expected); +} + +#[test] +fn diagnostic_width2() { + let source = r##"//@ revisions: ascii unicode +//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode +// ignore-tidy-linelength + +fn main() { + let unicode_is_fun = "؁‱ஹ௸௵꧄.ဪ꧅⸻𒈙𒐫﷽𒌄𒈟𒍼𒁎𒀱𒌧𒅃 𒈓𒍙𒊎𒄡𒅌𒁏𒀰𒐪𒐩𒈙𒐫𪚥"; + let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; + //[ascii]~^ ERROR cannot add `&str` to `&str` +} +"##; + let input = Level::Error + .message("cannot add `&str` to `&str`") + .id("E0369") + .group( + Group::new() + .element( + Snippet::source(source) + .origin("$DIR/non-1-width-unicode-multiline-label.rs") + .fold(true) + .annotation(AnnotationKind::Context.span(970..984).label("&str")) + .annotation(AnnotationKind::Context.span(987..1001).label("&str")) + .annotation( + AnnotationKind::Primary + .span(985..986) + .label("`+` cannot be used to concatenate two `&str` strings"), + ), + ) + .element( + Level::Note + .title("string concatenation requires an owned `String` on the left"), + ), + ) + .group( + Group::new() + .element(Level::Help.title("create an owned `String` from a string reference")) + .element( + Snippet::source(source) + .origin("$DIR/non-1-width-unicode-multiline-label.rs") + .fold(true) + .patch(Patch::new(984..984, ".to_owned()")), + ), + ); + + let expected = str![[r#" +error[E0369]: cannot add `&str` to `&str` + ╭▸ $DIR/non-1-width-unicode-multiline-label.rs:7:260 + │ +LL │ …ཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋…࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; + │ ┬───────────── ┯ ────────────── &str + │ │ │ + │ │ `+` cannot be used to concatenate two `&str` strings + │ &str + │ + ╰ note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + ╭╴ +LL │ let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!"; + ╰╴ +++++++++++ +"#]]; + + let renderer = Renderer::plain() + .anonymized_line_numbers(true) + .theme(OutputTheme::Unicode); + assert_data_eq!(renderer.render(input), expected); +} + +#[test] +fn macros_not_utf8() { + let source = r##"//@ error-pattern: did not contain valid UTF-8 +//@ reference: input.encoding.utf8 +//@ reference: input.encoding.invalid + +fn foo() { + include!("not-utf8.bin"); +} +"##; + let bin_source = "�|�\u{0002}!5�cc\u{0015}\u{0002}�Ӻi��WWj�ȥ�'�}�\u{0012}�J�ȉ��W�\u{001e}O�@����\u{001c}w�V���LO����\u{0014}[ \u{0003}_�'���SQ�~ذ��ų&��-\t��lN~��!@␌ _#���kQ��h�\u{001d}�:�\u{001c}\u{0007}�"; + let input = Level::Error + .message("couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8") + .group( + Group::new().element( + Snippet::source(source) + .origin("$DIR/not-utf8.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(136..160)), + ), + ) + .group( + Group::new() + .element(Level::Note.title("byte `193` is not valid utf-8")) + .element( + Snippet::source(bin_source) + .origin("$DIR/not-utf8.bin") + .fold(true) + .annotation(AnnotationKind::Primary.span(0..0)), + ) + .element(Level::Note.title("this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info)")), + ); + + let expected = str![[r#" +error: couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8 + --> $DIR/not-utf8.rs:6:5 + | +LL | include!("not-utf8.bin"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: byte `193` is not valid utf-8 + --> $DIR/not-utf8.bin:1:1 + | +LL | �|�␂!5�cc␕␂�Ӻi��WWj�ȥ�'�}�␒�J�ȉ��W�␞O�@����␜w�V���LO����␔[ ␃_�'���SQ�~ذ��ų&��- ��lN~��!@␌ _#���kQ��h�␝�:�... + | ^ + = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) +"#]]; + + let renderer = Renderer::plain().anonymized_line_numbers(true); + assert_data_eq!(renderer.render(input), expected); +} From 604b6f95a979ef1b2273d3e13d96907638f1f585 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Sat, 29 Mar 2025 22:31:44 -0600 Subject: [PATCH 161/175] fix: Handle margin cutting when encountering multibyte chars --- src/renderer/mod.rs | 72 +++++++++++++++++++++++++++++++++++---------- tests/formatter.rs | 30 +++++++++---------- 2 files changed, 71 insertions(+), 31 deletions(-) diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index ab3db82..7d4fd0f 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -956,12 +956,19 @@ impl Renderer { let line_offset = buffer.num_lines(); // Left trim - let left = margin.left(source_string.len()); + let left = margin.left(str_width(&source_string)); // FIXME: This looks fishy. See #132860. // Account for unicode characters of width !=0 that were removed. - let left = source_string.chars().take(left).map(char_width).sum(); + let mut taken = 0; + source_string.chars().for_each(|ch| { + let next = char_width(ch); + if taken + next <= left { + taken += next; + } + }); + let left = taken; self.draw_line( buffer, &source_string, @@ -2020,48 +2027,81 @@ impl Renderer { ) { // Tabs are assumed to have been replaced by spaces in calling code. debug_assert!(!source_string.contains('\t')); - let line_len = source_string.len(); + let line_len = str_width(source_string); // Create the source line we will highlight. let left = margin.left(line_len); let right = margin.right(line_len); // FIXME: The following code looks fishy. See #132860. // On long lines, we strip the source line, accounting for unicode. let mut taken = 0; + let mut skipped = 0; let code: String = source_string .chars() - .skip(left) + .skip_while(|ch| { + skipped += char_width(*ch); + skipped <= left + }) .take_while(|ch| { // Make sure that the trimming on the right will fall within the terminal width. - let next = char_width(*ch); - if taken + next > right - left { - return false; - } - taken += next; - true + taken += char_width(*ch); + taken <= (right - left) }) .collect(); buffer.puts(line_offset, code_offset, &code, ElementStyle::Quotation); let placeholder = self.margin(); - if margin.was_cut_left() { + let padding = str_width(placeholder); + let (width_taken, bytes_taken) = if margin.was_cut_left() { // We have stripped some code/whitespace from the beginning, make it clear. + let mut bytes_taken = 0; + let mut width_taken = 0; + for ch in code.chars() { + width_taken += char_width(ch); + bytes_taken += ch.len_utf8(); + + if width_taken >= padding { + break; + } + } buffer.puts( line_offset, code_offset, - placeholder, + &format!("{placeholder:>width_taken$}"), ElementStyle::LineNumber, ); - } + (width_taken, bytes_taken) + } else { + (0, 0) + }; + + buffer.puts( + line_offset, + code_offset + width_taken, + &code[bytes_taken..], + ElementStyle::Quotation, + ); + if margin.was_cut_right(line_len) { - let padding = str_width(placeholder); - // We have stripped some code after the rightmost span end, make it clear we did so. + // We have stripped some code/whitespace from the beginning, make it clear. + let mut char_taken = 0; + let mut width_taken_inner = 0; + for ch in code.chars().rev() { + width_taken_inner += char_width(ch); + char_taken += 1; + + if width_taken_inner >= padding { + break; + } + } + buffer.puts( line_offset, - code_offset + taken - padding, + code_offset + width_taken + code[bytes_taken..].chars().count() - char_taken, placeholder, ElementStyle::LineNumber, ); } + buffer.puts( line_offset, 0, diff --git a/tests/formatter.rs b/tests/formatter.rs index df6f965..5deb21a 100644 --- a/tests/formatter.rs +++ b/tests/formatter.rs @@ -2136,7 +2136,7 @@ error: title 2 | # Ensure that the spans from toml handle utf-8 correctly 3 | authors = [ | ___________^ -4 | | { name = "Z͑ͫ̓ͪ̂ͫ̽͏̴̙̤̞͉͚̯...A̴̵̜̰͔ͫ͗͢L̠ͨͧͩ͘G̴̻͈͍͔̹̑͗̎̅͛́Ǫ̵̹̻̝̳͂̌̌͘", email = 1 } +4 | | { name = "Z͑ͫ̓ͪ̂ͫ̽͏̴̙̤̞͉͚̯̞̠͍A̴̵̜̰͔ͫ͗͢L̠ͨͧͩ͘G̴̻͈͍͔̹̑͗̎̅͛́Ǫ̵̹̻̝̳͂̌̌͘", email = 1 } 5 | | ] | |_^ annotation "#]]; @@ -2162,8 +2162,8 @@ fn unicode_cut_handling2() { let expected = str![[r#" error: expected item, found `?` | -1.|.... - |^ expected item +1 | ...的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/? + | ^ expected item = note: for a full list of items that can appear in modules, see "#]]; @@ -2189,8 +2189,8 @@ fn unicode_cut_handling3() { let expected = str![[r#" error: expected item, found `?` | -1 | ...的。这是宽的。*/? ... -^ | expected item +1 | ...。这是宽的。这是宽的。这是宽的... + | ^^ expected item = note: for a full list of items that can appear in modules, see "#]]; @@ -2256,10 +2256,10 @@ fn main() { error[E0308]: mismatched types --> $DIR/non-whitespace-trimming-unicode.rs:4:415 | -LL | ...♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂... - | -- ^^ expected `()`, found integer - | | - | expected due to this +LL | ...♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷... + | -- ^^ expected `()`, found integer + | | + | expected due to this "#]]; let renderer = Renderer::plain().anonymized_line_numbers(true); @@ -2315,11 +2315,11 @@ fn main() { error[E0369]: cannot add `&str` to `&str` ╭▸ $DIR/non-1-width-unicode-multiline-label.rs:7:260 │ -LL │ …ཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋…࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; - │ ┬───────────── ┯ ────────────── &str - │ │ │ - │ │ `+` cannot be used to concatenate two `&str` strings - │ &str +LL │ …࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; + │ ┬───────────── ┯ ────────────── &str + │ │ │ + │ │ `+` cannot be used to concatenate two `&str` strings + │ &str │ ╰ note: string concatenation requires an owned `String` on the left help: create an owned `String` from a string reference @@ -2377,7 +2377,7 @@ LL | include!("not-utf8.bin"); note: byte `193` is not valid utf-8 --> $DIR/not-utf8.bin:1:1 | -LL | �|�␂!5�cc␕␂�Ӻi��WWj�ȥ�'�}�␒�J�ȉ��W�␞O�@����␜w�V���LO����␔[ ␃_�'���SQ�~ذ��ų&��- ��lN~��!@␌ _#���kQ��h�␝�:�... +LL | �|�␂!5�cc␕␂�Ӻi��WWj�ȥ�'�}�␒�J�ȉ��W�␞O�@����␜w�V���LO����␔[ ␃_�'���SQ�~ذ��ų&��- ��lN~��!@␌ _#���kQ��h�␝�:�␜␇� | ^ = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) "#]]; From ab5ca1802efc7d34a861da156133ff0ba57f0878 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Tue, 15 Apr 2025 02:17:40 -0600 Subject: [PATCH 162/175] test: Add tests for custom Levels --- examples/custom_error.rs | 35 ++++++++++++++++++++ examples/custom_error.svg | 35 ++++++++++++++++++++ examples/custom_level.rs | 69 +++++++++++++++++++++++++++++++++++++++ examples/custom_level.svg | 61 ++++++++++++++++++++++++++++++++++ tests/examples.rs | 14 ++++++++ 5 files changed, 214 insertions(+) create mode 100644 examples/custom_error.rs create mode 100644 examples/custom_error.svg create mode 100644 examples/custom_level.rs create mode 100644 examples/custom_level.svg diff --git a/examples/custom_error.rs b/examples/custom_error.rs new file mode 100644 index 0000000..3ba234d --- /dev/null +++ b/examples/custom_error.rs @@ -0,0 +1,35 @@ +use annotate_snippets::renderer::OutputTheme; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +fn main() { + let source = r#"//@ compile-flags: -Ztreat-err-as-bug +//@ failure-status: 101 +//@ error-pattern: aborting due to `-Z treat-err-as-bug=1` +//@ error-pattern: [eval_static_initializer] evaluating initializer of static `C` +//@ normalize-stderr: "note: .*\n\n" -> "" +//@ normalize-stderr: "thread 'rustc' panicked.*:\n.*\n" -> "" +//@ rustc-env:RUST_BACKTRACE=0 + +#![crate_type = "rlib"] + +pub static C: u32 = 0 - 1; +//~^ ERROR could not evaluate static initializer +"#; + let message = Level::None + .message("error: internal compiler error[E0080]: could not evaluate static initializer") + .group( + Group::new().element( + Snippet::source(source) + .origin("$DIR/err.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(386..391) + .label("attempt to compute `0_u32 - 1_u32`, which would overflow"), + ), + ), + ); + + let renderer = Renderer::styled().theme(OutputTheme::Unicode); + anstream::println!("{}", renderer.render(message)); +} diff --git a/examples/custom_error.svg b/examples/custom_error.svg new file mode 100644 index 0000000..5cb0c72 --- /dev/null +++ b/examples/custom_error.svg @@ -0,0 +1,35 @@ + + + + + + + error: internal compiler error[E0080]: could not evaluate static initializer + + ╭▸ $DIR/err.rs:11:21 + + + + 11 pub static C: u32 = 0 - 1; + + ╰╴ ━━━━━ attempt to compute `0_u32 - 1_u32`, which would overflow + + + + + + diff --git a/examples/custom_level.rs b/examples/custom_level.rs new file mode 100644 index 0000000..c19cdc4 --- /dev/null +++ b/examples/custom_level.rs @@ -0,0 +1,69 @@ +use annotate_snippets::renderer::OutputTheme; +use annotate_snippets::{AnnotationKind, Group, Level, Patch, Renderer, Snippet}; + +fn main() { + let source = r#"// Regression test for issue #114529 +// Tests that we do not ICE during const eval for a +// break-with-value in contexts where it is illegal + +#[allow(while_true)] +fn main() { + [(); { + while true { + break 9; //~ ERROR `break` with value from a `while` loop + }; + 51 + }]; + + [(); { + while let Some(v) = Some(9) { + break v; //~ ERROR `break` with value from a `while` loop + }; + 51 + }]; + + while true { + break (|| { //~ ERROR `break` with value from a `while` loop + let local = 9; + }); + } +} +"#; + let message = Level::Error + .message("`break` with value from a `while` loop") + .id("E0571") + .group( + Group::new().element( + Snippet::source(source) + .line_start(1) + .origin("$DIR/issue-114529-illegal-break-with-value.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(483..581) + .label("can only break with a value inside `loop` or breakable block"), + ) + .annotation( + AnnotationKind::Context + .span(462..472) + .label("you can't `break` with a value in a `while` loop"), + ), + ), + ) + .group( + Group::new() + .element(Level::None.title( + "suggestion: use `break` on its own without a value inside this `while` loop", + )) + .element( + Snippet::source(source) + .line_start(1) + .origin("$DIR/issue-114529-illegal-break-with-value.rs") + .fold(true) + .patch(Patch::new(483..581, "break")), + ), + ); + + let renderer = Renderer::styled().theme(OutputTheme::Unicode); + anstream::println!("{}", renderer.render(message)); +} diff --git a/examples/custom_level.svg b/examples/custom_level.svg new file mode 100644 index 0000000..1f31e65 --- /dev/null +++ b/examples/custom_level.svg @@ -0,0 +1,61 @@ + + + + + + + error[E0571]: `break` with value from a `while` loop + + ╭▸ $DIR/issue-114529-illegal-break-with-value.rs:22:9 + + + + 21 while true { + + ────────── you can't `break` with a value in a `while` loop + + 22 break (|| { //~ ERROR `break` with value from a `while` loop + + 23 let local = 9; + + 24 }); + + ┗━━━━━━━━━━┛ can only break with a value inside `loop` or breakable block + + ╰╴ + + suggestion: use `break` on its own without a value inside this `while` loop + + ╭╴ + + 22 - break (|| { //~ ERROR `break` with value from a `while` loop + + 23 - let local = 9; + + 24 - }); + + 22 + break; + + ╰╴ + + + + + + diff --git a/tests/examples.rs b/tests/examples.rs index a0504c1..66dd94b 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -1,3 +1,17 @@ +#[test] +fn custom_error() { + let target = "custom_error"; + let expected = snapbox::file!["../examples/custom_error.svg": TermSvg]; + assert_example(target, expected); +} + +#[test] +fn custom_level() { + let target = "custom_level"; + let expected = snapbox::file!["../examples/custom_level.svg": TermSvg]; + assert_example(target, expected); +} + #[test] fn expected_type() { let target = "expected_type"; From 353a040447d6284df6711c7b9cb8ed86302971d8 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Tue, 1 Apr 2025 18:27:45 -0600 Subject: [PATCH 163/175] feat: Add custom Levels --- benches/bench.rs | 6 +- examples/custom_error.rs | 8 +- examples/custom_error.svg | 5 +- examples/custom_level.rs | 12 ++- examples/custom_level.svg | 3 +- examples/expected_type.rs | 4 +- examples/footer.rs | 6 +- examples/format.rs | 4 +- examples/highlight_source.rs | 6 +- examples/highlight_title.rs | 6 +- examples/multislice.rs | 4 +- src/level.rs | 128 +++++++++++++++++++++++ src/lib.rs | 1 + src/renderer/mod.rs | 36 +++---- src/renderer/styled_buffer.rs | 6 +- src/snippet.rs | 65 +----------- tests/fixtures/deserialize.rs | 35 +++++-- tests/formatter.rs | 192 +++++++++++++++++----------------- tests/rustc_tests.rs | 88 ++++++++-------- 19 files changed, 352 insertions(+), 263 deletions(-) create mode 100644 src/level.rs diff --git a/benches/bench.rs b/benches/bench.rs index 01364af..d50cf43 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; +use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; #[divan::bench] fn simple() -> String { @@ -24,7 +24,7 @@ fn simple() -> String { _ => continue, } }"#; - let message = Level::Error.message("mismatched types").id("E0308").group( + let message = Level::ERROR.message("mismatched types").id("E0308").group( Group::new().element( Snippet::source(source) .line_start(51) @@ -69,7 +69,7 @@ fn fold(bencher: divan::Bencher<'_, '_>, context: usize) { (input, span) }) .bench_values(|(input, span)| { - let message = Level::Error.message("mismatched types").id("E0308").group( + let message = Level::ERROR.message("mismatched types").id("E0308").group( Group::new().element( Snippet::source(&input) .fold(true) diff --git a/examples/custom_error.rs b/examples/custom_error.rs index 3ba234d..4050d40 100644 --- a/examples/custom_error.rs +++ b/examples/custom_error.rs @@ -1,5 +1,5 @@ use annotate_snippets::renderer::OutputTheme; -use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; +use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; fn main() { let source = r#"//@ compile-flags: -Ztreat-err-as-bug @@ -15,8 +15,10 @@ fn main() { pub static C: u32 = 0 - 1; //~^ ERROR could not evaluate static initializer "#; - let message = Level::None - .message("error: internal compiler error[E0080]: could not evaluate static initializer") + let message = Level::ERROR + .text(Some("error: internal compiler error")) + .message("could not evaluate static initializer") + .id("E0080") .group( Group::new().element( Snippet::source(source) diff --git a/examples/custom_error.svg b/examples/custom_error.svg index 5cb0c72..af3611a 100644 --- a/examples/custom_error.svg +++ b/examples/custom_error.svg @@ -3,6 +3,7 @@ .fg { fill: #AAAAAA } .bg { background: #000000 } .fg-bright-blue { fill: #5555FF } + .fg-bright-red { fill: #FF5555 } .container { padding: 0 10px; line-height: 18px; @@ -18,7 +19,7 @@ - error: internal compiler error[E0080]: could not evaluate static initializer + error: internal compiler error[E0080]: could not evaluate static initializer ╭▸ $DIR/err.rs:11:21 @@ -26,7 +27,7 @@ 11 pub static C: u32 = 0 - 1; - ╰╴ ━━━━━ attempt to compute `0_u32 - 1_u32`, which would overflow + ╰╴ ━━━━━ attempt to compute `0_u32 - 1_u32`, which would overflow diff --git a/examples/custom_level.rs b/examples/custom_level.rs index c19cdc4..804f774 100644 --- a/examples/custom_level.rs +++ b/examples/custom_level.rs @@ -1,5 +1,5 @@ use annotate_snippets::renderer::OutputTheme; -use annotate_snippets::{AnnotationKind, Group, Level, Patch, Renderer, Snippet}; +use annotate_snippets::{level::Level, AnnotationKind, Group, Patch, Renderer, Snippet}; fn main() { let source = r#"// Regression test for issue #114529 @@ -29,7 +29,7 @@ fn main() { } } "#; - let message = Level::Error + let message = Level::ERROR .message("`break` with value from a `while` loop") .id("E0571") .group( @@ -52,9 +52,11 @@ fn main() { ) .group( Group::new() - .element(Level::None.title( - "suggestion: use `break` on its own without a value inside this `while` loop", - )) + .element( + Level::HELP + .text(Some("suggestion")) + .title("use `break` on its own without a value inside this `while` loop"), + ) .element( Snippet::source(source) .line_start(1) diff --git a/examples/custom_level.svg b/examples/custom_level.svg index 1f31e65..eebff28 100644 --- a/examples/custom_level.svg +++ b/examples/custom_level.svg @@ -3,6 +3,7 @@ .fg { fill: #AAAAAA } .bg { background: #000000 } .fg-bright-blue { fill: #5555FF } + .fg-bright-cyan { fill: #55FFFF } .fg-bright-green { fill: #55FF55 } .fg-bright-red { fill: #FF5555 } .container { @@ -40,7 +41,7 @@ ╰╴ - suggestion: use `break` on its own without a value inside this `while` loop + suggestion: use `break` on its own without a value inside this `while` loop ╭╴ diff --git a/examples/expected_type.rs b/examples/expected_type.rs index f61999d..9a51dce 100644 --- a/examples/expected_type.rs +++ b/examples/expected_type.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; +use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; fn main() { let source = r#" annotations: vec![SourceAnnotation { @@ -6,7 +6,7 @@ fn main() { , range: <22, 25>,"#; let message = - Level::Error.message("expected type, found `22`").group( + Level::ERROR.message("expected type, found `22`").group( Group::new().element( Snippet::source(source) .line_start(26) diff --git a/examples/footer.rs b/examples/footer.rs index 29b27c1..d61e84b 100644 --- a/examples/footer.rs +++ b/examples/footer.rs @@ -1,7 +1,7 @@ -use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; +use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; fn main() { - let message = Level::Error + let message = Level::ERROR .message("mismatched types") .id("E0308") .group( @@ -14,7 +14,7 @@ fn main() { )), ), ) - .group(Group::new().element(Level::Note.title( + .group(Group::new().element(Level::NOTE.title( "expected type: `snippet::Annotation`\n found type: `__&__snippet::Annotation`", ))); diff --git a/examples/format.rs b/examples/format.rs index df6f927..5324413 100644 --- a/examples/format.rs +++ b/examples/format.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; +use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; fn main() { let source = r#") -> Option { @@ -23,7 +23,7 @@ fn main() { _ => continue, } }"#; - let message = Level::Error.message("mismatched types").id("E0308").group( + let message = Level::ERROR.message("mismatched types").id("E0308").group( Group::new().element( Snippet::source(source) .line_start(51) diff --git a/examples/highlight_source.rs b/examples/highlight_source.rs index 2bb4ec2..9962542 100644 --- a/examples/highlight_source.rs +++ b/examples/highlight_source.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; +use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; fn main() { let source = r#"//@ compile-flags: -Z teach @@ -9,7 +9,7 @@ const CON: Vec = vec![1, 2, 3]; //~ ERROR E0010 //~| ERROR cannot call non-const method fn main() {} "#; - let message = Level::Error + let message = Level::ERROR .message("allocations are not allowed in constants") .id("E0010") .group( @@ -26,7 +26,7 @@ fn main() {} ), ) .element( - Level::Note.title("The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created."), + Level::NOTE.title("The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created."), ), ); diff --git a/examples/highlight_title.rs b/examples/highlight_title.rs index bb09049..e2da54f 100644 --- a/examples/highlight_title.rs +++ b/examples/highlight_title.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; +use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; use anstyle::Effects; fn main() { @@ -43,7 +43,7 @@ fn main() { magenta.render_reset() ); - let message = Level::Error.message("mismatched types").id("E0308").group( + let message = Level::ERROR.message("mismatched types").id("E0308").group( Group::new() .element( Snippet::source(source) @@ -60,7 +60,7 @@ fn main() { .label("arguments to this function are incorrect"), ), ) - .element(Level::Note.title(&title)), + .element(Level::NOTE.title(&title)), ); let renderer = Renderer::styled().anonymized_line_numbers(true); diff --git a/examples/multislice.rs b/examples/multislice.rs index d1ad72a..ddd938e 100644 --- a/examples/multislice.rs +++ b/examples/multislice.rs @@ -1,7 +1,7 @@ -use annotate_snippets::{Annotation, Group, Level, Renderer, Snippet}; +use annotate_snippets::{level::Level, Annotation, Group, Renderer, Snippet}; fn main() { - let message = Level::Error.message("mismatched types").group( + let message = Level::ERROR.message("mismatched types").group( Group::new() .element( Snippet::>::source("Foo") diff --git a/src/level.rs b/src/level.rs new file mode 100644 index 0000000..7f92024 --- /dev/null +++ b/src/level.rs @@ -0,0 +1,128 @@ +use crate::renderer::stylesheet::Stylesheet; +use crate::snippet::{ERROR_TXT, HELP_TXT, INFO_TXT, NOTE_TXT, WARNING_TXT}; +use crate::{Element, Group, Message, Title}; +use anstyle::Style; + +pub const ERROR: Level<'_> = Level { + name: None, + level: LevelInner::Error, +}; + +pub const WARNING: Level<'_> = Level { + name: None, + level: LevelInner::Warning, +}; + +pub const INFO: Level<'_> = Level { + name: None, + level: LevelInner::Info, +}; + +pub const NOTE: Level<'_> = Level { + name: None, + level: LevelInner::Note, +}; + +pub const HELP: Level<'_> = Level { + name: None, + level: LevelInner::Help, +}; + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Level<'a> { + pub(crate) name: Option>, + pub(crate) level: LevelInner, +} + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub enum Level2<'a> { + Builtin(LevelInner), + Custom { + name: Option<&'a str>, + level: LevelInner, + }, + None, +} + +impl<'a> Level<'a> { + pub const ERROR: Level<'a> = ERROR; + pub const WARNING: Level<'a> = WARNING; + pub const INFO: Level<'a> = INFO; + pub const NOTE: Level<'a> = NOTE; + pub const HELP: Level<'a> = HELP; + + /// Text passed to this function is considered "untrusted input", as such + /// all text is passed through a normalization function. Pre-styled text is + /// not allowed to be passed to this function. + pub fn text(self, text: Option<&'a str>) -> Level<'a> { + Level { + name: Some(text), + level: self.level, + } + } +} + +impl<'a> Level<'a> { + /// Text passed to this function is considered "untrusted input", as such + /// all text is passed through a normalization function. Pre-styled text is + /// not allowed to be passed to this function. + pub fn message(self, title: &'a str) -> Message<'a> { + Message { + id: None, + groups: vec![Group::new().element(Element::Title(Title { + level: self, + title, + primary: true, + }))], + } + } + + /// Text passed to this function is allowed to be pre-styled, as such all + /// text is considered "trusted input" and has no normalizations applied to + /// it. [`normalize_untrusted_str`](crate::normalize_untrusted_str) can be + /// used to normalize untrusted text before it is passed to this function. + pub fn title(self, title: &'a str) -> Title<'a> { + Title { + level: self, + title, + primary: false, + } + } + + pub(crate) fn as_str(&self) -> &'a str { + match (self.name, self.level) { + (Some(Some(name)), _) => name, + (Some(None), _) => "", + (None, LevelInner::Error) => ERROR_TXT, + (None, LevelInner::Warning) => WARNING_TXT, + (None, LevelInner::Info) => INFO_TXT, + (None, LevelInner::Note) => NOTE_TXT, + (None, LevelInner::Help) => HELP_TXT, + } + } + + pub(crate) fn style(&self, stylesheet: &Stylesheet) -> Style { + self.level.style(stylesheet) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub enum LevelInner { + Error, + Warning, + Info, + Note, + Help, +} + +impl LevelInner { + pub(crate) fn style(self, stylesheet: &Stylesheet) -> Style { + match self { + LevelInner::Error => stylesheet.error, + LevelInner::Warning => stylesheet.warning, + LevelInner::Info => stylesheet.info, + LevelInner::Note => stylesheet.note, + LevelInner::Help => stylesheet.help, + } + } +} diff --git a/src/lib.rs b/src/lib.rs index e6c49c6..eee2b6f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,7 @@ #![warn(clippy::print_stdout)] #![warn(missing_debug_implementations)] +pub mod level; pub mod renderer; mod snippet; diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 7d4fd0f..8efcff8 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -5,6 +5,7 @@ //! # Example //! ``` //! use annotate_snippets::*; +//! use annotate_snippets::level::Level; //! //! let source = r#" //! use baz::zed::bar; @@ -17,7 +18,7 @@ //! bar(); //! } //! "#; -//! Level::Error +//! Level::ERROR //! .message("unresolved import `baz::zed`") //! .id("E0432") //! .group( @@ -40,13 +41,12 @@ pub(crate) mod source_map; mod styled_buffer; pub(crate) mod stylesheet; +use crate::level::{Level, LevelInner}; use crate::renderer::source_map::{ AnnotatedLineInfo, LineInfo, Loc, SourceMap, SubstitutionHighlight, }; use crate::renderer::styled_buffer::StyledBuffer; -use crate::{ - Annotation, AnnotationKind, Element, Group, Level, Message, Origin, Patch, Snippet, Title, -}; +use crate::{Annotation, AnnotationKind, Element, Group, Message, Origin, Patch, Snippet, Title}; pub use anstyle::*; use margin::Margin; use std::borrow::Cow; @@ -207,7 +207,7 @@ impl Renderer { }; let title = message.groups.remove(0).elements.remove(0); let level = if let Element::Title(title) = &title { - title.level + title.level.clone() } else { panic!("Expected a title as the first element of the message") }; @@ -345,7 +345,7 @@ impl Renderer { ); if g == 0 && group_len > 1 { - if matches!(peek, Some(Element::Title(level)) if level.level != Level::None) + if matches!(peek, Some(Element::Title(level)) if level.level.name != Some(None)) { self.draw_col_separator_no_space( buffer, @@ -394,7 +394,7 @@ impl Renderer { if g == 0 && (matches!(section, Element::Origin(_)) || (matches!(section, Element::Title(_)) && i == 0) - || matches!(section, Element::Title(level) if level.level == Level::None)) + || matches!(section, Element::Title(level) if level.level.name == Some(None))) { if peek.is_none() && group_len > 1 { self.draw_col_separator_end( @@ -402,7 +402,7 @@ impl Renderer { buffer.num_lines(), max_line_num_len + 1, ); - } else if matches!(peek, Some(Element::Title(level)) if level.level != Level::None) + } else if matches!(peek, Some(Element::Title(level)) if level.level.name != Some(None)) { self.draw_col_separator_no_space( buffer, @@ -445,7 +445,7 @@ impl Renderer { buffer.prepend(line_offset, " ", ElementStyle::NoStyle); } - if title.level != Level::None { + if title.level.name != Some(None) { self.draw_note_separator(buffer, line_offset, max_line_num_len + 1, is_cont); buffer.append( line_offset, @@ -476,18 +476,18 @@ impl Renderer { } else { let mut label_width = 0; - if title.level != Level::None { + if title.level.name != Some(None) { buffer.append( line_offset, title.level.as_str(), - ElementStyle::Level(title.level), + ElementStyle::Level(title.level.level), ); } label_width += title.level.as_str().len(); if let Some(id) = id { - buffer.append(line_offset, "[", ElementStyle::Level(title.level)); - buffer.append(line_offset, id, ElementStyle::Level(title.level)); - buffer.append(line_offset, "]", ElementStyle::Level(title.level)); + buffer.append(line_offset, "[", ElementStyle::Level(title.level.level)); + buffer.append(line_offset, id, ElementStyle::Level(title.level.level)); + buffer.append(line_offset, "]", ElementStyle::Level(title.level.level)); label_width += 2 + id.len(); } let header_style = if is_secondary { @@ -495,7 +495,7 @@ impl Renderer { } else { ElementStyle::MainHeaderMsg }; - if title.level != Level::None { + if title.level.name != Some(None) { buffer.append(line_offset, ": ", header_style); label_width += 2; } @@ -647,7 +647,7 @@ impl Renderer { buffer_msg_line_offset + 1, max_line_num_len + 1, ); - let title = Level::Note.title(label); + let title = Level::NOTE.title(label); self.render_title(buffer, &title, None, max_line_num_len, true, None, false); } } @@ -2654,13 +2654,13 @@ pub(crate) enum ElementStyle { LabelPrimary, LabelSecondary, NoStyle, - Level(Level), + Level(LevelInner), Addition, Removal, } impl ElementStyle { - fn color_spec(&self, level: Level, stylesheet: &Stylesheet) -> Style { + fn color_spec(&self, level: &Level<'_>, stylesheet: &Stylesheet) -> Style { match self { ElementStyle::Addition => stylesheet.addition, ElementStyle::Removal => stylesheet.removal, diff --git a/src/renderer/styled_buffer.rs b/src/renderer/styled_buffer.rs index 8a4cc67..7114683 100644 --- a/src/renderer/styled_buffer.rs +++ b/src/renderer/styled_buffer.rs @@ -2,9 +2,9 @@ //! //! [styled_buffer]: https://github.com/rust-lang/rust/blob/894f7a4ba6554d3797404bbf550d9919df060b97/compiler/rustc_errors/src/styled_buffer.rs +use crate::level::Level; use crate::renderer::stylesheet::Stylesheet; use crate::renderer::ElementStyle; -use crate::Level; use std::fmt; use std::fmt::Write; @@ -41,14 +41,14 @@ impl StyledBuffer { pub(crate) fn render( &self, - level: Level, + level: Level<'_>, stylesheet: &Stylesheet, ) -> Result { let mut str = String::new(); for (i, line) in self.lines.iter().enumerate() { let mut current_style = stylesheet.none; for StyledChar { ch, style } in line { - let ch_style = style.color_spec(level, stylesheet); + let ch_style = style.color_spec(&level, stylesheet); if ch_style != current_style { if !line.is_empty() { write!(str, "{}", current_style.render_reset())?; diff --git a/src/snippet.rs b/src/snippet.rs index e8fa18c..fe1239d 100644 --- a/src/snippet.rs +++ b/src/snippet.rs @@ -1,8 +1,7 @@ //! Structures used as an input for the library. +use crate::level::Level; use crate::renderer::source_map::SourceMap; -use crate::renderer::stylesheet::Stylesheet; -use anstyle::Style; use std::ops::Range; pub(crate) const ERROR_TXT: &str = "error"; @@ -143,7 +142,7 @@ pub struct ColumnSeparator; #[derive(Debug)] pub struct Title<'a> { - pub(crate) level: Level, + pub(crate) level: Level<'a>, pub(crate) title: &'a str, pub(crate) primary: bool, } @@ -155,66 +154,6 @@ impl Title<'_> { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum Level { - Error, - Warning, - Info, - Note, - Help, - None, -} - -impl Level { - /// Text passed to this function is considered "untrusted input", as such - /// all text is passed through a normalization function. Pre-styled text is - /// not allowed to be passed to this function. - pub fn message(self, title: &str) -> Message<'_> { - Message { - id: None, - groups: vec![Group::new().element(Element::Title(Title { - level: self, - title, - primary: true, - }))], - } - } - - /// Text passed to this function is allowed to be pre-styled, as such all - /// text is considered "trusted input" and has no normalizations applied to - /// it. [`normalize_untrusted_str`](crate::normalize_untrusted_str) can be - /// used to normalize untrusted text before it is passed to this function. - pub fn title(self, title: &str) -> Title<'_> { - Title { - level: self, - title, - primary: false, - } - } - - pub(crate) fn as_str(self) -> &'static str { - match self { - Level::Error => ERROR_TXT, - Level::Warning => WARNING_TXT, - Level::Info => INFO_TXT, - Level::Note => NOTE_TXT, - Level::Help => HELP_TXT, - Level::None => "", - } - } - - pub(crate) fn style(&self, stylesheet: &Stylesheet) -> Style { - match self { - Level::Error => stylesheet.error, - Level::Warning => stylesheet.warning, - Level::Info => stylesheet.info, - Level::Note => stylesheet.note, - Level::Help => stylesheet.help, - Level::None => stylesheet.none, - } - } -} - #[derive(Debug)] pub struct Snippet<'a, T> { pub(crate) origin: Option<&'a str>, diff --git a/tests/fixtures/deserialize.rs b/tests/fixtures/deserialize.rs index 065c395..8f45b36 100644 --- a/tests/fixtures/deserialize.rs +++ b/tests/fixtures/deserialize.rs @@ -3,7 +3,7 @@ use std::ops::Range; use annotate_snippets::renderer::DEFAULT_TERM_WIDTH; use annotate_snippets::{ - Annotation, AnnotationKind, Element, Group, Level, Message, Patch, Renderer, Snippet, + level::Level, Annotation, AnnotationKind, Element, Group, Message, Patch, Renderer, Snippet, }; #[derive(Deserialize)] @@ -15,8 +15,7 @@ pub(crate) struct Fixture { #[derive(Deserialize)] pub struct MessageDef { - #[serde(with = "LevelDef")] - pub level: Level, + pub level: LevelDef, pub title: String, #[serde(default)] pub id: Option, @@ -32,13 +31,15 @@ impl<'a> From<&'a MessageDef> for Message<'a> { id, sections, } = val; - let mut message = level.message(title); + let mut message = Level::from(level).message(title); if let Some(id) = id { message = message.id(id); } message = message.group(Group::new().elements(sections.iter().map(|s| match s { - ElementDef::Title(title) => Element::Title(title.level.title(&title.title)), + ElementDef::Title(title) => { + Element::Title(Level::from(&title.level).title(&title.title)) + } ElementDef::Cause(cause) => Element::Cause(Snippet::from(cause)), ElementDef::Suggestion(suggestion) => Element::Suggestion(Snippet::from(suggestion)), }))); @@ -57,7 +58,9 @@ pub enum ElementDef { impl<'a> From<&'a ElementDef> for Element<'a> { fn from(val: &'a ElementDef) -> Self { match val { - ElementDef::Title(title) => Element::Title(title.level.title(&title.title)), + ElementDef::Title(title) => { + Element::Title(Level::from(&title.level).title(&title.title)) + } ElementDef::Cause(cause) => Element::Cause(Snippet::from(cause)), ElementDef::Suggestion(suggestion) => Element::Suggestion(Snippet::from(suggestion)), } @@ -67,8 +70,7 @@ impl<'a> From<&'a ElementDef> for Element<'a> { #[derive(Deserialize)] pub struct TitleDef { pub title: String, - #[serde(with = "LevelDef")] - pub level: Level, + pub level: LevelDef, } #[derive(Deserialize)] @@ -164,9 +166,8 @@ impl<'a> From<&'a PatchDef> for Patch<'a> { } #[allow(dead_code)] -#[derive(Deserialize)] -#[serde(remote = "Level")] -enum LevelDef { +#[derive(Clone, Copy, Deserialize)] +pub enum LevelDef { Error, Warning, Info, @@ -174,6 +175,18 @@ enum LevelDef { Help, } +impl<'a> From<&'a LevelDef> for Level<'a> { + fn from(val: &'a LevelDef) -> Self { + match val { + LevelDef::Error => Level::ERROR, + LevelDef::Warning => Level::WARNING, + LevelDef::Info => Level::INFO, + LevelDef::Note => Level::NOTE, + LevelDef::Help => Level::HELP, + } + } +} + #[derive(Default, Deserialize)] pub struct RendererDef { #[serde(default)] diff --git a/tests/formatter.rs b/tests/formatter.rs index 5deb21a..3f0e7cd 100644 --- a/tests/formatter.rs +++ b/tests/formatter.rs @@ -1,11 +1,13 @@ -use annotate_snippets::{Annotation, AnnotationKind, Group, Level, Patch, Renderer, Snippet}; +use annotate_snippets::{ + level::Level, Annotation, AnnotationKind, Group, Patch, Renderer, Snippet, +}; use annotate_snippets::renderer::OutputTheme; use snapbox::{assert_data_eq, str}; #[test] fn test_i_29() { - let snippets = Level::Error.message("oops").group( + let snippets = Level::ERROR.message("oops").group( Group::new().element( Snippet::source("First line\r\nSecond oops line") .origin("") @@ -27,7 +29,7 @@ error: oops #[test] fn test_point_to_double_width_characters() { - let snippets = Level::Error.message("").group( + let snippets = Level::ERROR.message("").group( Group::new().element( Snippet::source("こんにちは、世界") .origin("") @@ -49,7 +51,7 @@ error: #[test] fn test_point_to_double_width_characters_across_lines() { - let snippets = Level::Error.message("").group( + let snippets = Level::ERROR.message("").group( Group::new().element( Snippet::source("おはよう\nございます") .origin("") @@ -73,7 +75,7 @@ error: #[test] fn test_point_to_double_width_characters_multiple() { - let snippets = Level::Error.message("").group( + let snippets = Level::ERROR.message("").group( Group::new().element( Snippet::source("お寿司\n食べたい🍣") .origin("") @@ -98,7 +100,7 @@ error: #[test] fn test_point_to_double_width_characters_mixed() { - let snippets = Level::Error.message("").group( + let snippets = Level::ERROR.message("").group( Group::new().element( Snippet::source("こんにちは、新しいWorld!") .origin("") @@ -120,7 +122,7 @@ error: #[test] fn test_format_title() { - let input = Level::Error.message("This is a title").id("E0001"); + let input = Level::ERROR.message("This is a title").id("E0001"); let expected = str![r#"error[E0001]: This is a title"#]; let renderer = Renderer::plain(); @@ -130,7 +132,7 @@ fn test_format_title() { #[test] fn test_format_snippet_only() { let source = "This is line 1\nThis is line 2"; - let input = Level::Error + let input = Level::ERROR .message("") .group(Group::new().element(Snippet::>::source(source).line_start(5402))); @@ -148,7 +150,7 @@ error: fn test_format_snippets_continuation() { let src_0 = "This is slice 1"; let src_1 = "This is slice 2"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new() .element( Snippet::>::source(src_0) @@ -182,7 +184,7 @@ fn test_format_snippet_annotation_standalone() { let source = [line_1, line_2].join("\n"); // In line 2 let range = 22..24; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(&source).line_start(5402).annotation( AnnotationKind::Context @@ -204,9 +206,9 @@ error: #[test] fn test_format_footer_title() { - let input = Level::Error + let input = Level::ERROR .message("") - .group(Group::new().element(Level::Error.title("This __is__ a title"))); + .group(Group::new().element(Level::ERROR.title("This __is__ a title"))); let expected = str![[r#" error: | @@ -221,7 +223,7 @@ error: fn test_i26() { let source = "short"; let label = "label"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source).line_start(0).annotation( AnnotationKind::Primary @@ -237,7 +239,7 @@ fn test_i26() { #[test] fn test_source_content() { let source = "This is an example\nof content lines"; - let input = Level::Error + let input = Level::ERROR .message("") .group(Group::new().element(Snippet::>::source(source).line_start(56))); let expected = str![[r#" @@ -253,7 +255,7 @@ error: #[test] fn test_source_annotation_standalone_singleline() { let source = "tests"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -273,7 +275,7 @@ error: #[test] fn test_source_annotation_standalone_multiline() { let source = "tests"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -296,7 +298,7 @@ error: #[test] fn test_only_source() { - let input = Level::Error + let input = Level::ERROR .message("") .group(Group::new().element(Snippet::>::source("").origin("file.rs"))); let expected = str![[r#" @@ -311,7 +313,7 @@ error: #[test] fn test_anon_lines() { let source = "This is an example\nof content lines\n\nabc"; - let input = Level::Error + let input = Level::ERROR .message("") .group(Group::new().element(Snippet::>::source(source).line_start(56))); let expected = str![[r#" @@ -328,7 +330,7 @@ LL | abc #[test] fn issue_130() { - let input = Level::Error.message("dummy").group( + let input = Level::ERROR.message("dummy").group( Group::new().element( Snippet::source("foo\nbar\nbaz") .origin("file/path") @@ -356,7 +358,7 @@ fn unterminated_string_multiline() { a\" // ... "; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -380,7 +382,7 @@ error: #[test] fn char_and_nl_annotate_char() { let source = "a\r\nb"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -403,7 +405,7 @@ error: #[test] fn char_eol_annotate_char() { let source = "a\r\nb"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -425,7 +427,7 @@ error: #[test] fn char_eol_annotate_char_double_width() { - let snippets = Level::Error.message("").group( + let snippets = Level::ERROR.message("").group( Group::new().element( Snippet::source("こん\r\nにちは\r\n世界") .origin("") @@ -450,7 +452,7 @@ error: #[test] fn annotate_eol() { let source = "a\r\nb"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -473,7 +475,7 @@ error: #[test] fn annotate_eol2() { let source = "a\r\nb"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -496,7 +498,7 @@ error: #[test] fn annotate_eol3() { let source = "a\r\nb"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -519,7 +521,7 @@ error: #[test] fn annotate_eol4() { let source = "a\r\nb"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -541,7 +543,7 @@ error: #[test] fn annotate_eol_double_width() { - let snippets = Level::Error.message("").group( + let snippets = Level::ERROR.message("").group( Group::new().element( Snippet::source("こん\r\nにちは\r\n世界") .origin("") @@ -566,7 +568,7 @@ error: #[test] fn multiline_eol_start() { let source = "a\r\nb"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -590,7 +592,7 @@ error: #[test] fn multiline_eol_start2() { let source = "a\r\nb"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -614,7 +616,7 @@ error: #[test] fn multiline_eol_start3() { let source = "a\nb"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -637,7 +639,7 @@ error: #[test] fn multiline_eol_start_double_width() { - let snippets = Level::Error.message("").group( + let snippets = Level::ERROR.message("").group( Group::new().element( Snippet::source("こん\r\nにちは\r\n世界") .origin("") @@ -663,7 +665,7 @@ error: #[test] fn multiline_eol_start_eol_end() { let source = "a\nb\nc"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -688,7 +690,7 @@ error: #[test] fn multiline_eol_start_eol_end2() { let source = "a\r\nb\r\nc"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -713,7 +715,7 @@ error: #[test] fn multiline_eol_start_eol_end3() { let source = "a\r\nb\r\nc"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -738,7 +740,7 @@ error: #[test] fn multiline_eol_start_eof_end() { let source = "a\r\nb"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -762,7 +764,7 @@ error: #[test] fn multiline_eol_start_eof_end_double_width() { let source = "ん\r\nに"; - let input = Level::Error.message("").group( + let input = Level::ERROR.message("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -786,7 +788,7 @@ error: #[test] fn two_single_line_same_line() { let source = r#"bar = { version = "0.1.0", optional = true }"#; - let input = Level::Error.message("unused optional dependency").group( + let input = Level::ERROR.message("unused optional dependency").group( Group::new().element( Snippet::source(source) .origin("Cargo.toml") @@ -823,7 +825,7 @@ this is another line so is this bar = { version = "0.1.0", optional = true } "#; - let input = Level::Error.message("unused optional dependency").group( + let input = Level::ERROR.message("unused optional dependency").group( Group::new().element( Snippet::source(source) .line_start(4) @@ -862,7 +864,7 @@ this is another line so is this bar = { version = "0.1.0", optional = true } "#; - let input = Level::Error.message("unused optional dependency").group( + let input = Level::ERROR.message("unused optional dependency").group( Group::new().element( Snippet::source(source) .line_start(4) @@ -910,7 +912,7 @@ so is this bar = { version = "0.1.0", optional = true } this is another line "#; - let input = Level::Error.message("unused optional dependency").group( + let input = Level::ERROR.message("unused optional dependency").group( Group::new().element( Snippet::source(source) .line_start(4) @@ -961,7 +963,7 @@ error: unused optional dependency #[test] fn origin_correct_start_line() { let source = "aaa\nbbb\nccc\nddd\n"; - let input = Level::Error.message("title").group( + let input = Level::ERROR.message("title").group( Group::new().element( Snippet::source(source) .origin("origin.txt") @@ -987,7 +989,7 @@ error: title #[test] fn origin_correct_mid_line() { let source = "aaa\nbbb\nccc\nddd\n"; - let input = Level::Error.message("title").group( + let input = Level::ERROR.message("title").group( Group::new().element( Snippet::source(source) .origin("origin.txt") @@ -1017,7 +1019,7 @@ error: title #[test] fn two_suggestions_same_span() { let source = r#" A.foo();"#; - let input_new = Level::Error + let input_new = Level::ERROR .message("expected value, found enum `A`") .id("E0423") .group( @@ -1030,7 +1032,7 @@ fn two_suggestions_same_span() { .group( Group::new() .element( - Level::Help + Level::HELP .title("you might have meant to use one of the following enum variants"), ) .element( @@ -1085,7 +1087,7 @@ fn main() { banana::Chaenomeles.pick() }"#; let input_new = - Level::Error + Level::ERROR .message("no method named `pick` found for struct `Chaenomeles` in the current scope") .id("E0599") .group( @@ -1107,7 +1109,7 @@ fn main() { ) .group( Group::new() - .element(Level::Help.title( + .element(Level::HELP.title( "the following traits which provide `pick` are implemented but not in scope; perhaps you want to import one of them", )) .element( @@ -1145,7 +1147,7 @@ LL + use banana::Peach; fn single_line_non_overlapping_suggestions() { let source = r#" A.foo();"#; - let input_new = Level::Error + let input_new = Level::ERROR .message("expected value, found enum `A`") .id("E0423") .group( @@ -1158,7 +1160,7 @@ fn single_line_non_overlapping_suggestions() { ) .group( Group::new() - .element(Level::Help.title("make these changes and things will work")) + .element(Level::HELP.title("make these changes and things will work")) .element( Snippet::source(source) .fold(true) @@ -1187,7 +1189,7 @@ LL + (A::Tuple()).bar(); #[test] fn single_line_non_overlapping_suggestions2() { let source = r#" ThisIsVeryLong.foo();"#; - let input_new = Level::Error + let input_new = Level::ERROR .message("Found `ThisIsVeryLong`") .id("E0423") .group( @@ -1200,7 +1202,7 @@ fn single_line_non_overlapping_suggestions2() { ) .group( Group::new() - .element(Level::Help.title("make these changes and things will work")) + .element(Level::HELP.title("make these changes and things will work")) .element( Snippet::source(source) .fold(true) @@ -1236,7 +1238,7 @@ fn multiple_replacements() { y(); "#; - let input_new = Level::Error + let input_new = Level::ERROR .message("cannot borrow `*self` as mutable because it is also borrowed as immutable") .id("E0502") .group( @@ -1269,7 +1271,7 @@ fn multiple_replacements() { .group( Group::new() .element( - Level::Help + Level::HELP .title("try explicitly pass `&Self` into the Closure as an argument"), ) .element( @@ -1320,7 +1322,7 @@ fn main() { test1(); }"#; - let input_new = Level::Error + let input_new = Level::ERROR .message("cannot borrow `chars` as mutable more than once at a time") .id("E0499") .group( @@ -1348,7 +1350,7 @@ fn main() { .group( Group::new() .element( - Level::Help + Level::HELP .title("if you want to call `next` on a iterator within the loop, consider using `while let`") ) .element( @@ -1404,7 +1406,7 @@ struct Foo { fn main() {}"#; - let input_new = Level::Error + let input_new = Level::ERROR .message("failed to resolve: use of undeclared crate or module `st`") .id("E0433") .group( @@ -1418,7 +1420,7 @@ fn main() {}"#; ) .group( Group::new() - .element(Level::Help.title("there is a crate or module with a similar name")) + .element(Level::HELP.title("there is a crate or module with a similar name")) .element( Snippet::source(source) .fold(true) @@ -1427,7 +1429,7 @@ fn main() {}"#; ) .group( Group::new() - .element(Level::Help.title("consider importing this module")) + .element(Level::HELP.title("consider importing this module")) .element( Snippet::source(source) .fold(true) @@ -1436,7 +1438,7 @@ fn main() {}"#; ) .group( Group::new() - .element(Level::Help.title("if you import `cell`, refer to it directly")) + .element(Level::HELP.title("if you import `cell`, refer to it directly")) .element( Snippet::source(source) .fold(true) @@ -1486,7 +1488,7 @@ where fn main() {}"#; - let input_new = Level::Error + let input_new = Level::ERROR .message("the size for values of type `T` cannot be known at compilation time") .id("E0277") .group( @@ -1508,7 +1510,7 @@ fn main() {}"#; ) .group( Group::new() - .element(Level::Help.title( + .element(Level::HELP.title( "consider removing the `?Sized` bound to make the type parameter `Sized`", )) .element( @@ -1555,7 +1557,7 @@ and where } fn main() {}"#; - let input_new = Level::Error + let input_new = Level::ERROR .message("the size for values of type `T` cannot be known at compilation time") .id("E0277") .group(Group::new().element(Snippet::source(source) @@ -1573,7 +1575,7 @@ fn main() {}"#; .label("this type parameter needs to be `Sized`"), ))) .group(Group::new().element( - Level::Note + Level::NOTE .title("required by an implicit `Sized` bound in `Wrapper`") ).element( Snippet::source(source) @@ -1587,7 +1589,7 @@ fn main() {}"#; ) )) .group(Group::new().element( - Level::Help + Level::HELP .title("you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box`") ) .element( @@ -1608,7 +1610,7 @@ fn main() {}"#; )) .group(Group::new().element( - Level::Help + Level::HELP .title("consider removing the `?Sized` bound to make the type parameter `Sized`") ).element( Snippet::source(source) @@ -1660,12 +1662,12 @@ quack zappy "#; - let input_new = Level::Error + let input_new = Level::ERROR .message("the size for values of type `T` cannot be known at compilation time") .id("E0277") .group( Group::new() - .element(Level::Help.title( + .element(Level::HELP.title( "consider removing the `?Sized` bound to make the type parameter `Sized`", )) .element( @@ -1728,7 +1730,7 @@ fn main() { } "#; - let input_new = Level::Error + let input_new = Level::ERROR .message("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") .id("E0271") .group(Group::new().element(Snippet::source(source) @@ -1741,7 +1743,7 @@ fn main() { .label("type mismatch resolving `, ...>>, ...> as Future>::Error == Foo`"), ))) .group(Group::new().element( - Level::Note.title("expected this to be `Foo`") + Level::NOTE.title("expected this to be `Foo`") ).element( Snippet::source(source) .line_start(4) @@ -1749,7 +1751,7 @@ fn main() { .fold(true) .annotation(AnnotationKind::Primary.span(89..90)) ).element( - Level::Note + Level::NOTE .title("required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>`") , )); @@ -1816,7 +1818,7 @@ fn main() { } "#; - let input_new = Level::Error + let input_new = Level::ERROR .message("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") .id("E0271") .group(Group::new().element(Snippet::source(source) @@ -1829,7 +1831,7 @@ fn main() { .label("type mismatch resolving `, ...>>, ...> as Future>::Error == Foo`"), ))) .group(Group::new().element( - Level::Note.title("expected this to be `Foo`") + Level::NOTE.title("expected this to be `Foo`") ).element( Snippet::source(source) .line_start(4) @@ -1837,10 +1839,10 @@ fn main() { .fold(true) .annotation(AnnotationKind::Primary.span(89..90)) ).element( - Level::Note + Level::NOTE .title("required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>`") ).element( - Level::Note.title("a second note"), + Level::NOTE.title("a second note"), )); let expected = str![[r#" @@ -1969,7 +1971,7 @@ fn main() { } "#; - let input_new = Level::Error + let input_new = Level::ERROR .message("mismatched types") .id("E0308") .group(Group::new().element( @@ -1988,13 +1990,13 @@ fn main() { .label("expected due to this"), ) ).element( - Level::Note + Level::NOTE .title("expected struct `Atype, i32>`\n found enum `Result, _>`") ).element( - Level::Note + Level::NOTE .title("the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'") ).element( - Level::Note + Level::NOTE .title("consider using `--verbose` to print the full type name to the console") , )); @@ -2053,7 +2055,7 @@ fn main() { } "#; - let input_new = Level::Error + let input_new = Level::ERROR .message("mismatched types") .id("E0308") .group(Group::new().element( @@ -2072,12 +2074,12 @@ fn main() { .label("arguments to this function are incorrect"), ), ).element( - Level::Note + Level::NOTE .title("expected fn pointer `for<'a> fn(Box<(dyn Any + Send + 'a)>) -> Pin<_>`\n found fn item `fn(Box<(dyn Any + Send + 'static)>) -> Pin<_> {wrapped_fn}`") , )) .group(Group::new().element( - Level::Note.title("function defined here"), + Level::NOTE.title("function defined here"), ).element( Snippet::source(source) .line_start(7) @@ -2122,7 +2124,7 @@ LL │ ┃ )>>) {} #[test] fn unicode_cut_handling() { let source = "version = \"0.1.0\"\n# Ensure that the spans from toml handle utf-8 correctly\nauthors = [\n { name = \"Z\u{351}\u{36b}\u{343}\u{36a}\u{302}\u{36b}\u{33d}\u{34f}\u{334}\u{319}\u{324}\u{31e}\u{349}\u{35a}\u{32f}\u{31e}\u{320}\u{34d}A\u{36b}\u{357}\u{334}\u{362}\u{335}\u{31c}\u{330}\u{354}L\u{368}\u{367}\u{369}\u{358}\u{320}G\u{311}\u{357}\u{30e}\u{305}\u{35b}\u{341}\u{334}\u{33b}\u{348}\u{34d}\u{354}\u{339}O\u{342}\u{30c}\u{30c}\u{358}\u{328}\u{335}\u{339}\u{33b}\u{31d}\u{333}\", email = 1 }\n]\n"; - let input = Level::Error.message("title").group( + let input = Level::ERROR.message("title").group( Group::new().element( Snippet::source(source) .fold(false) @@ -2147,7 +2149,7 @@ error: title #[test] fn unicode_cut_handling2() { let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?"; - let input = Level::Error + let input = Level::ERROR .message("expected item, found `?`") .group( Group::new().element( @@ -2155,7 +2157,7 @@ fn unicode_cut_handling2() { .fold(false) .annotation(AnnotationKind::Primary.span(499..500).label("expected item")) ).element( - Level::Note.title("for a full list of items that can appear in modules, see ") + Level::NOTE.title("for a full list of items that can appear in modules, see ") ) ); @@ -2174,7 +2176,7 @@ error: expected item, found `?` #[test] fn unicode_cut_handling3() { let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?"; - let input = Level::Error + let input = Level::ERROR .message("expected item, found `?`") .group( Group::new().element( @@ -2182,7 +2184,7 @@ fn unicode_cut_handling3() { .fold(false) .annotation(AnnotationKind::Primary.span(251..254).label("expected item")) ).element( - Level::Note.title("for a full list of items that can appear in modules, see ") + Level::NOTE.title("for a full list of items that can appear in modules, see ") ) ); @@ -2201,7 +2203,7 @@ error: expected item, found `?` #[test] fn unicode_cut_handling4() { let source = "/*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/?"; - let input = Level::Error + let input = Level::ERROR .message("expected item, found `?`") .group( Group::new().element( @@ -2209,7 +2211,7 @@ fn unicode_cut_handling4() { .fold(false) .annotation(AnnotationKind::Primary.span(334..335).label("expected item")) ).element( - Level::Note.title("for a full list of items that can appear in modules, see ") + Level::NOTE.title("for a full list of items that can appear in modules, see ") ) ); @@ -2234,7 +2236,7 @@ fn main() { //~^ ERROR mismatched types } "##; - let input = Level::Error.message("mismatched types").id("E0308").group( + let input = Level::ERROR.message("mismatched types").id("E0308").group( Group::new().element( Snippet::source(source) .origin("$DIR/non-whitespace-trimming-unicode.rs") @@ -2278,7 +2280,7 @@ fn main() { //[ascii]~^ ERROR cannot add `&str` to `&str` } "##; - let input = Level::Error + let input = Level::ERROR .message("cannot add `&str` to `&str`") .id("E0369") .group( @@ -2296,13 +2298,13 @@ fn main() { ), ) .element( - Level::Note + Level::NOTE .title("string concatenation requires an owned `String` on the left"), ), ) .group( Group::new() - .element(Level::Help.title("create an owned `String` from a string reference")) + .element(Level::HELP.title("create an owned `String` from a string reference")) .element( Snippet::source(source) .origin("$DIR/non-1-width-unicode-multiline-label.rs") @@ -2345,7 +2347,7 @@ fn foo() { } "##; let bin_source = "�|�\u{0002}!5�cc\u{0015}\u{0002}�Ӻi��WWj�ȥ�'�}�\u{0012}�J�ȉ��W�\u{001e}O�@����\u{001c}w�V���LO����\u{0014}[ \u{0003}_�'���SQ�~ذ��ų&��-\t��lN~��!@␌ _#���kQ��h�\u{001d}�:�\u{001c}\u{0007}�"; - let input = Level::Error + let input = Level::ERROR .message("couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8") .group( Group::new().element( @@ -2357,14 +2359,14 @@ fn foo() { ) .group( Group::new() - .element(Level::Note.title("byte `193` is not valid utf-8")) + .element(Level::NOTE.title("byte `193` is not valid utf-8")) .element( Snippet::source(bin_source) .origin("$DIR/not-utf8.bin") .fold(true) .annotation(AnnotationKind::Primary.span(0..0)), ) - .element(Level::Note.title("this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info)")), + .element(Level::NOTE.title("this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info)")), ); let expected = str![[r#" diff --git a/tests/rustc_tests.rs b/tests/rustc_tests.rs index 47a3399..7a795db 100644 --- a/tests/rustc_tests.rs +++ b/tests/rustc_tests.rs @@ -2,7 +2,7 @@ //! //! [parser-tests]: https://github.com/rust-lang/rust/blob/894f7a4ba6554d3797404bbf550d9919df060b97/compiler/rustc_parse/src/parser/tests.rs -use annotate_snippets::{AnnotationKind, Group, Level, Origin, Renderer, Snippet}; +use annotate_snippets::{level::Level, AnnotationKind, Group, Origin, Renderer, Snippet}; use snapbox::{assert_data_eq, str}; @@ -12,7 +12,7 @@ fn ends_on_col0() { fn foo() { } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -42,7 +42,7 @@ fn foo() { } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -74,7 +74,7 @@ fn foo() { X2 Y2 } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -117,7 +117,7 @@ fn foo() { Y1 X1 } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -161,7 +161,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -205,7 +205,7 @@ fn foo() { X2 Y2 Z2 } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -252,7 +252,7 @@ fn foo() { X2 Y2 Z2 } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -300,7 +300,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -350,7 +350,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -394,7 +394,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -437,7 +437,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -470,7 +470,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -502,7 +502,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -537,7 +537,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -571,7 +571,7 @@ fn foo() { a bc d } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -605,7 +605,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -633,7 +633,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -662,7 +662,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -701,7 +701,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -732,7 +732,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -772,7 +772,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -832,7 +832,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::Error.message("foo").group( + let input = Level::ERROR.message("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -886,7 +886,7 @@ fn issue_91334() { fn f(){||yield(((){), "#; - let input = Level::Error + let input = Level::ERROR .message("this file contains an unclosed delimiter") .group( Group::new().element( @@ -957,7 +957,7 @@ fn main() { } } "#; - let input = Level::Error + let input = Level::ERROR .message("`break` with value from a `while` loop") .id("E0571") .group( @@ -981,7 +981,7 @@ fn main() { .group( Group::new() .element( - Level::Help + Level::HELP .title("use `break` on its own without a value inside this `while` loop"), ) .element( @@ -1167,7 +1167,7 @@ fn nsize() { } "#; let input = - Level::Error + Level::ERROR .message("`V0usize` cannot be safely transmuted into `[usize; 2]`") .id("E0277") .group( @@ -1183,7 +1183,7 @@ fn nsize() { ) .group( Group::new() - .element(Level::Note.title("required by a bound in `is_transmutable`")) + .element(Level::NOTE.title("required by a bound in `is_transmutable`")) .element( Snippet::source(source) .line_start(1) @@ -1253,7 +1253,7 @@ fn main() { assert::is_maybe_transmutable::<&'static [u8; 0], &'static [u16; 0]>(); //~ ERROR `&[u8; 0]` cannot be safely transmuted into `&[u16; 0]` } "#; - let input = Level::Error + let input = Level::ERROR .message("`&[u8; 0]` cannot be safely transmuted into `&[u16; 0]`") .id("E027s7") .group( @@ -1322,7 +1322,7 @@ fn g() { } fn main() {} "#; - let input = Level::Error + let input = Level::ERROR .message("expected function, found `{integer}`") .id("E0618") .group( @@ -1413,7 +1413,7 @@ macro_rules! outer_macro { outer_macro!(FirstStruct, FirstAttrStruct); "#; - let input = Level::Warning + let input = Level::WARNING .message("non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module") .group( Group::new() @@ -1441,17 +1441,17 @@ outer_macro!(FirstStruct, FirstAttrStruct); ), ) .element( - Level::Help + Level::HELP .title("remove the `#[macro_export]` or move this `macro_rules!` outside the of the current function `main`") ) .element( - Level::Note + Level::NOTE .title("a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute") ), ) .group( Group::new() - .element(Level::Note.title("the lint level is defined here")) + .element(Level::NOTE.title("the lint level is defined here")) .element( Snippet::source(source) .line_start(1) @@ -1546,7 +1546,7 @@ macro_rules! inline { () => () } "#; - let input = Level::Error + let input = Level::ERROR .message("can't call method `pow` on ambiguous numeric type `{integer}`") .id("E0689") .group( @@ -1560,7 +1560,7 @@ macro_rules! inline { ) .group( Group::new() - .element(Level::Help.title("you must specify a type for this binding, like `i32`")) + .element(Level::HELP.title("you must specify a type for this binding, like `i32`")) .element( Snippet::source(aux_source) .line_start(1) @@ -1610,7 +1610,7 @@ fn courier_to_des_moines_and_points_west(data: &[u32]) -> String { fn main() {} "#; - let input = Level::Error + let input = Level::ERROR .message("type annotations needed") .id("E0282") .group( @@ -1716,7 +1716,7 @@ fn nonempty(arrayN_of_empty: [!; N]) { fn main() {} "##; - let input = Level::Error + let input = Level::ERROR .message( "non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered" ) @@ -1736,7 +1736,7 @@ fn main() {} ) .group( Group::new() - .element(Level::Note.title("`NonEmptyEnum5` defined here")) + .element(Level::NOTE.title("`NonEmptyEnum5` defined here")) .element( Snippet::source(source) .line_start(1) @@ -1749,13 +1749,13 @@ fn main() {} .annotation(AnnotationKind::Context.span(878..880).label("not covered")) .annotation(AnnotationKind::Context.span(890..892).label("not covered")) ) - .element(Level::Note.title("the matched value is of type `NonEmptyEnum5`")) - .element(Level::Note.title("match arms with guards don't count towards exhaustivity")) + .element(Level::NOTE.title("the matched value is of type `NonEmptyEnum5`")) + .element(Level::NOTE.title("match arms with guards don't count towards exhaustivity")) ) .group( Group::new() .element( - Level::Help + Level::HELP .title("ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms") ) .element( @@ -1818,7 +1818,7 @@ fn main() { //~^ ERROR must be specified } "#; - let input = Level::Error + let input = Level::ERROR .message("the trait alias `EqAlias` is not dyn compatible") .id("E0038") .group( @@ -1837,7 +1837,7 @@ fn main() { .group( Group::new() .element( - Level::Note + Level::NOTE .title("for a trait to be dyn compatible it needs to allow building a vtable\nfor more information, visit ")) .element( Origin::new("$SRC_DIR/core/src/cmp.rs") From a1a11a53235087853a98c9404627abf90a8d383d Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 16 Apr 2025 15:09:13 -0500 Subject: [PATCH 164/175] fix: Remove unused Level2 --- src/level.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/level.rs b/src/level.rs index 7f92024..81aea8c 100644 --- a/src/level.rs +++ b/src/level.rs @@ -34,16 +34,6 @@ pub struct Level<'a> { pub(crate) level: LevelInner, } -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum Level2<'a> { - Builtin(LevelInner), - Custom { - name: Option<&'a str>, - level: LevelInner, - }, - None, -} - impl<'a> Level<'a> { pub const ERROR: Level<'a> = ERROR; pub const WARNING: Level<'a> = WARNING; From a792c392cd720e11a3a03e2fa2d1fa609979821c Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 16 Apr 2025 15:09:46 -0500 Subject: [PATCH 165/175] fix: Hide LevelInner --- src/level.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/level.rs b/src/level.rs index 81aea8c..46eaef1 100644 --- a/src/level.rs +++ b/src/level.rs @@ -97,7 +97,7 @@ impl<'a> Level<'a> { } #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum LevelInner { +pub(crate) enum LevelInner { Error, Warning, Info, From 1d802c3480aedbebff07ad950c51b86422635b42 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 16 Apr 2025 15:12:03 -0500 Subject: [PATCH 166/175] fix: Re-export Level at the top-level --- benches/bench.rs | 2 +- examples/custom_error.rs | 2 +- examples/custom_level.rs | 2 +- examples/expected_type.rs | 2 +- examples/footer.rs | 2 +- examples/format.rs | 2 +- examples/highlight_source.rs | 2 +- examples/highlight_title.rs | 2 +- examples/multislice.rs | 2 +- src/lib.rs | 2 ++ src/renderer/mod.rs | 2 +- src/renderer/styled_buffer.rs | 2 +- src/snippet.rs | 2 +- tests/fixtures/deserialize.rs | 2 +- tests/formatter.rs | 4 +--- tests/rustc_tests.rs | 2 +- 16 files changed, 17 insertions(+), 17 deletions(-) diff --git a/benches/bench.rs b/benches/bench.rs index d50cf43..a6cdb37 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; #[divan::bench] fn simple() -> String { diff --git a/examples/custom_error.rs b/examples/custom_error.rs index 4050d40..418d342 100644 --- a/examples/custom_error.rs +++ b/examples/custom_error.rs @@ -1,5 +1,5 @@ use annotate_snippets::renderer::OutputTheme; -use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; fn main() { let source = r#"//@ compile-flags: -Ztreat-err-as-bug diff --git a/examples/custom_level.rs b/examples/custom_level.rs index 804f774..87cad9a 100644 --- a/examples/custom_level.rs +++ b/examples/custom_level.rs @@ -1,5 +1,5 @@ use annotate_snippets::renderer::OutputTheme; -use annotate_snippets::{level::Level, AnnotationKind, Group, Patch, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Patch, Renderer, Snippet}; fn main() { let source = r#"// Regression test for issue #114529 diff --git a/examples/expected_type.rs b/examples/expected_type.rs index 9a51dce..5c801c7 100644 --- a/examples/expected_type.rs +++ b/examples/expected_type.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; fn main() { let source = r#" annotations: vec![SourceAnnotation { diff --git a/examples/footer.rs b/examples/footer.rs index d61e84b..95de15c 100644 --- a/examples/footer.rs +++ b/examples/footer.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; fn main() { let message = Level::ERROR diff --git a/examples/format.rs b/examples/format.rs index 5324413..eb68d82 100644 --- a/examples/format.rs +++ b/examples/format.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; fn main() { let source = r#") -> Option { diff --git a/examples/highlight_source.rs b/examples/highlight_source.rs index 9962542..165dd86 100644 --- a/examples/highlight_source.rs +++ b/examples/highlight_source.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; fn main() { let source = r#"//@ compile-flags: -Z teach diff --git a/examples/highlight_title.rs b/examples/highlight_title.rs index e2da54f..ea74612 100644 --- a/examples/highlight_title.rs +++ b/examples/highlight_title.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; use anstyle::Effects; fn main() { diff --git a/examples/multislice.rs b/examples/multislice.rs index ddd938e..9be82e9 100644 --- a/examples/multislice.rs +++ b/examples/multislice.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{level::Level, Annotation, Group, Renderer, Snippet}; +use annotate_snippets::{Annotation, Group, Level, Renderer, Snippet}; fn main() { let message = Level::ERROR.message("mismatched types").group( diff --git a/src/lib.rs b/src/lib.rs index eee2b6f..0d23b29 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,6 +53,8 @@ pub fn normalize_untrusted_str(s: &str) -> String { renderer::normalize_whitespace(s) } +#[doc(inline)] +pub use level::Level; #[doc(inline)] pub use renderer::Renderer; pub use snippet::ColumnSeparator; diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 8efcff8..12fc5d9 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -5,7 +5,7 @@ //! # Example //! ``` //! use annotate_snippets::*; -//! use annotate_snippets::level::Level; +//! use annotate_snippets::Level; //! //! let source = r#" //! use baz::zed::bar; diff --git a/src/renderer/styled_buffer.rs b/src/renderer/styled_buffer.rs index 7114683..c9b805a 100644 --- a/src/renderer/styled_buffer.rs +++ b/src/renderer/styled_buffer.rs @@ -2,9 +2,9 @@ //! //! [styled_buffer]: https://github.com/rust-lang/rust/blob/894f7a4ba6554d3797404bbf550d9919df060b97/compiler/rustc_errors/src/styled_buffer.rs -use crate::level::Level; use crate::renderer::stylesheet::Stylesheet; use crate::renderer::ElementStyle; +use crate::Level; use std::fmt; use std::fmt::Write; diff --git a/src/snippet.rs b/src/snippet.rs index fe1239d..aa5f9ff 100644 --- a/src/snippet.rs +++ b/src/snippet.rs @@ -1,7 +1,7 @@ //! Structures used as an input for the library. -use crate::level::Level; use crate::renderer::source_map::SourceMap; +use crate::Level; use std::ops::Range; pub(crate) const ERROR_TXT: &str = "error"; diff --git a/tests/fixtures/deserialize.rs b/tests/fixtures/deserialize.rs index 8f45b36..55374df 100644 --- a/tests/fixtures/deserialize.rs +++ b/tests/fixtures/deserialize.rs @@ -3,7 +3,7 @@ use std::ops::Range; use annotate_snippets::renderer::DEFAULT_TERM_WIDTH; use annotate_snippets::{ - level::Level, Annotation, AnnotationKind, Element, Group, Message, Patch, Renderer, Snippet, + Annotation, AnnotationKind, Element, Group, Level, Message, Patch, Renderer, Snippet, }; #[derive(Deserialize)] diff --git a/tests/formatter.rs b/tests/formatter.rs index 3f0e7cd..22b517b 100644 --- a/tests/formatter.rs +++ b/tests/formatter.rs @@ -1,6 +1,4 @@ -use annotate_snippets::{ - level::Level, Annotation, AnnotationKind, Group, Patch, Renderer, Snippet, -}; +use annotate_snippets::{Annotation, AnnotationKind, Group, Level, Patch, Renderer, Snippet}; use annotate_snippets::renderer::OutputTheme; use snapbox::{assert_data_eq, str}; diff --git a/tests/rustc_tests.rs b/tests/rustc_tests.rs index 7a795db..93860d0 100644 --- a/tests/rustc_tests.rs +++ b/tests/rustc_tests.rs @@ -2,7 +2,7 @@ //! //! [parser-tests]: https://github.com/rust-lang/rust/blob/894f7a4ba6554d3797404bbf550d9919df060b97/compiler/rustc_parse/src/parser/tests.rs -use annotate_snippets::{level::Level, AnnotationKind, Group, Origin, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Origin, Renderer, Snippet}; use snapbox::{assert_data_eq, str}; From 4c113cca128ffe8e1d62625daddd58ed6181a7db Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 16 Apr 2025 15:23:22 -0500 Subject: [PATCH 167/175] fix!: Rename `Renderer::line_no` to `Renderer::line_num` Fixes #175 --- src/renderer/mod.rs | 8 ++++---- src/renderer/stylesheet.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 12fc5d9..f421c2d 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -101,7 +101,7 @@ impl Renderer { info: BRIGHT_BLUE.effects(Effects::BOLD), note: AnsiColor::BrightGreen.on_default().effects(Effects::BOLD), help: AnsiColor::BrightCyan.on_default().effects(Effects::BOLD), - line_no: BRIGHT_BLUE.effects(Effects::BOLD), + line_num: BRIGHT_BLUE.effects(Effects::BOLD), emphasis: if USE_WINDOWS_COLORS { AnsiColor::BrightWhite.on_default() } else { @@ -178,8 +178,8 @@ impl Renderer { } /// Set the output style for line numbers - pub const fn line_no(mut self, style: Style) -> Self { - self.stylesheet.line_no = style; + pub const fn line_num(mut self, style: Style) -> Self { + self.stylesheet.line_num = style; self } @@ -2665,7 +2665,7 @@ impl ElementStyle { ElementStyle::Addition => stylesheet.addition, ElementStyle::Removal => stylesheet.removal, ElementStyle::LineAndColumn => stylesheet.none, - ElementStyle::LineNumber => stylesheet.line_no, + ElementStyle::LineNumber => stylesheet.line_num, ElementStyle::Quotation => stylesheet.none, ElementStyle::MainHeaderMsg => stylesheet.emphasis, ElementStyle::UnderlinePrimary | ElementStyle::LabelPrimary => level.style(stylesheet), diff --git a/src/renderer/stylesheet.rs b/src/renderer/stylesheet.rs index 4aa21a5..075cad4 100644 --- a/src/renderer/stylesheet.rs +++ b/src/renderer/stylesheet.rs @@ -7,7 +7,7 @@ pub(crate) struct Stylesheet { pub(crate) info: Style, pub(crate) note: Style, pub(crate) help: Style, - pub(crate) line_no: Style, + pub(crate) line_num: Style, pub(crate) emphasis: Style, pub(crate) none: Style, pub(crate) context: Style, @@ -29,7 +29,7 @@ impl Stylesheet { info: Style::new(), note: Style::new(), help: Style::new(), - line_no: Style::new(), + line_num: Style::new(), emphasis: Style::new(), none: Style::new(), context: Style::new(), From f6d191440268c5309c5c70755f1eaf49d2e1db33 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 16 Apr 2025 15:36:57 -0500 Subject: [PATCH 168/175] fix: Clarify ColumnSeparator is Padding --- src/lib.rs | 2 +- src/renderer/mod.rs | 4 ++-- src/snippet.rs | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0d23b29..021ed52 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,5 +57,5 @@ pub fn normalize_untrusted_str(s: &str) -> String { pub use level::Level; #[doc(inline)] pub use renderer::Renderer; -pub use snippet::ColumnSeparator; +pub use snippet::Padding; pub use snippet::*; diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index f421c2d..1e88bca 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -383,7 +383,7 @@ impl Renderer { self.render_origin(buffer, max_line_num_len, origin); last_was_suggestion = false; } - Element::ColumnSeparator(_) => { + Element::Padding(_) => { self.draw_col_separator_no_space( buffer, buffer.num_lines(), @@ -430,7 +430,7 @@ impl Renderer { let (has_primary_spans, has_span_labels) = next_section.map_or((false, false), |s| match s { - Element::Title(_) | Element::ColumnSeparator(_) => (false, false), + Element::Title(_) | Element::Padding(_) => (false, false), Element::Cause(cause) => ( cause.markers.iter().any(|m| m.kind.is_primary()), cause.markers.iter().any(|m| m.label.is_some()), diff --git a/src/snippet.rs b/src/snippet.rs index aa5f9ff..bf22c5b 100644 --- a/src/snippet.rs +++ b/src/snippet.rs @@ -34,7 +34,7 @@ impl<'a> Message<'a> { v.elements .iter() .map(|s| match s { - Element::Title(_) | Element::Origin(_) | Element::ColumnSeparator(_) => 0, + Element::Title(_) | Element::Origin(_) | Element::Padding(_) => 0, Element::Cause(cause) => { let end = cause .markers @@ -104,7 +104,7 @@ pub enum Element<'a> { Cause(Snippet<'a, Annotation<'a>>), Suggestion(Snippet<'a, Patch<'a>>), Origin(Origin<'a>), - ColumnSeparator(ColumnSeparator), + Padding(Padding), } impl<'a> From> for Element<'a> { @@ -131,14 +131,14 @@ impl<'a> From> for Element<'a> { } } -impl From for Element<'_> { - fn from(value: ColumnSeparator) -> Self { - Self::ColumnSeparator(value) +impl From for Element<'_> { + fn from(value: Padding) -> Self { + Self::Padding(value) } } #[derive(Debug)] -pub struct ColumnSeparator; +pub struct Padding; #[derive(Debug)] pub struct Title<'a> { From d3b79b6466562c810d55b3d256de94ce5c352812 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 16 Apr 2025 15:59:54 -0500 Subject: [PATCH 169/175] fix!: Rename Level::title/Level::message to Level::header This doesn't completely take care of #118 because of #196 --- benches/bench.rs | 4 +- examples/custom_error.rs | 2 +- examples/custom_level.rs | 2 +- examples/expected_type.rs | 2 +- examples/footer.rs | 2 +- examples/format.rs | 2 +- examples/highlight_source.rs | 2 +- examples/highlight_title.rs | 2 +- examples/multislice.rs | 2 +- src/level.rs | 4 +- src/renderer/mod.rs | 2 +- tests/fixtures/color/ann_eof.toml | 2 +- tests/fixtures/color/ann_insertion.toml | 2 +- tests/fixtures/color/ann_multiline.toml | 2 +- tests/fixtures/color/ann_multiline2.toml | 2 +- tests/fixtures/color/ann_removed_nl.toml | 2 +- .../color/ensure-emoji-highlight-width.toml | 2 +- tests/fixtures/color/fold_ann_multiline.toml | 2 +- .../fixtures/color/fold_bad_origin_line.toml | 2 +- tests/fixtures/color/fold_leading.toml | 2 +- tests/fixtures/color/fold_trailing.toml | 2 +- tests/fixtures/color/issue_9.toml | 2 +- .../fixtures/color/multiple_annotations.toml | 2 +- tests/fixtures/color/simple.toml | 2 +- tests/fixtures/color/strip_line.toml | 2 +- tests/fixtures/color/strip_line_char.toml | 2 +- tests/fixtures/color/strip_line_non_ws.toml | 2 +- tests/fixtures/deserialize.rs | 6 +- tests/formatter.rs | 124 +++++++++--------- tests/rustc_tests.rs | 64 ++++----- 30 files changed, 126 insertions(+), 126 deletions(-) diff --git a/benches/bench.rs b/benches/bench.rs index a6cdb37..c3799fb 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -24,7 +24,7 @@ fn simple() -> String { _ => continue, } }"#; - let message = Level::ERROR.message("mismatched types").id("E0308").group( + let message = Level::ERROR.header("mismatched types").id("E0308").group( Group::new().element( Snippet::source(source) .line_start(51) @@ -69,7 +69,7 @@ fn fold(bencher: divan::Bencher<'_, '_>, context: usize) { (input, span) }) .bench_values(|(input, span)| { - let message = Level::ERROR.message("mismatched types").id("E0308").group( + let message = Level::ERROR.header("mismatched types").id("E0308").group( Group::new().element( Snippet::source(&input) .fold(true) diff --git a/examples/custom_error.rs b/examples/custom_error.rs index 418d342..b9e27b3 100644 --- a/examples/custom_error.rs +++ b/examples/custom_error.rs @@ -17,7 +17,7 @@ pub static C: u32 = 0 - 1; "#; let message = Level::ERROR .text(Some("error: internal compiler error")) - .message("could not evaluate static initializer") + .header("could not evaluate static initializer") .id("E0080") .group( Group::new().element( diff --git a/examples/custom_level.rs b/examples/custom_level.rs index 87cad9a..b2af361 100644 --- a/examples/custom_level.rs +++ b/examples/custom_level.rs @@ -30,7 +30,7 @@ fn main() { } "#; let message = Level::ERROR - .message("`break` with value from a `while` loop") + .header("`break` with value from a `while` loop") .id("E0571") .group( Group::new().element( diff --git a/examples/expected_type.rs b/examples/expected_type.rs index 5c801c7..02abdec 100644 --- a/examples/expected_type.rs +++ b/examples/expected_type.rs @@ -6,7 +6,7 @@ fn main() { , range: <22, 25>,"#; let message = - Level::ERROR.message("expected type, found `22`").group( + Level::ERROR.header("expected type, found `22`").group( Group::new().element( Snippet::source(source) .line_start(26) diff --git a/examples/footer.rs b/examples/footer.rs index 95de15c..ca6f1dc 100644 --- a/examples/footer.rs +++ b/examples/footer.rs @@ -2,7 +2,7 @@ use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; fn main() { let message = Level::ERROR - .message("mismatched types") + .header("mismatched types") .id("E0308") .group( Group::new().element( diff --git a/examples/format.rs b/examples/format.rs index eb68d82..4b688d4 100644 --- a/examples/format.rs +++ b/examples/format.rs @@ -23,7 +23,7 @@ fn main() { _ => continue, } }"#; - let message = Level::ERROR.message("mismatched types").id("E0308").group( + let message = Level::ERROR.header("mismatched types").id("E0308").group( Group::new().element( Snippet::source(source) .line_start(51) diff --git a/examples/highlight_source.rs b/examples/highlight_source.rs index 165dd86..92d8114 100644 --- a/examples/highlight_source.rs +++ b/examples/highlight_source.rs @@ -10,7 +10,7 @@ const CON: Vec = vec![1, 2, 3]; //~ ERROR E0010 fn main() {} "#; let message = Level::ERROR - .message("allocations are not allowed in constants") + .header("allocations are not allowed in constants") .id("E0010") .group( Group::new() diff --git a/examples/highlight_title.rs b/examples/highlight_title.rs index ea74612..12c106a 100644 --- a/examples/highlight_title.rs +++ b/examples/highlight_title.rs @@ -43,7 +43,7 @@ fn main() { magenta.render_reset() ); - let message = Level::ERROR.message("mismatched types").id("E0308").group( + let message = Level::ERROR.header("mismatched types").id("E0308").group( Group::new() .element( Snippet::source(source) diff --git a/examples/multislice.rs b/examples/multislice.rs index 9be82e9..a7d340a 100644 --- a/examples/multislice.rs +++ b/examples/multislice.rs @@ -1,7 +1,7 @@ use annotate_snippets::{Annotation, Group, Level, Renderer, Snippet}; fn main() { - let message = Level::ERROR.message("mismatched types").group( + let message = Level::ERROR.header("mismatched types").group( Group::new() .element( Snippet::>::source("Foo") diff --git a/src/level.rs b/src/level.rs index 46eaef1..3fd504d 100644 --- a/src/level.rs +++ b/src/level.rs @@ -56,12 +56,12 @@ impl<'a> Level<'a> { /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. - pub fn message(self, title: &'a str) -> Message<'a> { + pub fn header(self, header: &'a str) -> Message<'a> { Message { id: None, groups: vec![Group::new().element(Element::Title(Title { level: self, - title, + title: header, primary: true, }))], } diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 1e88bca..e5572e5 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -19,7 +19,7 @@ //! } //! "#; //! Level::ERROR -//! .message("unresolved import `baz::zed`") +//! .header("unresolved import `baz::zed`") //! .id("E0432") //! .group( //! Group::new().element( diff --git a/tests/fixtures/color/ann_eof.toml b/tests/fixtures/color/ann_eof.toml index ac129f3..ef711de 100644 --- a/tests/fixtures/color/ann_eof.toml +++ b/tests/fixtures/color/ann_eof.toml @@ -1,6 +1,6 @@ [message] level = "Error" -title = "expected `.`, `=`" +header = "expected `.`, `=`" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/ann_insertion.toml b/tests/fixtures/color/ann_insertion.toml index 13bc13c..30af1bf 100644 --- a/tests/fixtures/color/ann_insertion.toml +++ b/tests/fixtures/color/ann_insertion.toml @@ -1,6 +1,6 @@ [message] level = "Error" -title = "expected `.`, `=`" +header = "expected `.`, `=`" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/ann_multiline.toml b/tests/fixtures/color/ann_multiline.toml index 722c3e1..2a5f206 100644 --- a/tests/fixtures/color/ann_multiline.toml +++ b/tests/fixtures/color/ann_multiline.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E0027" -title = "pattern does not mention fields `lineno`, `content`" +header = "pattern does not mention fields `lineno`, `content`" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/ann_multiline2.toml b/tests/fixtures/color/ann_multiline2.toml index 329beb4..854b38a 100644 --- a/tests/fixtures/color/ann_multiline2.toml +++ b/tests/fixtures/color/ann_multiline2.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E####" -title = "spacing error found" +header = "spacing error found" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/ann_removed_nl.toml b/tests/fixtures/color/ann_removed_nl.toml index 8ed96bc..6ffeb7a 100644 --- a/tests/fixtures/color/ann_removed_nl.toml +++ b/tests/fixtures/color/ann_removed_nl.toml @@ -1,6 +1,6 @@ [message] level = "Error" -title = "expected `.`, `=`" +header = "expected `.`, `=`" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/ensure-emoji-highlight-width.toml b/tests/fixtures/color/ensure-emoji-highlight-width.toml index 8d7a14a..669959f 100644 --- a/tests/fixtures/color/ensure-emoji-highlight-width.toml +++ b/tests/fixtures/color/ensure-emoji-highlight-width.toml @@ -1,5 +1,5 @@ [message] -title = "invalid character ` ` in package name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)" +header = "invalid character ` ` in package name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)" level = "Error" diff --git a/tests/fixtures/color/fold_ann_multiline.toml b/tests/fixtures/color/fold_ann_multiline.toml index 745ef42..2cee27d 100644 --- a/tests/fixtures/color/fold_ann_multiline.toml +++ b/tests/fixtures/color/fold_ann_multiline.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E0308" -title = "mismatched types" +header = "mismatched types" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/fold_bad_origin_line.toml b/tests/fixtures/color/fold_bad_origin_line.toml index 3b0d827..2fab2d6 100644 --- a/tests/fixtures/color/fold_bad_origin_line.toml +++ b/tests/fixtures/color/fold_bad_origin_line.toml @@ -1,6 +1,6 @@ [message] level = "Error" -title = "" +header = "" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/fold_leading.toml b/tests/fixtures/color/fold_leading.toml index 564187b..0ef043c 100644 --- a/tests/fixtures/color/fold_leading.toml +++ b/tests/fixtures/color/fold_leading.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E0308" -title = "invalid type: integer `20`, expected a bool" +header = "invalid type: integer `20`, expected a bool" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/fold_trailing.toml b/tests/fixtures/color/fold_trailing.toml index eea6365..91e4ab4 100644 --- a/tests/fixtures/color/fold_trailing.toml +++ b/tests/fixtures/color/fold_trailing.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E0308" -title = "invalid type: integer `20`, expected a lints table" +header = "invalid type: integer `20`, expected a lints table" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/issue_9.toml b/tests/fixtures/color/issue_9.toml index 96ad2c0..f423915 100644 --- a/tests/fixtures/color/issue_9.toml +++ b/tests/fixtures/color/issue_9.toml @@ -1,6 +1,6 @@ [message] level = "Error" -title = "expected one of `.`, `;`, `?`, or an operator, found `for`" +header = "expected one of `.`, `;`, `?`, or an operator, found `for`" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/multiple_annotations.toml b/tests/fixtures/color/multiple_annotations.toml index f4c90a4..367c53e 100644 --- a/tests/fixtures/color/multiple_annotations.toml +++ b/tests/fixtures/color/multiple_annotations.toml @@ -1,6 +1,6 @@ [message] level = "Error" -title = "" +header = "" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/simple.toml b/tests/fixtures/color/simple.toml index b70f11c..d5a3647 100644 --- a/tests/fixtures/color/simple.toml +++ b/tests/fixtures/color/simple.toml @@ -1,6 +1,6 @@ [message] level = "Error" -title = "expected one of `.`, `;`, `?`, or an operator, found `for`" +header = "expected one of `.`, `;`, `?`, or an operator, found `for`" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/strip_line.toml b/tests/fixtures/color/strip_line.toml index d7af686..18a7805 100644 --- a/tests/fixtures/color/strip_line.toml +++ b/tests/fixtures/color/strip_line.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E0308" -title = "mismatched types" +header = "mismatched types" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/strip_line_char.toml b/tests/fixtures/color/strip_line_char.toml index 6585005..3174ced 100644 --- a/tests/fixtures/color/strip_line_char.toml +++ b/tests/fixtures/color/strip_line_char.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E0308" -title = "mismatched types" +header = "mismatched types" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/strip_line_non_ws.toml b/tests/fixtures/color/strip_line_non_ws.toml index 1f085b5..b7844ec 100644 --- a/tests/fixtures/color/strip_line_non_ws.toml +++ b/tests/fixtures/color/strip_line_non_ws.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E0308" -title = "mismatched types" +header = "mismatched types" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/deserialize.rs b/tests/fixtures/deserialize.rs index 55374df..2042966 100644 --- a/tests/fixtures/deserialize.rs +++ b/tests/fixtures/deserialize.rs @@ -16,7 +16,7 @@ pub(crate) struct Fixture { #[derive(Deserialize)] pub struct MessageDef { pub level: LevelDef, - pub title: String, + pub header: String, #[serde(default)] pub id: Option, #[serde(default)] @@ -27,11 +27,11 @@ impl<'a> From<&'a MessageDef> for Message<'a> { fn from(val: &'a MessageDef) -> Self { let MessageDef { level, - title, + header, id, sections, } = val; - let mut message = Level::from(level).message(title); + let mut message = Level::from(level).header(header); if let Some(id) = id { message = message.id(id); } diff --git a/tests/formatter.rs b/tests/formatter.rs index 22b517b..75cf853 100644 --- a/tests/formatter.rs +++ b/tests/formatter.rs @@ -5,7 +5,7 @@ use snapbox::{assert_data_eq, str}; #[test] fn test_i_29() { - let snippets = Level::ERROR.message("oops").group( + let snippets = Level::ERROR.header("oops").group( Group::new().element( Snippet::source("First line\r\nSecond oops line") .origin("") @@ -27,7 +27,7 @@ error: oops #[test] fn test_point_to_double_width_characters() { - let snippets = Level::ERROR.message("").group( + let snippets = Level::ERROR.header("").group( Group::new().element( Snippet::source("こんにちは、世界") .origin("") @@ -49,7 +49,7 @@ error: #[test] fn test_point_to_double_width_characters_across_lines() { - let snippets = Level::ERROR.message("").group( + let snippets = Level::ERROR.header("").group( Group::new().element( Snippet::source("おはよう\nございます") .origin("") @@ -73,7 +73,7 @@ error: #[test] fn test_point_to_double_width_characters_multiple() { - let snippets = Level::ERROR.message("").group( + let snippets = Level::ERROR.header("").group( Group::new().element( Snippet::source("お寿司\n食べたい🍣") .origin("") @@ -98,7 +98,7 @@ error: #[test] fn test_point_to_double_width_characters_mixed() { - let snippets = Level::ERROR.message("").group( + let snippets = Level::ERROR.header("").group( Group::new().element( Snippet::source("こんにちは、新しいWorld!") .origin("") @@ -120,7 +120,7 @@ error: #[test] fn test_format_title() { - let input = Level::ERROR.message("This is a title").id("E0001"); + let input = Level::ERROR.header("This is a title").id("E0001"); let expected = str![r#"error[E0001]: This is a title"#]; let renderer = Renderer::plain(); @@ -131,7 +131,7 @@ fn test_format_title() { fn test_format_snippet_only() { let source = "This is line 1\nThis is line 2"; let input = Level::ERROR - .message("") + .header("") .group(Group::new().element(Snippet::>::source(source).line_start(5402))); let expected = str![[r#" @@ -148,7 +148,7 @@ error: fn test_format_snippets_continuation() { let src_0 = "This is slice 1"; let src_1 = "This is slice 2"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new() .element( Snippet::>::source(src_0) @@ -182,7 +182,7 @@ fn test_format_snippet_annotation_standalone() { let source = [line_1, line_2].join("\n"); // In line 2 let range = 22..24; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(&source).line_start(5402).annotation( AnnotationKind::Context @@ -205,7 +205,7 @@ error: #[test] fn test_format_footer_title() { let input = Level::ERROR - .message("") + .header("") .group(Group::new().element(Level::ERROR.title("This __is__ a title"))); let expected = str![[r#" error: @@ -221,7 +221,7 @@ error: fn test_i26() { let source = "short"; let label = "label"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source).line_start(0).annotation( AnnotationKind::Primary @@ -238,7 +238,7 @@ fn test_i26() { fn test_source_content() { let source = "This is an example\nof content lines"; let input = Level::ERROR - .message("") + .header("") .group(Group::new().element(Snippet::>::source(source).line_start(56))); let expected = str![[r#" error: @@ -253,7 +253,7 @@ error: #[test] fn test_source_annotation_standalone_singleline() { let source = "tests"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -273,7 +273,7 @@ error: #[test] fn test_source_annotation_standalone_multiline() { let source = "tests"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -297,7 +297,7 @@ error: #[test] fn test_only_source() { let input = Level::ERROR - .message("") + .header("") .group(Group::new().element(Snippet::>::source("").origin("file.rs"))); let expected = str![[r#" error: @@ -312,7 +312,7 @@ error: fn test_anon_lines() { let source = "This is an example\nof content lines\n\nabc"; let input = Level::ERROR - .message("") + .header("") .group(Group::new().element(Snippet::>::source(source).line_start(56))); let expected = str![[r#" error: @@ -328,7 +328,7 @@ LL | abc #[test] fn issue_130() { - let input = Level::ERROR.message("dummy").group( + let input = Level::ERROR.header("dummy").group( Group::new().element( Snippet::source("foo\nbar\nbaz") .origin("file/path") @@ -356,7 +356,7 @@ fn unterminated_string_multiline() { a\" // ... "; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -380,7 +380,7 @@ error: #[test] fn char_and_nl_annotate_char() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -403,7 +403,7 @@ error: #[test] fn char_eol_annotate_char() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -425,7 +425,7 @@ error: #[test] fn char_eol_annotate_char_double_width() { - let snippets = Level::ERROR.message("").group( + let snippets = Level::ERROR.header("").group( Group::new().element( Snippet::source("こん\r\nにちは\r\n世界") .origin("") @@ -450,7 +450,7 @@ error: #[test] fn annotate_eol() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -473,7 +473,7 @@ error: #[test] fn annotate_eol2() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -496,7 +496,7 @@ error: #[test] fn annotate_eol3() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -519,7 +519,7 @@ error: #[test] fn annotate_eol4() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -541,7 +541,7 @@ error: #[test] fn annotate_eol_double_width() { - let snippets = Level::ERROR.message("").group( + let snippets = Level::ERROR.header("").group( Group::new().element( Snippet::source("こん\r\nにちは\r\n世界") .origin("") @@ -566,7 +566,7 @@ error: #[test] fn multiline_eol_start() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -590,7 +590,7 @@ error: #[test] fn multiline_eol_start2() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -614,7 +614,7 @@ error: #[test] fn multiline_eol_start3() { let source = "a\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -637,7 +637,7 @@ error: #[test] fn multiline_eol_start_double_width() { - let snippets = Level::ERROR.message("").group( + let snippets = Level::ERROR.header("").group( Group::new().element( Snippet::source("こん\r\nにちは\r\n世界") .origin("") @@ -663,7 +663,7 @@ error: #[test] fn multiline_eol_start_eol_end() { let source = "a\nb\nc"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -688,7 +688,7 @@ error: #[test] fn multiline_eol_start_eol_end2() { let source = "a\r\nb\r\nc"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -713,7 +713,7 @@ error: #[test] fn multiline_eol_start_eol_end3() { let source = "a\r\nb\r\nc"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -738,7 +738,7 @@ error: #[test] fn multiline_eol_start_eof_end() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -762,7 +762,7 @@ error: #[test] fn multiline_eol_start_eof_end_double_width() { let source = "ん\r\nに"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -786,7 +786,7 @@ error: #[test] fn two_single_line_same_line() { let source = r#"bar = { version = "0.1.0", optional = true }"#; - let input = Level::ERROR.message("unused optional dependency").group( + let input = Level::ERROR.header("unused optional dependency").group( Group::new().element( Snippet::source(source) .origin("Cargo.toml") @@ -823,7 +823,7 @@ this is another line so is this bar = { version = "0.1.0", optional = true } "#; - let input = Level::ERROR.message("unused optional dependency").group( + let input = Level::ERROR.header("unused optional dependency").group( Group::new().element( Snippet::source(source) .line_start(4) @@ -862,7 +862,7 @@ this is another line so is this bar = { version = "0.1.0", optional = true } "#; - let input = Level::ERROR.message("unused optional dependency").group( + let input = Level::ERROR.header("unused optional dependency").group( Group::new().element( Snippet::source(source) .line_start(4) @@ -910,7 +910,7 @@ so is this bar = { version = "0.1.0", optional = true } this is another line "#; - let input = Level::ERROR.message("unused optional dependency").group( + let input = Level::ERROR.header("unused optional dependency").group( Group::new().element( Snippet::source(source) .line_start(4) @@ -961,7 +961,7 @@ error: unused optional dependency #[test] fn origin_correct_start_line() { let source = "aaa\nbbb\nccc\nddd\n"; - let input = Level::ERROR.message("title").group( + let input = Level::ERROR.header("title").group( Group::new().element( Snippet::source(source) .origin("origin.txt") @@ -987,7 +987,7 @@ error: title #[test] fn origin_correct_mid_line() { let source = "aaa\nbbb\nccc\nddd\n"; - let input = Level::ERROR.message("title").group( + let input = Level::ERROR.header("title").group( Group::new().element( Snippet::source(source) .origin("origin.txt") @@ -1018,7 +1018,7 @@ error: title fn two_suggestions_same_span() { let source = r#" A.foo();"#; let input_new = Level::ERROR - .message("expected value, found enum `A`") + .header("expected value, found enum `A`") .id("E0423") .group( Group::new().element( @@ -1086,7 +1086,7 @@ fn main() { }"#; let input_new = Level::ERROR - .message("no method named `pick` found for struct `Chaenomeles` in the current scope") + .header("no method named `pick` found for struct `Chaenomeles` in the current scope") .id("E0599") .group( Group::new().element( @@ -1146,7 +1146,7 @@ fn single_line_non_overlapping_suggestions() { let source = r#" A.foo();"#; let input_new = Level::ERROR - .message("expected value, found enum `A`") + .header("expected value, found enum `A`") .id("E0423") .group( Group::new().element( @@ -1188,7 +1188,7 @@ LL + (A::Tuple()).bar(); fn single_line_non_overlapping_suggestions2() { let source = r#" ThisIsVeryLong.foo();"#; let input_new = Level::ERROR - .message("Found `ThisIsVeryLong`") + .header("Found `ThisIsVeryLong`") .id("E0423") .group( Group::new().element( @@ -1237,7 +1237,7 @@ fn multiple_replacements() { "#; let input_new = Level::ERROR - .message("cannot borrow `*self` as mutable because it is also borrowed as immutable") + .header("cannot borrow `*self` as mutable because it is also borrowed as immutable") .id("E0502") .group( Group::new().element( @@ -1321,7 +1321,7 @@ fn main() { }"#; let input_new = Level::ERROR - .message("cannot borrow `chars` as mutable more than once at a time") + .header("cannot borrow `chars` as mutable more than once at a time") .id("E0499") .group( Group::new().element( @@ -1405,7 +1405,7 @@ struct Foo { fn main() {}"#; let input_new = Level::ERROR - .message("failed to resolve: use of undeclared crate or module `st`") + .header("failed to resolve: use of undeclared crate or module `st`") .id("E0433") .group( Group::new().element( @@ -1487,7 +1487,7 @@ where fn main() {}"#; let input_new = Level::ERROR - .message("the size for values of type `T` cannot be known at compilation time") + .header("the size for values of type `T` cannot be known at compilation time") .id("E0277") .group( Group::new().element( @@ -1556,7 +1556,7 @@ and where fn main() {}"#; let input_new = Level::ERROR - .message("the size for values of type `T` cannot be known at compilation time") + .header("the size for values of type `T` cannot be known at compilation time") .id("E0277") .group(Group::new().element(Snippet::source(source) .line_start(1) @@ -1661,7 +1661,7 @@ zappy "#; let input_new = Level::ERROR - .message("the size for values of type `T` cannot be known at compilation time") + .header("the size for values of type `T` cannot be known at compilation time") .id("E0277") .group( Group::new() @@ -1729,7 +1729,7 @@ fn main() { "#; let input_new = Level::ERROR - .message("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") + .header("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") .id("E0271") .group(Group::new().element(Snippet::source(source) .line_start(4) @@ -1817,7 +1817,7 @@ fn main() { "#; let input_new = Level::ERROR - .message("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") + .header("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") .id("E0271") .group(Group::new().element(Snippet::source(source) .line_start(4) @@ -1970,7 +1970,7 @@ fn main() { "#; let input_new = Level::ERROR - .message("mismatched types") + .header("mismatched types") .id("E0308") .group(Group::new().element( Snippet::source(source) @@ -2054,7 +2054,7 @@ fn main() { "#; let input_new = Level::ERROR - .message("mismatched types") + .header("mismatched types") .id("E0308") .group(Group::new().element( Snippet::source(source) @@ -2122,7 +2122,7 @@ LL │ ┃ )>>) {} #[test] fn unicode_cut_handling() { let source = "version = \"0.1.0\"\n# Ensure that the spans from toml handle utf-8 correctly\nauthors = [\n { name = \"Z\u{351}\u{36b}\u{343}\u{36a}\u{302}\u{36b}\u{33d}\u{34f}\u{334}\u{319}\u{324}\u{31e}\u{349}\u{35a}\u{32f}\u{31e}\u{320}\u{34d}A\u{36b}\u{357}\u{334}\u{362}\u{335}\u{31c}\u{330}\u{354}L\u{368}\u{367}\u{369}\u{358}\u{320}G\u{311}\u{357}\u{30e}\u{305}\u{35b}\u{341}\u{334}\u{33b}\u{348}\u{34d}\u{354}\u{339}O\u{342}\u{30c}\u{30c}\u{358}\u{328}\u{335}\u{339}\u{33b}\u{31d}\u{333}\", email = 1 }\n]\n"; - let input = Level::ERROR.message("title").group( + let input = Level::ERROR.header("title").group( Group::new().element( Snippet::source(source) .fold(false) @@ -2148,7 +2148,7 @@ error: title fn unicode_cut_handling2() { let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?"; let input = Level::ERROR - .message("expected item, found `?`") + .header("expected item, found `?`") .group( Group::new().element( Snippet::source(source) @@ -2175,7 +2175,7 @@ error: expected item, found `?` fn unicode_cut_handling3() { let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?"; let input = Level::ERROR - .message("expected item, found `?`") + .header("expected item, found `?`") .group( Group::new().element( Snippet::source(source) @@ -2202,7 +2202,7 @@ error: expected item, found `?` fn unicode_cut_handling4() { let source = "/*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/?"; let input = Level::ERROR - .message("expected item, found `?`") + .header("expected item, found `?`") .group( Group::new().element( Snippet::source(source) @@ -2234,7 +2234,7 @@ fn main() { //~^ ERROR mismatched types } "##; - let input = Level::ERROR.message("mismatched types").id("E0308").group( + let input = Level::ERROR.header("mismatched types").id("E0308").group( Group::new().element( Snippet::source(source) .origin("$DIR/non-whitespace-trimming-unicode.rs") @@ -2279,7 +2279,7 @@ fn main() { } "##; let input = Level::ERROR - .message("cannot add `&str` to `&str`") + .header("cannot add `&str` to `&str`") .id("E0369") .group( Group::new() @@ -2346,7 +2346,7 @@ fn foo() { "##; let bin_source = "�|�\u{0002}!5�cc\u{0015}\u{0002}�Ӻi��WWj�ȥ�'�}�\u{0012}�J�ȉ��W�\u{001e}O�@����\u{001c}w�V���LO����\u{0014}[ \u{0003}_�'���SQ�~ذ��ų&��-\t��lN~��!@␌ _#���kQ��h�\u{001d}�:�\u{001c}\u{0007}�"; let input = Level::ERROR - .message("couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8") + .header("couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8") .group( Group::new().element( Snippet::source(source) diff --git a/tests/rustc_tests.rs b/tests/rustc_tests.rs index 93860d0..6998629 100644 --- a/tests/rustc_tests.rs +++ b/tests/rustc_tests.rs @@ -12,7 +12,7 @@ fn ends_on_col0() { fn foo() { } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -42,7 +42,7 @@ fn foo() { } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -74,7 +74,7 @@ fn foo() { X2 Y2 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -117,7 +117,7 @@ fn foo() { Y1 X1 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -161,7 +161,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -205,7 +205,7 @@ fn foo() { X2 Y2 Z2 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -252,7 +252,7 @@ fn foo() { X2 Y2 Z2 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -300,7 +300,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -350,7 +350,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -394,7 +394,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -437,7 +437,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -470,7 +470,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -502,7 +502,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -537,7 +537,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -571,7 +571,7 @@ fn foo() { a bc d } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -605,7 +605,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -633,7 +633,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -662,7 +662,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -701,7 +701,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -732,7 +732,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -772,7 +772,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -832,7 +832,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -887,7 +887,7 @@ fn issue_91334() { fn f(){||yield(((){), "#; let input = Level::ERROR - .message("this file contains an unclosed delimiter") + .header("this file contains an unclosed delimiter") .group( Group::new().element( Snippet::source(source) @@ -958,7 +958,7 @@ fn main() { } "#; let input = Level::ERROR - .message("`break` with value from a `while` loop") + .header("`break` with value from a `while` loop") .id("E0571") .group( Group::new().element( @@ -1168,7 +1168,7 @@ fn nsize() { "#; let input = Level::ERROR - .message("`V0usize` cannot be safely transmuted into `[usize; 2]`") + .header("`V0usize` cannot be safely transmuted into `[usize; 2]`") .id("E0277") .group( Group::new().element( @@ -1254,7 +1254,7 @@ fn main() { } "#; let input = Level::ERROR - .message("`&[u8; 0]` cannot be safely transmuted into `&[u16; 0]`") + .header("`&[u8; 0]` cannot be safely transmuted into `&[u16; 0]`") .id("E027s7") .group( Group::new().element( @@ -1323,7 +1323,7 @@ fn g() { fn main() {} "#; let input = Level::ERROR - .message("expected function, found `{integer}`") + .header("expected function, found `{integer}`") .id("E0618") .group( Group::new().element( @@ -1414,7 +1414,7 @@ macro_rules! outer_macro { outer_macro!(FirstStruct, FirstAttrStruct); "#; let input = Level::WARNING - .message("non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module") + .header("non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module") .group( Group::new() .element( @@ -1547,7 +1547,7 @@ macro_rules! inline { } "#; let input = Level::ERROR - .message("can't call method `pow` on ambiguous numeric type `{integer}`") + .header("can't call method `pow` on ambiguous numeric type `{integer}`") .id("E0689") .group( Group::new().element( @@ -1611,7 +1611,7 @@ fn main() {} "#; let input = Level::ERROR - .message("type annotations needed") + .header("type annotations needed") .id("E0282") .group( Group::new().element( @@ -1717,7 +1717,7 @@ fn main() {} "##; let input = Level::ERROR - .message( + .header( "non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered" ) .id("E0004") @@ -1819,7 +1819,7 @@ fn main() { } "#; let input = Level::ERROR - .message("the trait alias `EqAlias` is not dyn compatible") + .header("the trait alias `EqAlias` is not dyn compatible") .id("E0038") .group( Group::new().element( From a928524d03391efbc6952b09670737b84d6c8d8a Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 16 Apr 2025 16:11:38 -0500 Subject: [PATCH 170/175] refactor: Remove redundant re-export --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 021ed52..76836d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,5 +57,4 @@ pub fn normalize_untrusted_str(s: &str) -> String { pub use level::Level; #[doc(inline)] pub use renderer::Renderer; -pub use snippet::Padding; pub use snippet::*; From 21ca62eaf23d9fabd75ad787b9c8cde541d60213 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 16 Apr 2025 16:33:28 -0500 Subject: [PATCH 171/175] docs: Rename 'range' parameter to 'span' --- src/renderer/mod.rs | 14 +++++++------- src/renderer/source_map.rs | 18 +++++++++--------- src/snippet.rs | 24 ++++++++++++------------ 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index e5572e5..be2abab 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -1523,7 +1523,7 @@ impl Renderer { } if suggestion.origin != primary_origin { if let Some(origin) = suggestion.origin { - let (loc, _) = sm.span_to_locations(parts[0].range.clone()); + let (loc, _) = sm.span_to_locations(parts[0].span.clone()); // --> file.rs:line:col // | let arrow = self.file_start(); @@ -1563,8 +1563,8 @@ impl Renderer { row_num += 1; } - let file_lines = sm.span_to_lines(parts[0].range.clone()); - let (line_start, line_end) = sm.span_to_locations(parts[0].range.clone()); + let file_lines = sm.span_to_lines(parts[0].span.clone()); + let (line_start, line_end) = sm.span_to_locations(parts[0].span.clone()); let mut lines = complete.lines(); if lines.clone().next().is_none() { // Account for a suggestion to completely remove a line(s) with whitespace (#94192). @@ -1697,8 +1697,8 @@ impl Renderer { // already existing code, despite the colors and UI elements. // We special case `#[derive(_)]\n` and other attribute suggestions, because those // are the ones where context is most useful. - let file_lines = sm.span_to_lines(parts[0].range.end..parts[0].range.end); - let (lo, _) = sm.span_to_locations(parts[0].range.clone()); + let file_lines = sm.span_to_lines(parts[0].span.end..parts[0].span.end); + let (lo, _) = sm.span_to_locations(parts[0].span.clone()); let line_num = lo.line; if let Some(line) = sm.get_line(line_num) { let line = normalize_whitespace(line); @@ -1724,7 +1724,7 @@ impl Renderer { show_code_change { for part in parts { - let (span_start, span_end) = sm.span_to_locations(part.range.clone()); + let (span_start, span_end) = sm.span_to_locations(part.span.clone()); let span_start_pos = span_start.display; let span_end_pos = span_end.display; @@ -1764,7 +1764,7 @@ impl Renderer { let padding: usize = max_line_num_len + 3; for p in underline_start..underline_end { if matches!(show_code_change, DisplaySuggestion::Underline) - && is_different(sm, part.replacement, part.range.clone()) + && is_different(sm, part.replacement, part.span.clone()) { // If this is a replacement, underline with `~`, if this is an addition // underline with `+`. diff --git a/src/renderer/source_map.rs b/src/renderer/source_map.rs index 33fe189..d014bb0 100644 --- a/src/renderer/source_map.rs +++ b/src/renderer/source_map.rs @@ -129,8 +129,8 @@ impl<'a> SourceMap<'a> { let source_len = self.source.len(); if let Some(bigger) = annotations.iter().find_map(|x| { // Allow highlighting one past the last character in the source. - if source_len + 1 < x.range.end { - Some(&x.range) + if source_len + 1 < x.span.end { + Some(&x.span) } else { None } @@ -150,13 +150,13 @@ impl<'a> SourceMap<'a> { let mut multiline_annotations = vec![]; for Annotation { - range, + span, label, kind, highlight_source, } in annotations { - let (lo, mut hi) = self.span_to_locations(range.clone()); + let (lo, mut hi) = self.span_to_locations(span.clone()); // Watch out for "empty spans". If we get a span like 6..6, we // want to just display a `^` at 6, so convert that to @@ -374,13 +374,13 @@ impl<'a> SourceMap<'a> { } // Assumption: all spans are in the same file, and all spans // are disjoint. Sort in ascending order. - patches.sort_by_key(|p| p.range.start); + patches.sort_by_key(|p| p.span.start); // Find the bounding span. - let Some(lo) = patches.iter().map(|p| p.range.start).min() else { + let Some(lo) = patches.iter().map(|p| p.span.start).min() else { return Vec::new(); }; - let Some(hi) = patches.iter().map(|p| p.range.end).max() else { + let Some(hi) = patches.iter().map(|p| p.span.end).max() else { return Vec::new(); }; @@ -410,7 +410,7 @@ impl<'a> SourceMap<'a> { // suggestion and snippet to look as if we just suggested to add // `"b"`, which is typically much easier for the user to understand. part.trim_trivial_replacements(self); - let (cur_lo, cur_hi) = self.span_to_locations(part.range.clone()); + let (cur_lo, cur_hi) = self.span_to_locations(part.span.clone()); if prev_hi.line == cur_lo.line { let mut count = push_trailing(&mut buf, prev_line, &prev_hi, Some(&cur_lo)); while count > 0 { @@ -454,7 +454,7 @@ impl<'a> SourceMap<'a> { _ => 1, }) .sum(); - if !is_different(self, part.replacement, part.range.clone()) { + if !is_different(self, part.replacement, part.span.clone()) { // Account for cases where we are suggesting the same code that's already // there. This shouldn't happen often, but in some cases for multipart // suggestions it's much easier to handle it here than in the origin. diff --git a/src/snippet.rs b/src/snippet.rs index bf22c5b..f37a048 100644 --- a/src/snippet.rs +++ b/src/snippet.rs @@ -39,7 +39,7 @@ impl<'a> Message<'a> { let end = cause .markers .iter() - .map(|a| a.range.end) + .map(|a| a.span.end) .max() .unwrap_or(cause.source.len()) .min(cause.source.len()); @@ -50,7 +50,7 @@ impl<'a> Message<'a> { let end = suggestion .markers .iter() - .map(|a| a.range.end) + .map(|a| a.span.end) .max() .unwrap_or(suggestion.source.len()) .min(suggestion.source.len()); @@ -222,7 +222,7 @@ impl<'a> Snippet<'a, Patch<'a>> { #[derive(Clone, Debug)] pub struct Annotation<'a> { - pub(crate) range: Range, + pub(crate) span: Range, pub(crate) label: Option<&'a str>, pub(crate) kind: AnnotationKind, pub(crate) highlight_source: bool, @@ -254,7 +254,7 @@ pub enum AnnotationKind { impl AnnotationKind { pub fn span<'a>(self, span: Range) -> Annotation<'a> { Annotation { - range: span, + span, label: None, kind: self, highlight_source: false, @@ -268,7 +268,7 @@ impl AnnotationKind { #[derive(Clone, Debug)] pub struct Patch<'a> { - pub(crate) range: Range, + pub(crate) span: Range, pub(crate) replacement: &'a str, } @@ -276,8 +276,8 @@ impl<'a> Patch<'a> { /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. - pub fn new(range: Range, replacement: &'a str) -> Self { - Self { range, replacement } + pub fn new(span: Range, replacement: &'a str) -> Self { + Self { span, replacement } } pub(crate) fn is_addition(&self, sm: &SourceMap<'_>) -> bool { @@ -299,7 +299,7 @@ impl<'a> Patch<'a> { pub(crate) fn is_destructive_replacement(&self, sm: &SourceMap<'_>) -> bool { self.is_replacement(sm) && !sm - .span_to_snippet(self.range.clone()) + .span_to_snippet(self.span.clone()) // This should use `is_some_and` when our MSRV is >= 1.70 .map_or(false, |s| { as_substr(s.trim(), self.replacement.trim()).is_some() @@ -307,8 +307,8 @@ impl<'a> Patch<'a> { } fn replaces_meaningful_content(&self, sm: &SourceMap<'_>) -> bool { - sm.span_to_snippet(self.range.clone()) - .map_or(!self.range.is_empty(), |snippet| !snippet.trim().is_empty()) + sm.span_to_snippet(self.span.clone()) + .map_or(!self.span.is_empty(), |snippet| !snippet.trim().is_empty()) } /// Try to turn a replacement into an addition when the span that is being @@ -317,12 +317,12 @@ impl<'a> Patch<'a> { if self.replacement.is_empty() { return; } - let Some(snippet) = sm.span_to_snippet(self.range.clone()) else { + let Some(snippet) = sm.span_to_snippet(self.span.clone()) else { return; }; if let Some((prefix, substr, suffix)) = as_substr(snippet, self.replacement) { - self.range = self.range.start + prefix..self.range.end.saturating_sub(suffix); + self.span = self.span.start + prefix..self.span.end.saturating_sub(suffix); self.replacement = substr; } } From 66369feec323d89b8209e69ecdf365321a01ac47 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 16 Apr 2025 16:46:45 -0500 Subject: [PATCH 172/175] docs: Make an attempt --- src/level.rs | 20 ++++++++++++++ src/snippet.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/src/level.rs b/src/level.rs index 3fd504d..87d1a9f 100644 --- a/src/level.rs +++ b/src/level.rs @@ -1,33 +1,41 @@ +//! [`Level`] constants for easy importing + use crate::renderer::stylesheet::Stylesheet; use crate::snippet::{ERROR_TXT, HELP_TXT, INFO_TXT, NOTE_TXT, WARNING_TXT}; use crate::{Element, Group, Message, Title}; use anstyle::Style; +/// Default `error:` [`Level`] pub const ERROR: Level<'_> = Level { name: None, level: LevelInner::Error, }; +/// Default `warning:` [`Level`] pub const WARNING: Level<'_> = Level { name: None, level: LevelInner::Warning, }; +/// Default `info:` [`Level`] pub const INFO: Level<'_> = Level { name: None, level: LevelInner::Info, }; +/// Default `note:` [`Level`] pub const NOTE: Level<'_> = Level { name: None, level: LevelInner::Note, }; +/// Default `help:` [`Level`] pub const HELP: Level<'_> = Level { name: None, level: LevelInner::Help, }; +/// [`Message`] or [`Title`] severity level #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Level<'a> { pub(crate) name: Option>, @@ -41,9 +49,13 @@ impl<'a> Level<'a> { pub const NOTE: Level<'a> = NOTE; pub const HELP: Level<'a> = HELP; + ///
+ /// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. + /// + ///
pub fn text(self, text: Option<&'a str>) -> Level<'a> { Level { name: Some(text), @@ -53,9 +65,13 @@ impl<'a> Level<'a> { } impl<'a> Level<'a> { + ///
+ /// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. + /// + ///
pub fn header(self, header: &'a str) -> Message<'a> { Message { id: None, @@ -67,10 +83,14 @@ impl<'a> Level<'a> { } } + ///
+ /// /// Text passed to this function is allowed to be pre-styled, as such all /// text is considered "trusted input" and has no normalizations applied to /// it. [`normalize_untrusted_str`](crate::normalize_untrusted_str) can be /// used to normalize untrusted text before it is passed to this function. + /// + ///
pub fn title(self, title: &'a str) -> Title<'a> { Title { level: self, diff --git a/src/snippet.rs b/src/snippet.rs index f37a048..03bfe3d 100644 --- a/src/snippet.rs +++ b/src/snippet.rs @@ -10,6 +10,7 @@ pub(crate) const INFO_TXT: &str = "info"; pub(crate) const NOTE_TXT: &str = "note"; pub(crate) const WARNING_TXT: &str = "warning"; +/// Top-level user message #[derive(Debug)] pub struct Message<'a> { pub(crate) id: Option<&'a str>, // for "correctness", could be sloppy and be on Title @@ -17,11 +18,19 @@ pub struct Message<'a> { } impl<'a> Message<'a> { + ///
+ /// + /// Text passed to this function is considered "untrusted input", as such + /// all text is passed through a normalization function. Pre-styled text is + /// not allowed to be passed to this function. + /// + ///
pub fn id(mut self, id: &'a str) -> Self { self.id = Some(id); self } + /// Add an [`Element`] container pub fn group(mut self, group: Group<'a>) -> Self { self.groups.push(group); self @@ -66,6 +75,7 @@ impl<'a> Message<'a> { } } +/// An [`Element`] container #[derive(Debug)] pub struct Group<'a> { pub(crate) elements: Vec>, @@ -97,6 +107,7 @@ impl<'a> Group<'a> { } } +/// A section of content within a [`Group`] #[derive(Debug)] #[non_exhaustive] pub enum Element<'a> { @@ -137,9 +148,13 @@ impl From for Element<'_> { } } +/// A whitespace [`Element`] in a [`Group`] #[derive(Debug)] pub struct Padding; +/// A text [`Element`] in a [`Group`] +/// +/// See [`Level::title`] to create this. #[derive(Debug)] pub struct Title<'a> { pub(crate) level: Level<'a>, @@ -154,6 +169,7 @@ impl Title<'_> { } } +/// A source view [`Element`] in a [`Group`] #[derive(Debug)] pub struct Snippet<'a, T> { pub(crate) origin: Option<&'a str>, @@ -164,9 +180,15 @@ pub struct Snippet<'a, T> { } impl<'a, T: Clone> Snippet<'a, T> { + /// The source code to be rendered + /// + ///
+ /// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. + /// + ///
pub fn source(source: &'a str) -> Self { Self { origin: None, @@ -177,19 +199,28 @@ impl<'a, T: Clone> Snippet<'a, T> { } } + /// When manually [`fold`][Self::fold]ing, + /// the [`source`][Self::source]s line offset from the original start pub fn line_start(mut self, line_start: usize) -> Self { self.line_start = line_start; self } + /// The location of the [`source`][Self::source] (e.g. a path) + /// + ///
+ /// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. + /// + ///
pub fn origin(mut self, origin: &'a str) -> Self { self.origin = Some(origin); self } + /// Hide lines without [`Annotation`]s pub fn fold(mut self, fold: bool) -> Self { self.fold = fold; self @@ -197,11 +228,13 @@ impl<'a, T: Clone> Snippet<'a, T> { } impl<'a> Snippet<'a, Annotation<'a>> { + /// Highlight and describe a span of text within the [`source`][Self::source] pub fn annotation(mut self, annotation: Annotation<'a>) -> Snippet<'a, Annotation<'a>> { self.markers.push(annotation); self } + /// Highlight and describe spans of text within the [`source`][Self::source] pub fn annotations(mut self, annotation: impl IntoIterator>) -> Self { self.markers.extend(annotation); self @@ -209,17 +242,22 @@ impl<'a> Snippet<'a, Annotation<'a>> { } impl<'a> Snippet<'a, Patch<'a>> { + /// Suggest to the user an edit to the [`source`][Self::source] pub fn patch(mut self, patch: Patch<'a>) -> Snippet<'a, Patch<'a>> { self.markers.push(patch); self } + /// Suggest to the user edits to the [`source`][Self::source] pub fn patches(mut self, patches: impl IntoIterator>) -> Self { self.markers.extend(patches); self } } +/// Highlighted and describe a span of text within a [`Snippet`] +/// +/// See [`AnnotationKind`] to create an annotation. #[derive(Clone, Debug)] pub struct Annotation<'a> { pub(crate) span: Range, @@ -229,20 +267,30 @@ pub struct Annotation<'a> { } impl<'a> Annotation<'a> { + /// Describe the reason the span is highlighted + /// + /// This will be styled according to the [`AnnotationKind`] + /// + ///
+ /// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. + /// + ///
pub fn label(mut self, label: &'a str) -> Self { self.label = Some(label); self } + /// Style the source according to the [`AnnotationKind`] pub fn highlight_source(mut self, highlight_source: bool) -> Self { self.highlight_source = highlight_source; self } } +/// The category of the [`Annotation`] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum AnnotationKind { /// Color to [`Message`]'s [`Level`] @@ -266,6 +314,7 @@ impl AnnotationKind { } } +/// Suggested edit to the [`Snippet`] #[derive(Clone, Debug)] pub struct Patch<'a> { pub(crate) span: Range, @@ -273,9 +322,15 @@ pub struct Patch<'a> { } impl<'a> Patch<'a> { + /// Splice `replacement` into the [`Snippet`] at the `span` + /// + ///
+ /// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. + /// + ///
pub fn new(span: Range, replacement: &'a str) -> Self { Self { span, replacement } } @@ -328,6 +383,7 @@ impl<'a> Patch<'a> { } } +/// The location of the [`Snippet`] (e.g. a path) #[derive(Clone, Debug)] pub struct Origin<'a> { pub(crate) origin: &'a str, @@ -338,9 +394,13 @@ pub struct Origin<'a> { } impl<'a> Origin<'a> { + ///
+ /// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. + /// + ///
pub fn new(origin: &'a str) -> Self { Self { origin, @@ -351,11 +411,17 @@ impl<'a> Origin<'a> { } } + /// Set the default line number to display + /// + /// Otherwise this will be inferred from the primary [`Annotation`] pub fn line(mut self, line: usize) -> Self { self.line = Some(line); self } + /// Set the default column to display + /// + /// Otherwise this will be inferred from the primary [`Annotation`] pub fn char_column(mut self, char_column: usize) -> Self { self.char_column = Some(char_column); self @@ -366,9 +432,15 @@ impl<'a> Origin<'a> { self } + /// Like [`Annotation::label`], but when there is no source + /// + ///
+ /// /// Text passed to this function is considered "untrusted input", as such /// all text is passed through a normalization function. Pre-styled text is /// not allowed to be passed to this function. + /// + ///
pub fn label(mut self, label: &'a str) -> Self { self.label = Some(label); self From 17eb40e020e119d8f9bf20987050015d761d54c7 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Sat, 26 Apr 2025 06:29:03 -0600 Subject: [PATCH 173/175] test(fixtures): Move to source code based color tests --- Cargo.lock | 327 +----------------- Cargo.toml | 6 - tests/color/ann_eof.rs | 18 + .../ann_eof.svg => color/ann_eof.term.svg} | 0 tests/color/ann_insertion.rs | 18 + .../ann_insertion.term.svg} | 0 tests/color/ann_multiline.rs | 31 ++ .../ann_multiline.term.svg} | 0 tests/color/ann_multiline2.rs | 31 ++ .../ann_multiline2.term.svg} | 0 tests/color/ann_removed_nl.rs | 18 + .../ann_removed_nl.term.svg} | 0 tests/color/ensure_emoji_highlight_width.rs | 24 ++ .../ensure_emoji_highlight_width.term.svg} | 0 tests/color/fold_ann_multiline.rs | 50 +++ .../fold_ann_multiline.term.svg} | 0 tests/color/fold_bad_origin_line.rs | 24 ++ .../fold_bad_origin_line.term.svg} | 0 tests/color/fold_leading.rs | 35 ++ .../fold_leading.term.svg} | 0 tests/color/fold_trailing.rs | 34 ++ .../fold_trailing.term.svg} | 0 tests/color/issue_9.rs | 31 ++ .../issue_9.svg => color/issue_9.term.svg} | 0 tests/color/main.rs | 16 + tests/color/multiple_annotations.rs | 42 +++ .../multiple_annotations.term.svg} | 0 tests/color/simple.rs | 34 ++ .../simple.svg => color/simple.term.svg} | 0 tests/color/strip_line.rs | 24 ++ .../strip_line.term.svg} | 0 tests/color/strip_line_char.rs | 24 ++ .../strip_line_char.term.svg} | 0 tests/color/strip_line_non_ws.rs | 30 ++ .../strip_line_non_ws.term.svg} | 0 tests/fixtures/color/ann_eof.toml | 15 - tests/fixtures/color/ann_insertion.toml | 15 - tests/fixtures/color/ann_multiline.toml | 21 -- tests/fixtures/color/ann_multiline2.toml | 21 -- tests/fixtures/color/ann_removed_nl.toml | 15 - .../color/ensure-emoji-highlight-width.toml | 18 - tests/fixtures/color/fold_ann_multiline.toml | 41 --- .../fixtures/color/fold_bad_origin_line.toml | 20 -- tests/fixtures/color/fold_leading.toml | 29 -- tests/fixtures/color/fold_trailing.toml | 28 -- tests/fixtures/color/issue_9.toml | 34 -- .../fixtures/color/multiple_annotations.toml | 33 -- tests/fixtures/color/simple.toml | 23 -- tests/fixtures/color/strip_line.toml | 19 - tests/fixtures/color/strip_line_char.toml | 19 - tests/fixtures/color/strip_line_non_ws.toml | 27 -- tests/fixtures/deserialize.rs | 217 ------------ tests/fixtures/main.rs | 42 --- 53 files changed, 489 insertions(+), 965 deletions(-) create mode 100644 tests/color/ann_eof.rs rename tests/{fixtures/color/ann_eof.svg => color/ann_eof.term.svg} (100%) create mode 100644 tests/color/ann_insertion.rs rename tests/{fixtures/color/ann_insertion.svg => color/ann_insertion.term.svg} (100%) create mode 100644 tests/color/ann_multiline.rs rename tests/{fixtures/color/ann_multiline.svg => color/ann_multiline.term.svg} (100%) create mode 100644 tests/color/ann_multiline2.rs rename tests/{fixtures/color/ann_multiline2.svg => color/ann_multiline2.term.svg} (100%) create mode 100644 tests/color/ann_removed_nl.rs rename tests/{fixtures/color/ann_removed_nl.svg => color/ann_removed_nl.term.svg} (100%) create mode 100644 tests/color/ensure_emoji_highlight_width.rs rename tests/{fixtures/color/ensure-emoji-highlight-width.svg => color/ensure_emoji_highlight_width.term.svg} (100%) create mode 100644 tests/color/fold_ann_multiline.rs rename tests/{fixtures/color/fold_ann_multiline.svg => color/fold_ann_multiline.term.svg} (100%) create mode 100644 tests/color/fold_bad_origin_line.rs rename tests/{fixtures/color/fold_bad_origin_line.svg => color/fold_bad_origin_line.term.svg} (100%) create mode 100644 tests/color/fold_leading.rs rename tests/{fixtures/color/fold_leading.svg => color/fold_leading.term.svg} (100%) create mode 100644 tests/color/fold_trailing.rs rename tests/{fixtures/color/fold_trailing.svg => color/fold_trailing.term.svg} (100%) create mode 100644 tests/color/issue_9.rs rename tests/{fixtures/color/issue_9.svg => color/issue_9.term.svg} (100%) create mode 100644 tests/color/main.rs create mode 100644 tests/color/multiple_annotations.rs rename tests/{fixtures/color/multiple_annotations.svg => color/multiple_annotations.term.svg} (100%) create mode 100644 tests/color/simple.rs rename tests/{fixtures/color/simple.svg => color/simple.term.svg} (100%) create mode 100644 tests/color/strip_line.rs rename tests/{fixtures/color/strip_line.svg => color/strip_line.term.svg} (100%) create mode 100644 tests/color/strip_line_char.rs rename tests/{fixtures/color/strip_line_char.svg => color/strip_line_char.term.svg} (100%) create mode 100644 tests/color/strip_line_non_ws.rs rename tests/{fixtures/color/strip_line_non_ws.svg => color/strip_line_non_ws.term.svg} (100%) delete mode 100644 tests/fixtures/color/ann_eof.toml delete mode 100644 tests/fixtures/color/ann_insertion.toml delete mode 100644 tests/fixtures/color/ann_multiline.toml delete mode 100644 tests/fixtures/color/ann_multiline2.toml delete mode 100644 tests/fixtures/color/ann_removed_nl.toml delete mode 100644 tests/fixtures/color/ensure-emoji-highlight-width.toml delete mode 100644 tests/fixtures/color/fold_ann_multiline.toml delete mode 100644 tests/fixtures/color/fold_bad_origin_line.toml delete mode 100644 tests/fixtures/color/fold_leading.toml delete mode 100644 tests/fixtures/color/fold_trailing.toml delete mode 100644 tests/fixtures/color/issue_9.toml delete mode 100644 tests/fixtures/color/multiple_annotations.toml delete mode 100644 tests/fixtures/color/simple.toml delete mode 100644 tests/fixtures/color/strip_line.toml delete mode 100644 tests/fixtures/color/strip_line_char.toml delete mode 100644 tests/fixtures/color/strip_line_non_ws.toml delete mode 100644 tests/fixtures/deserialize.rs delete mode 100644 tests/fixtures/main.rs diff --git a/Cargo.lock b/Cargo.lock index 8838e31..dd4fd20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,21 +2,12 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - [[package]] name = "annotate-snippets" version = "0.11.5" dependencies = [ "annotate-snippets", - "anstream 0.6.18", + "anstream", "anstyle", "difference", "divan", @@ -24,26 +15,9 @@ dependencies = [ "memchr", "serde", "snapbox", - "toml", - "tryfn", "unicode-width 0.2.0", ] -[[package]] -name = "anstream" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon 1.0.2", - "colorchoice", - "is-terminal", - "utf8parse", -] - [[package]] name = "anstream" version = "0.6.18" @@ -53,7 +27,7 @@ dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", - "anstyle-wincon 3.0.6", + "anstyle-wincon", "colorchoice", "is_terminal_polyfill", "utf8parse", @@ -98,23 +72,13 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbbf0bf947d663010f0b4132f28ca08da9151f3b9035fa7578a38de521c1d1aa" dependencies = [ - "anstream 0.6.18", + "anstream", "anstyle", "anstyle-lossy", "html-escape", "unicode-width 0.1.13", ] -[[package]] -name = "anstyle-wincon" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" -dependencies = [ - "anstyle", - "windows-sys 0.48.0", -] - [[package]] name = "anstyle-wincon" version = "3.0.6" @@ -131,16 +95,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bstr" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -154,8 +108,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb690e81c7840c0d7aade59f242ea3b41b9bc27bcd5997890e7702ae4b32e487" dependencies = [ "clap_builder", - "clap_derive", - "once_cell", ] [[package]] @@ -164,25 +116,11 @@ version = "4.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ed2e96bc16d8d740f6f48d663eddf4b8a0983e79210fd55479b7bcd0a69860e" dependencies = [ - "anstream 0.3.2", "anstyle", "clap_lex", - "strsim", "terminal_size", ] -[[package]] -name = "clap_derive" -version = "4.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "clap_lex" version = "0.5.0" @@ -232,12 +170,6 @@ dependencies = [ "syn", ] -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - [[package]] name = "errno" version = "0.3.9" @@ -248,15 +180,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "escape8259" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4911e3666fcd7826997b4745c8224295a6f3072f1418c3067b97a67557ee" -dependencies = [ - "rustversion", -] - [[package]] name = "escargot" version = "0.5.13" @@ -275,31 +198,6 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" -[[package]] -name = "globset" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" -dependencies = [ - "aho-corasick", - "bstr", - "log", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "hashbrown" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "hermit-abi" version = "0.3.9" @@ -315,33 +213,6 @@ dependencies = [ "utf8-width", ] -[[package]] -name = "ignore" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" -dependencies = [ - "globset", - "lazy_static", - "log", - "memchr", - "regex", - "same-file", - "thread_local", - "walkdir", - "winapi-util", -] - -[[package]] -name = "indexmap" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" -dependencies = [ - "equivalent", - "hashbrown", -] - [[package]] name = "io-lifetimes" version = "1.0.11" @@ -379,30 +250,12 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[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.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" -[[package]] -name = "libtest-mimic" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc0bda45ed5b3a2904262c1bb91e526127aa70e7ef3758aba2ef93cf896b9b58" -dependencies = [ - "clap", - "escape8259", - "termcolor", - "threadpool", -] - [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -427,16 +280,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "once_cell" version = "1.19.0" @@ -471,41 +314,12 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "regex" -version = "1.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - [[package]] name = "regex-lite" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" -[[package]] -name = "regex-syntax" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" - [[package]] name = "rustix" version = "0.37.27" @@ -520,27 +334,12 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "rustversion" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - [[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" -[[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 = "serde" version = "1.0.219" @@ -572,15 +371,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_spanned" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" -dependencies = [ - "serde", -] - [[package]] name = "similar" version = "2.5.0" @@ -593,7 +383,7 @@ version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96dcfc4581e3355d70ac2ee14cfdf81dce3d85c85f1ed9e2c1d3013f53b3436b" dependencies = [ - "anstream 0.6.18", + "anstream", "anstyle", "anstyle-svg", "escargot", @@ -613,15 +403,9 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16569f53ca23a41bb6f62e0a5084aa1661f4814a67fa33696a79073e03a664af" dependencies = [ - "anstream 0.6.18", + "anstream", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "syn" version = "2.0.86" @@ -633,15 +417,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "terminal_size" version = "0.2.6" @@ -652,70 +427,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "toml" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tryfn" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe242ee9e646acec9ab73a5c540e8543ed1b107f0ce42be831e0775d423c396" -dependencies = [ - "ignore", - "libtest-mimic", - "snapbox", -] - [[package]] name = "unicode-ident" version = "1.0.12" @@ -755,25 +466,6 @@ dependencies = [ "libc", ] -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "winapi-util" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -921,12 +613,3 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" -dependencies = [ - "memchr", -] diff --git a/Cargo.toml b/Cargo.toml index f30c64f..4a8adf0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -128,17 +128,11 @@ divan = "0.1.14" glob = "0.3.1" serde = { version = "1.0.199", features = ["derive"] } snapbox = { version = "0.6.0", features = ["diff", "term-svg", "cmd", "examples"] } -toml = "0.8.0" -tryfn = "0.2.1" [[bench]] name = "bench" harness = false -[[test]] -name = "fixtures" -harness = false - [features] default = [] simd = ["memchr"] diff --git a/tests/color/ann_eof.rs b/tests/color/ann_eof.rs new file mode 100644 index 0000000..00e34b1 --- /dev/null +++ b/tests/color/ann_eof.rs @@ -0,0 +1,18 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let input = Level::ERROR.header("expected `.`, `=`").group( + Group::new().element( + Snippet::source("asdf") + .origin("Cargo.toml") + .line_start(1) + .annotation(AnnotationKind::Primary.span(4..4).label("")), + ), + ); + let expected = file!["ann_eof.term.svg"]; + let renderer = Renderer::styled(); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/ann_eof.svg b/tests/color/ann_eof.term.svg similarity index 100% rename from tests/fixtures/color/ann_eof.svg rename to tests/color/ann_eof.term.svg diff --git a/tests/color/ann_insertion.rs b/tests/color/ann_insertion.rs new file mode 100644 index 0000000..802a0c7 --- /dev/null +++ b/tests/color/ann_insertion.rs @@ -0,0 +1,18 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let input = Level::ERROR.header("expected `.`, `=`").group( + Group::new().element( + Snippet::source("asf") + .origin("Cargo.toml") + .line_start(1) + .annotation(AnnotationKind::Primary.span(2..2).label("'d' belongs here")), + ), + ); + let expected = file!["ann_insertion.term.svg"]; + let renderer = Renderer::styled(); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/ann_insertion.svg b/tests/color/ann_insertion.term.svg similarity index 100% rename from tests/fixtures/color/ann_insertion.svg rename to tests/color/ann_insertion.term.svg diff --git a/tests/color/ann_multiline.rs b/tests/color/ann_multiline.rs new file mode 100644 index 0000000..4b561ed --- /dev/null +++ b/tests/color/ann_multiline.rs @@ -0,0 +1,31 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let source = r#" if let DisplayLine::Source { + ref mut inline_marks, + } = body[body_idx] +"#; + + let input = Level::ERROR + .header("pattern does not mention fields `lineno`, `content`") + .id("E0027") + .group( + Group::new().element( + Snippet::source(source) + .origin("src/display_list.rs") + .line_start(139) + .fold(false) + .annotation( + AnnotationKind::Primary + .span(31..128) + .label("missing fields `lineno`, `content`"), + ), + ), + ); + let expected = file!["ann_multiline.term.svg"]; + let renderer = Renderer::styled(); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/ann_multiline.svg b/tests/color/ann_multiline.term.svg similarity index 100% rename from tests/fixtures/color/ann_multiline.svg rename to tests/color/ann_multiline.term.svg diff --git a/tests/color/ann_multiline2.rs b/tests/color/ann_multiline2.rs new file mode 100644 index 0000000..9996fa9 --- /dev/null +++ b/tests/color/ann_multiline2.rs @@ -0,0 +1,31 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let source = r#"This is an example +of an edge case of an annotation overflowing +to exactly one character on next line. +"#; + + let input = Level::ERROR + .header("spacing error found") + .id("E####") + .group( + Group::new().element( + Snippet::source(source) + .origin("foo.txt") + .line_start(26) + .fold(false) + .annotation( + AnnotationKind::Primary + .span(11..19) + .label("this should not be on separate lines"), + ), + ), + ); + let expected = file!["ann_multiline2.term.svg"]; + let renderer = Renderer::styled(); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/ann_multiline2.svg b/tests/color/ann_multiline2.term.svg similarity index 100% rename from tests/fixtures/color/ann_multiline2.svg rename to tests/color/ann_multiline2.term.svg diff --git a/tests/color/ann_removed_nl.rs b/tests/color/ann_removed_nl.rs new file mode 100644 index 0000000..45a6462 --- /dev/null +++ b/tests/color/ann_removed_nl.rs @@ -0,0 +1,18 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let input = Level::ERROR.header("expected `.`, `=`").group( + Group::new().element( + Snippet::source("asdf") + .origin("Cargo.toml") + .line_start(1) + .annotation(AnnotationKind::Primary.span(4..5).label("")), + ), + ); + let expected = file!["ann_removed_nl.term.svg"]; + let renderer = Renderer::styled(); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/ann_removed_nl.svg b/tests/color/ann_removed_nl.term.svg similarity index 100% rename from tests/fixtures/color/ann_removed_nl.svg rename to tests/color/ann_removed_nl.term.svg diff --git a/tests/color/ensure_emoji_highlight_width.rs b/tests/color/ensure_emoji_highlight_width.rs new file mode 100644 index 0000000..b239784 --- /dev/null +++ b/tests/color/ensure_emoji_highlight_width.rs @@ -0,0 +1,24 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let source = r#""haha this isn't a valid name 🐛" = { package = "libc", version = "0.1" } +"#; + + let input = Level::ERROR.header("invalid character ` ` in package name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)") + .group( + Group::new() + .element( + Snippet::source(source) + .origin("") + .line_start(7) + .annotation(AnnotationKind::Primary.span(0..35).label("")) + ) + ) +; + let expected = file!["ensure_emoji_highlight_width.term.svg"]; + let renderer = Renderer::styled(); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/ensure-emoji-highlight-width.svg b/tests/color/ensure_emoji_highlight_width.term.svg similarity index 100% rename from tests/fixtures/color/ensure-emoji-highlight-width.svg rename to tests/color/ensure_emoji_highlight_width.term.svg diff --git a/tests/color/fold_ann_multiline.rs b/tests/color/fold_ann_multiline.rs new file mode 100644 index 0000000..3995b68 --- /dev/null +++ b/tests/color/fold_ann_multiline.rs @@ -0,0 +1,50 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let 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 || 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, + } + } +"#; + + let input = Level::ERROR.header("mismatched types").id("E0308").group( + Group::new().element( + Snippet::source(source) + .origin("src/format.rs") + .line_start(51) + .fold(true) + .annotation(AnnotationKind::Context.span(5..19).label( + "expected `std::option::Option` because of return type", + )) + .annotation( + AnnotationKind::Primary + .span(22..766) + .label("expected enum `std::option::Option`, found ()"), + ), + ), + ); + let expected = file!["fold_ann_multiline.term.svg"]; + let renderer = Renderer::styled(); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/fold_ann_multiline.svg b/tests/color/fold_ann_multiline.term.svg similarity index 100% rename from tests/fixtures/color/fold_ann_multiline.svg rename to tests/color/fold_ann_multiline.term.svg diff --git a/tests/color/fold_bad_origin_line.rs b/tests/color/fold_bad_origin_line.rs new file mode 100644 index 0000000..1a21a5e --- /dev/null +++ b/tests/color/fold_bad_origin_line.rs @@ -0,0 +1,24 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let source = r#" + +invalid syntax +"#; + + let input = Level::ERROR.header("").group( + Group::new().element( + Snippet::source(source) + .origin("path/to/error.rs") + .line_start(1) + .fold(true) + .annotation(AnnotationKind::Context.span(2..16).label("error here")), + ), + ); + let expected = file!["fold_bad_origin_line.term.svg"]; + let renderer = Renderer::styled(); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/fold_bad_origin_line.svg b/tests/color/fold_bad_origin_line.term.svg similarity index 100% rename from tests/fixtures/color/fold_bad_origin_line.svg rename to tests/color/fold_bad_origin_line.term.svg diff --git a/tests/color/fold_leading.rs b/tests/color/fold_leading.rs new file mode 100644 index 0000000..93ba499 --- /dev/null +++ b/tests/color/fold_leading.rs @@ -0,0 +1,35 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let source = r#"[workspace] + +[package] +name = "hello" +version = "1.0.0" +license = "MIT" +rust-version = "1.70" +edition = "2021" + +[lints] +workspace = 20 +"#; + + let input = Level::ERROR + .header("invalid type: integer `20`, expected a bool") + .id("E0308") + .group( + Group::new().element( + Snippet::source(source) + .origin("Cargo.toml") + .line_start(1) + .fold(true) + .annotation(AnnotationKind::Primary.span(132..134).label("")), + ), + ); + let expected = file!["fold_leading.term.svg"]; + let renderer = Renderer::styled(); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/fold_leading.svg b/tests/color/fold_leading.term.svg similarity index 100% rename from tests/fixtures/color/fold_leading.svg rename to tests/color/fold_leading.term.svg diff --git a/tests/color/fold_trailing.rs b/tests/color/fold_trailing.rs new file mode 100644 index 0000000..f86ade7 --- /dev/null +++ b/tests/color/fold_trailing.rs @@ -0,0 +1,34 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let source = r#"lints = 20 + +[workspace] + +[package] +name = "hello" +version = "1.0.0" +license = "MIT" +rust-version = "1.70" +edition = "2021" +"#; + + let input = Level::ERROR + .header("invalid type: integer `20`, expected a lints table") + .id("E0308") + .group( + Group::new().element( + Snippet::source(source) + .origin("Cargo.toml") + .line_start(1) + .fold(true) + .annotation(AnnotationKind::Primary.span(8..10).label("")), + ), + ); + let expected = file!["fold_trailing.term.svg"]; + let renderer = Renderer::styled(); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/fold_trailing.svg b/tests/color/fold_trailing.term.svg similarity index 100% rename from tests/fixtures/color/fold_trailing.svg rename to tests/color/fold_trailing.term.svg diff --git a/tests/color/issue_9.rs b/tests/color/issue_9.rs new file mode 100644 index 0000000..2accd2f --- /dev/null +++ b/tests/color/issue_9.rs @@ -0,0 +1,31 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let input = Level::ERROR.header("expected one of `.`, `;`, `?`, or an operator, found `for`") + .group( + Group::new() + .element( + Snippet::source("let x = vec![1];") + .origin("/code/rust/src/test/ui/annotate-snippet/suggestion.rs") + .line_start(4) + .annotation(AnnotationKind::Context.span(4..5).label("move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait")) + ) + .element( + Snippet::source("let y = x;") + .line_start(7) + .annotation(AnnotationKind::Context.span(8..9).label("value moved here")) + ) + .element( + Snippet::source("x;") + .line_start(9) + .annotation(AnnotationKind::Primary.span(0..1).label("value used here after move")) + ) + ) +; + let expected = file!["issue_9.term.svg"]; + let renderer = Renderer::styled(); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/issue_9.svg b/tests/color/issue_9.term.svg similarity index 100% rename from tests/fixtures/color/issue_9.svg rename to tests/color/issue_9.term.svg diff --git a/tests/color/main.rs b/tests/color/main.rs new file mode 100644 index 0000000..f954bb7 --- /dev/null +++ b/tests/color/main.rs @@ -0,0 +1,16 @@ +mod ann_eof; +mod ann_insertion; +mod ann_multiline; +mod ann_multiline2; +mod ann_removed_nl; +mod ensure_emoji_highlight_width; +mod fold_ann_multiline; +mod fold_bad_origin_line; +mod fold_leading; +mod fold_trailing; +mod issue_9; +mod multiple_annotations; +mod simple; +mod strip_line; +mod strip_line_char; +mod strip_line_non_ws; diff --git a/tests/color/multiple_annotations.rs b/tests/color/multiple_annotations.rs new file mode 100644 index 0000000..b568b91 --- /dev/null +++ b/tests/color/multiple_annotations.rs @@ -0,0 +1,42 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let source = r#"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, + )); + } +} +"#; + + let input = Level::ERROR.header("").group( + Group::new().element( + Snippet::source(source) + .line_start(96) + .annotation( + AnnotationKind::Primary + .span(100..110) + .label("Variable defined here"), + ) + .annotation( + AnnotationKind::Primary + .span(184..194) + .label("Referenced here"), + ) + .annotation( + AnnotationKind::Primary + .span(243..253) + .label("Referenced again here"), + ), + ), + ); + let expected = file!["multiple_annotations.term.svg"]; + let renderer = Renderer::styled(); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/multiple_annotations.svg b/tests/color/multiple_annotations.term.svg similarity index 100% rename from tests/fixtures/color/multiple_annotations.svg rename to tests/color/multiple_annotations.term.svg diff --git a/tests/color/simple.rs b/tests/color/simple.rs new file mode 100644 index 0000000..35e83d3 --- /dev/null +++ b/tests/color/simple.rs @@ -0,0 +1,34 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let source = r#" }) + + for line in &self.body { +"#; + + let input = Level::ERROR + .header("expected one of `.`, `;`, `?`, or an operator, found `for`") + .group( + Group::new().element( + Snippet::source(source) + .origin("src/format_color.rs") + .line_start(169) + .annotation( + AnnotationKind::Primary + .span(20..23) + .label("unexpected token"), + ) + .annotation( + AnnotationKind::Context + .span(10..11) + .label("expected one of `.`, `;`, `?`, or an operator here"), + ), + ), + ); + let expected = file!["simple.term.svg"]; + let renderer = Renderer::styled(); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/simple.svg b/tests/color/simple.term.svg similarity index 100% rename from tests/fixtures/color/simple.svg rename to tests/color/simple.term.svg diff --git a/tests/color/strip_line.rs b/tests/color/strip_line.rs new file mode 100644 index 0000000..fd1ba58 --- /dev/null +++ b/tests/color/strip_line.rs @@ -0,0 +1,24 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let source = r#" let _: () = 42;"#; + + let input = Level::ERROR.header("mismatched types").id("E0308").group( + Group::new().element( + Snippet::source(source) + .origin("$DIR/whitespace-trimming.rs") + .line_start(4) + .annotation( + AnnotationKind::Primary + .span(192..194) + .label("expected (), found integer"), + ), + ), + ); + let expected = file!["strip_line.term.svg"]; + let renderer = Renderer::styled().anonymized_line_numbers(true); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/strip_line.svg b/tests/color/strip_line.term.svg similarity index 100% rename from tests/fixtures/color/strip_line.svg rename to tests/color/strip_line.term.svg diff --git a/tests/color/strip_line_char.rs b/tests/color/strip_line_char.rs new file mode 100644 index 0000000..df609e2 --- /dev/null +++ b/tests/color/strip_line_char.rs @@ -0,0 +1,24 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let source = r#" let _: () = 42ñ"#; + + let input = Level::ERROR.header("mismatched types").id("E0308").group( + Group::new().element( + Snippet::source(source) + .origin("$DIR/whitespace-trimming.rs") + .line_start(4) + .annotation( + AnnotationKind::Primary + .span(192..194) + .label("expected (), found integer"), + ), + ), + ); + let expected = file!["strip_line_char.term.svg"]; + let renderer = Renderer::styled().anonymized_line_numbers(true); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/strip_line_char.svg b/tests/color/strip_line_char.term.svg similarity index 100% rename from tests/fixtures/color/strip_line_char.svg rename to tests/color/strip_line_char.term.svg diff --git a/tests/color/strip_line_non_ws.rs b/tests/color/strip_line_non_ws.rs new file mode 100644 index 0000000..f82d369 --- /dev/null +++ b/tests/color/strip_line_non_ws.rs @@ -0,0 +1,30 @@ +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let source = r#" let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); +"#; + + let input = Level::ERROR.header("mismatched types").id("E0308").group( + Group::new().element( + Snippet::source(source) + .origin("$DIR/non-whitespace-trimming.rs") + .line_start(4) + .annotation( + AnnotationKind::Primary + .span(237..239) + .label("expected `()`, found integer"), + ) + .annotation( + AnnotationKind::Primary + .span(232..234) + .label("expected due to this"), + ), + ), + ); + let expected = file!["strip_line_non_ws.term.svg"]; + let renderer = Renderer::styled().anonymized_line_numbers(true); + assert_data_eq!(renderer.render(input), expected); +} diff --git a/tests/fixtures/color/strip_line_non_ws.svg b/tests/color/strip_line_non_ws.term.svg similarity index 100% rename from tests/fixtures/color/strip_line_non_ws.svg rename to tests/color/strip_line_non_ws.term.svg diff --git a/tests/fixtures/color/ann_eof.toml b/tests/fixtures/color/ann_eof.toml deleted file mode 100644 index ef711de..0000000 --- a/tests/fixtures/color/ann_eof.toml +++ /dev/null @@ -1,15 +0,0 @@ -[message] -level = "Error" -header = "expected `.`, `=`" - -[[message.sections]] -type = "Cause" -source = "asdf" -line_start = 1 -origin = "Cargo.toml" -annotations = [ - { label = "", kind = "Primary", range = [4, 4] }, -] - -[renderer] -color = true diff --git a/tests/fixtures/color/ann_insertion.toml b/tests/fixtures/color/ann_insertion.toml deleted file mode 100644 index 30af1bf..0000000 --- a/tests/fixtures/color/ann_insertion.toml +++ /dev/null @@ -1,15 +0,0 @@ -[message] -level = "Error" -header = "expected `.`, `=`" - -[[message.sections]] -type = "Cause" -source = "asf" -line_start = 1 -origin = "Cargo.toml" -annotations = [ - { label = "'d' belongs here", kind = "Primary", range = [2, 2] } -] - -[renderer] -color = true diff --git a/tests/fixtures/color/ann_multiline.toml b/tests/fixtures/color/ann_multiline.toml deleted file mode 100644 index 2a5f206..0000000 --- a/tests/fixtures/color/ann_multiline.toml +++ /dev/null @@ -1,21 +0,0 @@ -[message] -level = "Error" -id = "E0027" -header = "pattern does not mention fields `lineno`, `content`" - -[[message.sections]] -type = "Cause" -source = """ - if let DisplayLine::Source { - ref mut inline_marks, - } = body[body_idx] -""" -line_start = 139 -origin = "src/display_list.rs" -fold = false -annotations = [ - { label = "missing fields `lineno`, `content`", kind = "Primary", range = [31, 128] } -] - -[renderer] -color = true diff --git a/tests/fixtures/color/ann_multiline2.toml b/tests/fixtures/color/ann_multiline2.toml deleted file mode 100644 index 854b38a..0000000 --- a/tests/fixtures/color/ann_multiline2.toml +++ /dev/null @@ -1,21 +0,0 @@ -[message] -level = "Error" -id = "E####" -header = "spacing error found" - -[[message.sections]] -type = "Cause" -source = """ -This is an example -of an edge case of an annotation overflowing -to exactly one character on next line. -""" -line_start = 26 -origin = "foo.txt" -fold = false -annotations = [ - { label = "this should not be on separate lines", kind = "Primary", range = [11, 19] }, -] - -[renderer] -color = true diff --git a/tests/fixtures/color/ann_removed_nl.toml b/tests/fixtures/color/ann_removed_nl.toml deleted file mode 100644 index 6ffeb7a..0000000 --- a/tests/fixtures/color/ann_removed_nl.toml +++ /dev/null @@ -1,15 +0,0 @@ -[message] -level = "Error" -header = "expected `.`, `=`" - -[[message.sections]] -type = "Cause" -source = "asdf" -line_start = 1 -origin = "Cargo.toml" -annotations = [ - { label = "", kind = "Primary", range = [4, 5] }, -] - -[renderer] -color = true diff --git a/tests/fixtures/color/ensure-emoji-highlight-width.toml b/tests/fixtures/color/ensure-emoji-highlight-width.toml deleted file mode 100644 index 669959f..0000000 --- a/tests/fixtures/color/ensure-emoji-highlight-width.toml +++ /dev/null @@ -1,18 +0,0 @@ -[message] -header = "invalid character ` ` in package name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)" -level = "Error" - - -[[message.sections]] -type = "Cause" -source = """ -"haha this isn't a valid name 🐛" = { package = "libc", version = "0.1" } -""" -line_start = 7 -origin = "" -annotations = [ - { label = "", kind = "Primary", range = [0, 35] }, -] - -[renderer] -color = true diff --git a/tests/fixtures/color/fold_ann_multiline.toml b/tests/fixtures/color/fold_ann_multiline.toml deleted file mode 100644 index 2cee27d..0000000 --- a/tests/fixtures/color/fold_ann_multiline.toml +++ /dev/null @@ -1,41 +0,0 @@ -[message] -level = "Error" -id = "E0308" -header = "mismatched types" - -[[message.sections]] -type = "Cause" -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 -annotations = [ - { label = "expected `std::option::Option` because of return type", kind = "Context", range = [5, 19] }, - { label = "expected enum `std::option::Option`, found ()", kind = "Primary", range = [22, 766] }, -] - -[renderer] -color = true diff --git a/tests/fixtures/color/fold_bad_origin_line.toml b/tests/fixtures/color/fold_bad_origin_line.toml deleted file mode 100644 index 2fab2d6..0000000 --- a/tests/fixtures/color/fold_bad_origin_line.toml +++ /dev/null @@ -1,20 +0,0 @@ -[message] -level = "Error" -header = "" - -[[message.sections]] -type = "Cause" -source = """ - - -invalid syntax -""" -line_start = 1 -origin = "path/to/error.rs" -fold = true -annotations = [ - { label = "error here", kind = "Context", range = [2,16] }, -] - -[renderer] -color = true diff --git a/tests/fixtures/color/fold_leading.toml b/tests/fixtures/color/fold_leading.toml deleted file mode 100644 index 0ef043c..0000000 --- a/tests/fixtures/color/fold_leading.toml +++ /dev/null @@ -1,29 +0,0 @@ -[message] -level = "Error" -id = "E0308" -header = "invalid type: integer `20`, expected a bool" - -[[message.sections]] -type = "Cause" -source = """ -[workspace] - -[package] -name = "hello" -version = "1.0.0" -license = "MIT" -rust-version = "1.70" -edition = "2021" - -[lints] -workspace = 20 -""" -line_start = 1 -origin = "Cargo.toml" -fold = true -annotations = [ - { label = "", kind = "Primary", range = [132, 134] }, -] - -[renderer] -color = true diff --git a/tests/fixtures/color/fold_trailing.toml b/tests/fixtures/color/fold_trailing.toml deleted file mode 100644 index 91e4ab4..0000000 --- a/tests/fixtures/color/fold_trailing.toml +++ /dev/null @@ -1,28 +0,0 @@ -[message] -level = "Error" -id = "E0308" -header = "invalid type: integer `20`, expected a lints table" - -[[message.sections]] -type = "Cause" -source = """ -lints = 20 - -[workspace] - -[package] -name = "hello" -version = "1.0.0" -license = "MIT" -rust-version = "1.70" -edition = "2021" -""" -line_start = 1 -origin = "Cargo.toml" -fold = true -annotations = [ - { label = "", kind = "Primary", range = [8, 10] }, -] - -[renderer] -color = true diff --git a/tests/fixtures/color/issue_9.toml b/tests/fixtures/color/issue_9.toml deleted file mode 100644 index f423915..0000000 --- a/tests/fixtures/color/issue_9.toml +++ /dev/null @@ -1,34 +0,0 @@ -[message] -level = "Error" -header = "expected one of `.`, `;`, `?`, or an operator, found `for`" - -[[message.sections]] -type = "Cause" -source = "let x = vec![1];" -line_start = 4 -origin = "/code/rust/src/test/ui/annotate-snippet/suggestion.rs" -[[message.sections.annotations]] -label = "move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait" -kind = "Context" -range = [4, 5] - -[[message.sections]] -type = "Cause" -source = "let y = x;" -line_start = 7 -[[message.sections.annotations]] -label = "value moved here" -kind = "Context" -range = [8, 9] - -[[message.sections]] -type = "Cause" -source = "x;" -line_start = 9 -[[message.sections.annotations]] -label = "value used here after move" -kind = "Primary" -range = [0, 1] - -[renderer] -color = true diff --git a/tests/fixtures/color/multiple_annotations.toml b/tests/fixtures/color/multiple_annotations.toml deleted file mode 100644 index 367c53e..0000000 --- a/tests/fixtures/color/multiple_annotations.toml +++ /dev/null @@ -1,33 +0,0 @@ -[message] -level = "Error" -header = "" - -[[message.sections]] -type = "Cause" -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 -[[message.sections.annotations]] -label = "Variable defined here" -kind = "Primary" -range = [100, 110] -[[message.sections.annotations]] -label = "Referenced here" -kind = "Primary" -range = [184, 194] -[[message.sections.annotations]] -label = "Referenced again here" -kind = "Primary" -range = [243, 253] - -[renderer] -color = true diff --git a/tests/fixtures/color/simple.toml b/tests/fixtures/color/simple.toml deleted file mode 100644 index d5a3647..0000000 --- a/tests/fixtures/color/simple.toml +++ /dev/null @@ -1,23 +0,0 @@ -[message] -level = "Error" -header = "expected one of `.`, `;`, `?`, or an operator, found `for`" - -[[message.sections]] -type = "Cause" -source = """ - }) - - for line in &self.body {""" -line_start = 169 -origin = "src/format_color.rs" -[[message.sections.annotations]] -label = "unexpected token" -kind = "Primary" -range = [20, 23] -[[message.sections.annotations]] -label = "expected one of `.`, `;`, `?`, or an operator here" -kind = "Context" -range = [10, 11] - -[renderer] -color = true diff --git a/tests/fixtures/color/strip_line.toml b/tests/fixtures/color/strip_line.toml deleted file mode 100644 index 18a7805..0000000 --- a/tests/fixtures/color/strip_line.toml +++ /dev/null @@ -1,19 +0,0 @@ -[message] -level = "Error" -id = "E0308" -header = "mismatched types" - -[[message.sections]] -type = "Cause" -source = " let _: () = 42;" -line_start = 4 -origin = "$DIR/whitespace-trimming.rs" - -[[message.sections.annotations]] -label = "expected (), found integer" -kind = "Primary" -range = [192, 194] - -[renderer] -color = true -anonymized_line_numbers = true diff --git a/tests/fixtures/color/strip_line_char.toml b/tests/fixtures/color/strip_line_char.toml deleted file mode 100644 index 3174ced..0000000 --- a/tests/fixtures/color/strip_line_char.toml +++ /dev/null @@ -1,19 +0,0 @@ -[message] -level = "Error" -id = "E0308" -header = "mismatched types" - -[[message.sections]] -type = "Cause" -source = " let _: () = 42ñ" -line_start = 4 -origin = "$DIR/whitespace-trimming.rs" - -[[message.sections.annotations]] -label = "expected (), found integer" -kind = "Primary" -range = [192, 194] - -[renderer] -color = true -anonymized_line_numbers = true diff --git a/tests/fixtures/color/strip_line_non_ws.toml b/tests/fixtures/color/strip_line_non_ws.toml deleted file mode 100644 index b7844ec..0000000 --- a/tests/fixtures/color/strip_line_non_ws.toml +++ /dev/null @@ -1,27 +0,0 @@ -[message] -level = "Error" -id = "E0308" -header = "mismatched types" - -[[message.sections]] -type = "Cause" -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" - -[[message.sections.annotations]] -label = "expected `()`, found integer" -kind = "Primary" -range = [237, 239] - -[[message.sections.annotations]] -label = "expected due to this" -kind = "Primary" -range = [232, 234] - - -[renderer] -anonymized_line_numbers = true -color = true diff --git a/tests/fixtures/deserialize.rs b/tests/fixtures/deserialize.rs deleted file mode 100644 index 2042966..0000000 --- a/tests/fixtures/deserialize.rs +++ /dev/null @@ -1,217 +0,0 @@ -use serde::Deserialize; -use std::ops::Range; - -use annotate_snippets::renderer::DEFAULT_TERM_WIDTH; -use annotate_snippets::{ - Annotation, AnnotationKind, Element, Group, Level, Message, Patch, Renderer, Snippet, -}; - -#[derive(Deserialize)] -pub(crate) struct Fixture { - #[serde(default)] - pub(crate) renderer: RendererDef, - pub(crate) message: MessageDef, -} - -#[derive(Deserialize)] -pub struct MessageDef { - pub level: LevelDef, - pub header: String, - #[serde(default)] - pub id: Option, - #[serde(default)] - pub sections: Vec, -} - -impl<'a> From<&'a MessageDef> for Message<'a> { - fn from(val: &'a MessageDef) -> Self { - let MessageDef { - level, - header, - id, - sections, - } = val; - let mut message = Level::from(level).header(header); - if let Some(id) = id { - message = message.id(id); - } - - message = message.group(Group::new().elements(sections.iter().map(|s| match s { - ElementDef::Title(title) => { - Element::Title(Level::from(&title.level).title(&title.title)) - } - ElementDef::Cause(cause) => Element::Cause(Snippet::from(cause)), - ElementDef::Suggestion(suggestion) => Element::Suggestion(Snippet::from(suggestion)), - }))); - message - } -} - -#[derive(Deserialize)] -#[serde(tag = "type")] -pub enum ElementDef { - Title(TitleDef), - Cause(SnippetAnnotationDef), - Suggestion(SnippetPatchDef), -} - -impl<'a> From<&'a ElementDef> for Element<'a> { - fn from(val: &'a ElementDef) -> Self { - match val { - ElementDef::Title(title) => { - Element::Title(Level::from(&title.level).title(&title.title)) - } - ElementDef::Cause(cause) => Element::Cause(Snippet::from(cause)), - ElementDef::Suggestion(suggestion) => Element::Suggestion(Snippet::from(suggestion)), - } - } -} - -#[derive(Deserialize)] -pub struct TitleDef { - pub title: String, - pub level: LevelDef, -} - -#[derive(Deserialize)] -pub struct SnippetAnnotationDef { - pub(crate) origin: Option, - pub(crate) line_start: usize, - pub(crate) source: String, - pub(crate) annotations: Vec, - #[serde(default)] - pub(crate) fold: bool, -} - -impl<'a> From<&'a SnippetAnnotationDef> for Snippet<'a, Annotation<'a>> { - fn from(val: &'a SnippetAnnotationDef) -> Self { - let SnippetAnnotationDef { - origin, - line_start, - source, - annotations, - fold, - } = val; - let mut snippet = Snippet::source(source).line_start(*line_start).fold(*fold); - if let Some(origin) = origin { - snippet = snippet.origin(origin); - } - snippet = snippet.annotations(annotations.iter().map(Into::into)); - snippet - } -} - -#[derive(Deserialize)] -pub struct AnnotationDef { - pub range: Range, - pub label: String, - #[serde(with = "AnnotationKindDef")] - pub kind: AnnotationKind, -} - -impl<'a> From<&'a AnnotationDef> for Annotation<'a> { - fn from(val: &'a AnnotationDef) -> Self { - let AnnotationDef { range, label, kind } = val; - kind.span(range.start..range.end).label(label) - } -} - -#[allow(dead_code)] -#[derive(Deserialize)] -#[serde(remote = "AnnotationKind")] -enum AnnotationKindDef { - Primary, - Context, -} - -#[derive(Deserialize)] -pub struct SnippetPatchDef { - pub(crate) origin: Option, - pub(crate) line_start: usize, - pub(crate) source: String, - pub(crate) patches: Vec, - #[serde(default)] - pub(crate) fold: bool, -} - -impl<'a> From<&'a SnippetPatchDef> for Snippet<'a, Patch<'a>> { - fn from(val: &'a SnippetPatchDef) -> Self { - let SnippetPatchDef { - origin, - line_start, - source, - patches, - fold, - } = val; - let mut snippet = Snippet::source(source).line_start(*line_start).fold(*fold); - if let Some(origin) = origin { - snippet = snippet.origin(origin); - } - snippet = snippet.patches(patches.iter().map(Into::into)); - snippet - } -} - -#[derive(Deserialize)] -pub struct PatchDef { - pub range: Range, - pub replacement: String, -} - -impl<'a> From<&'a PatchDef> for Patch<'a> { - fn from(val: &'a PatchDef) -> Self { - let PatchDef { range, replacement } = val; - Patch::new(range.start..range.end, replacement) - } -} - -#[allow(dead_code)] -#[derive(Clone, Copy, Deserialize)] -pub enum LevelDef { - Error, - Warning, - Info, - Note, - Help, -} - -impl<'a> From<&'a LevelDef> for Level<'a> { - fn from(val: &'a LevelDef) -> Self { - match val { - LevelDef::Error => Level::ERROR, - LevelDef::Warning => Level::WARNING, - LevelDef::Info => Level::INFO, - LevelDef::Note => Level::NOTE, - LevelDef::Help => Level::HELP, - } - } -} - -#[derive(Default, Deserialize)] -pub struct RendererDef { - #[serde(default)] - anonymized_line_numbers: bool, - #[serde(default)] - term_width: Option, - #[serde(default)] - color: bool, -} - -impl From for Renderer { - fn from(val: RendererDef) -> Self { - let RendererDef { - anonymized_line_numbers, - term_width, - color, - } = val; - - let renderer = if color { - Renderer::styled() - } else { - Renderer::plain() - }; - renderer - .anonymized_line_numbers(anonymized_line_numbers) - .term_width(term_width.unwrap_or(DEFAULT_TERM_WIDTH)) - } -} diff --git a/tests/fixtures/main.rs b/tests/fixtures/main.rs deleted file mode 100644 index 2708262..0000000 --- a/tests/fixtures/main.rs +++ /dev/null @@ -1,42 +0,0 @@ -mod deserialize; - -use crate::deserialize::Fixture; -use annotate_snippets::{Message, Renderer}; -use snapbox::data::DataFormat; -use snapbox::Data; -use std::error::Error; - -fn main() { - #[cfg(not(windows))] - tryfn::Harness::new("tests/fixtures/", setup, test) - .select(["*/*.toml"]) - .test(); -} - -fn setup(input_path: std::path::PathBuf) -> tryfn::Case { - let parent = input_path - .parent() - .unwrap() - .file_name() - .unwrap() - .to_str() - .unwrap(); - let file_name = input_path.file_name().unwrap().to_str().unwrap(); - let name = format!("{parent}/{file_name}"); - let expected = Data::read_from(&input_path.with_extension("svg"), None); - tryfn::Case { - name, - fixture: input_path, - expected, - } -} - -fn test(input_path: &std::path::Path) -> Result> { - let src = std::fs::read_to_string(input_path)?; - let fixture: Fixture = toml::from_str(&src)?; - let renderer: Renderer = fixture.renderer.into(); - let message: Message<'_> = (&fixture.message).into(); - - let actual = renderer.render(message); - Ok(Data::from(actual).coerce_to(DataFormat::TermSvg)) -} From df05eb77a29bc9baa56764f6041b318f4e55ba4d Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Sat, 26 Apr 2025 08:23:27 -0600 Subject: [PATCH 174/175] chore: Remove unused dev-dependencies --- Cargo.lock | 15 --------------- Cargo.toml | 3 --- 2 files changed, 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dd4fd20..e643134 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,11 +9,8 @@ dependencies = [ "annotate-snippets", "anstream", "anstyle", - "difference", "divan", - "glob", "memchr", - "serde", "snapbox", "unicode-width 0.2.0", ] @@ -139,12 +136,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf0a07a401f374238ab8e2f11a104d2851bf9ce711ec69804834de8af45c7af" -[[package]] -name = "difference" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" - [[package]] name = "divan" version = "0.1.17" @@ -192,12 +183,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - [[package]] name = "hermit-abi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 4a8adf0..8434567 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -123,10 +123,7 @@ unicode-width = "0.2.0" [dev-dependencies] annotate-snippets = { path = ".", features = ["testing-colors"] } anstream = "0.6.13" -difference = "2.0.0" divan = "0.1.14" -glob = "0.3.1" -serde = { version = "1.0.199", features = ["derive"] } snapbox = { version = "0.6.0", features = ["diff", "term-svg", "cmd", "examples"] } [[bench]] From 9c5ba46e1cd041df9e4a62a2936130c1f5c8ceea Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 May 2025 03:41:39 +0000 Subject: [PATCH 175/175] chore(deps): Update Rust crate divan to v0.1.21 (#202) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e643134..532bb57 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -138,9 +138,9 @@ checksum = "baf0a07a401f374238ab8e2f11a104d2851bf9ce711ec69804834de8af45c7af" [[package]] name = "divan" -version = "0.1.17" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0583193020b29b03682d8d33bb53a5b0f50df6daacece12ca99b904cfdcb8c4" +checksum = "a405457ec78b8fe08b0e32b4a3570ab5dff6dd16eb9e76a5ee0a9d9cbd898933" dependencies = [ "cfg-if", "clap", @@ -152,9 +152,9 @@ dependencies = [ [[package]] name = "divan-macros" -version = "0.1.17" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc51d98e636f5e3b0759a39257458b22619cac7e96d932da6eeb052891bb67c" +checksum = "9556bc800956545d6420a640173e5ba7dfa82f38d3ea5a167eb555bc69ac3323" dependencies = [ "proc-macro2", "quote",