diff --git a/.clippy.toml b/.clippy.toml new file mode 100644 index 0000000..2e52a64 --- /dev/null +++ b/.clippy.toml @@ -0,0 +1,4 @@ +allow-print-in-tests = true +allow-expect-in-tests = true +allow-unwrap-in-tests = true +allow-dbg-in-tests = true diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 87676d4..c184420 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: [ @@ -17,30 +18,35 @@ '^\\.github/workflows/rust-next.yml$', ], matchStrings: [ - 'MSRV.*?(?\\d+\\.\\d+(\\.\\d+)?)', - '(?\\d+\\.\\d+(\\.\\d+)?).*?MSRV', + 'STABLE.*?(?\\d+\\.\\d+(\\.\\d+)?)', + '(?\\d+\\.\\d+(\\.\\d+)?).*?STABLE', ], - depNameTemplate: 'rust', + depNameTemplate: 'STABLE', packageNameTemplate: 'rust-lang/rust', datasourceTemplate: 'github-releases', }, ], packageRules: [ { - commitMessageTopic: 'MSRV', + commitMessageTopic: 'Rust Stable', matchManagers: [ 'custom.regex', ], matchPackageNames: [ - 'rust', + 'STABLE', ], - minimumReleaseAge: '84 days', - internalChecksFilter: 'strict', - extractVersion: '^(?\\d+\\.\\d+)', + extractVersion: '^(?\\d+\\.\\d+)', // Drop the patch version schedule: [ '* * * * *', ], + automerge: true, }, + // 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', @@ -66,6 +72,7 @@ matchCurrentVersion: '>=1.0.0', matchUpdateTypes: [ 'minor', + 'patch', ], enabled: false, }, @@ -93,6 +100,7 @@ matchCurrentVersion: '>=1.0.0', matchUpdateTypes: [ 'minor', + 'patch', ], automerge: true, groupName: 'compatible (dev)', diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 442e637..35b3da8 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 f10a0db..a621652 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,21 +14,27 @@ env: CARGO_TERM_COLOR: always CLICOLOR: 1 +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + jobs: ci: 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: matrix: - os: ["ubuntu-latest", "windows-latest", "macos-latest"] + os: ["ubuntu-latest", "windows-latest", "macos-14"] rust: ["stable"] continue-on-error: ${{ matrix.rust != 'stable' }} runs-on: ${{ matrix.os }} @@ -40,16 +46,13 @@ jobs: with: toolchain: ${{ matrix.rust }} - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@cargo-hack - 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 + run: cargo test --workspace --no-run + - name: Test + run: cargo hack test --feature-powerset --workspace msrv: - name: "Check MSRV: 1.73" # MSRV + name: "Check MSRV" runs-on: ubuntu-latest steps: - name: Checkout repository @@ -57,14 +60,11 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.73" # MSRV + toolchain: stable - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@cargo-hack - 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 + run: cargo hack check --feature-powerset --locked --rust-version --ignore-private --workspace --all-targets lockfile: runs-on: ubuntu-latest steps: @@ -76,7 +76,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 @@ -86,7 +86,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: @@ -101,9 +101,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 @@ -119,13 +117,13 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.73" # MSRV + toolchain: "1.76" # STABLE 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 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 6eb6ca1..3d04055 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -5,13 +5,17 @@ permissions: {} # none on: pull_request: push: - branches: [main] + branches: [master] env: RUST_BACKTRACE: 1 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 d8c2d25..ab49963 100644 --- a/.github/workflows/rust-next.yml +++ b/.github/workflows/rust-next.yml @@ -12,12 +12,16 @@ env: CARGO_TERM_COLOR: always CLICOLOR: 1 +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + jobs: test: 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 @@ -32,12 +36,11 @@ jobs: 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 + - uses: taiki-e/install-action@cargo-hack + - name: Build + run: cargo test --workspace --no-run + - name: Test + run: cargo hack test --feature-powerset --workspace latest: name: "Check latest dependencies" runs-on: ubuntu-latest @@ -49,11 +52,10 @@ jobs: with: toolchain: stable - uses: Swatinem/rust-cache@v2 - - name: Update dependencues + - uses: taiki-e/install-action@cargo-hack + - name: Update dependencies 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 + - name: Build + run: cargo test --workspace --no-run + - name: Test + run: cargo hack test --feature-powerset --workspace 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 diff --git a/Cargo.toml b/Cargo.toml index 72bf895..5022f46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,3 +48,70 @@ harness = false [features] default = [] testing-colors = [] + +[lints.rust] +rust_2018_idioms = { level = "warn", priority = -1 } +unreachable_pub = "warn" +unsafe_op_in_unsafe_fn = "warn" +unused_lifetimes = "warn" +unused_macro_rules = "warn" +unused_qualifications = "warn" + +[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" +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" +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" +mem_forget = "warn" +mutex_integer = "warn" +needless_continue = "warn" +needless_for_each = "warn" +negative_feature_names = "warn" +path_buf_push_overwrite = "warn" +ptr_as_ptr = "warn" +rc_mutex = "warn" +redundant_feature_names = "warn" +ref_option_ref = "warn" +rest_pat_in_fully_bound_structs = "warn" +same_functions_in_if_condition = "warn" +self_named_module_files = "warn" +semicolon_if_nothing_returned = "warn" +str_to_string = "warn" +string_add = "warn" +string_add_assign = "warn" +string_lit_as_bytes = "warn" +string_to_string = "warn" +todo = "warn" +trait_duplication_in_bounds = "warn" +verbose_file_reads = "warn" +wildcard_imports = "warn" +zero_sized_map_values = "warn" diff --git a/benches/simple.rs b/benches/simple.rs index fccb70b..723793e 100644 --- a/benches/simple.rs +++ b/benches/simple.rs @@ -50,7 +50,7 @@ fn create_snippet(renderer: Renderer) { pub fn criterion_benchmark(c: &mut Criterion) { c.bench_function("format", |b| { - b.iter(|| black_box(create_snippet(Renderer::plain()))) + b.iter(|| black_box(create_snippet(Renderer::plain()))); }); } 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(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 +] # This section is considered when running `cargo deny check bans`. # More documentation about the '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 = [] diff --git a/src/lib.rs b/src/lib.rs index bfd2dc6..ed9b3f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,3 @@ -#![deny(rust_2018_idioms)] -#![warn(missing_debug_implementations)] - //! A library for formatting of text or programming code snippets. //! //! It's primary purpose is to build an ASCII-graphical representation of the snippet @@ -40,6 +37,11 @@ //! cargo add annotate-snippets --dev --feature testing-colors //! ``` +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![warn(clippy::print_stderr)] +#![warn(clippy::print_stdout)] +#![warn(missing_debug_implementations)] + pub mod renderer; mod snippet; diff --git a/src/renderer/display_list.rs b/src/renderer/display_list.rs index ead3db9..d94a660 100644 --- a/src/renderer/display_list.rs +++ b/src/renderer/display_list.rs @@ -1,4 +1,4 @@ -//! display_list module stores the output model for the snippet. +//! `display_list` module stores the output model for the snippet. //! //! `DisplayList` is a central structure in the crate, which contains //! the structured list of lines to be displayed. @@ -48,9 +48,9 @@ const WARNING_TXT: &str = "warning"; /// List of lines to be displayed. pub(crate) struct DisplayList<'a> { - pub body: Vec>, - pub stylesheet: &'a Stylesheet, - pub anonymized_line_numbers: bool, + pub(crate) body: Vec>, + pub(crate) stylesheet: &'a Stylesheet, + pub(crate) anonymized_line_numbers: bool, } impl<'a> PartialEq for DisplayList<'a> { @@ -147,8 +147,8 @@ impl<'a> DisplayList<'a> { #[derive(Debug, PartialEq)] pub(crate) struct DisplaySet<'a> { - pub display_lines: Vec>, - pub margin: Margin, + pub(crate) display_lines: Vec>, + pub(crate) margin: Margin, } impl<'a> DisplaySet<'a> { @@ -493,15 +493,15 @@ impl<'a> DisplaySet<'a> { /// Inline annotation which can be used in either Raw or Source line. #[derive(Debug, PartialEq)] -pub struct Annotation<'a> { - pub annotation_type: DisplayAnnotationType, - pub id: Option<&'a str>, - pub label: Vec>, +pub(crate) struct Annotation<'a> { + pub(crate) annotation_type: DisplayAnnotationType, + pub(crate) id: Option<&'a str>, + pub(crate) label: Vec>, } /// A single line used in `DisplayList`. #[derive(Debug, PartialEq)] -pub enum DisplayLine<'a> { +pub(crate) enum DisplayLine<'a> { /// A line with `lineno` portion of the slice. Source { lineno: Option, @@ -519,7 +519,7 @@ pub enum DisplayLine<'a> { /// A source line. #[derive(Debug, PartialEq)] -pub enum DisplaySourceLine<'a> { +pub(crate) enum DisplaySourceLine<'a> { /// A line with the content of the Snippet. Content { text: &'a str, @@ -530,17 +530,17 @@ pub enum DisplaySourceLine<'a> { } #[derive(Debug, PartialEq)] -pub struct DisplaySourceAnnotation<'a> { - pub annotation: Annotation<'a>, - pub range: (usize, usize), - pub annotation_type: DisplayAnnotationType, - pub annotation_part: DisplayAnnotationPart, +pub(crate) struct DisplaySourceAnnotation<'a> { + pub(crate) annotation: Annotation<'a>, + pub(crate) range: (usize, usize), + pub(crate) annotation_type: DisplayAnnotationType, + pub(crate) annotation_part: DisplayAnnotationPart, } /// Raw line - a line which does not have the `lineno` part and is not considered /// a part of the snippet. #[derive(Debug, PartialEq)] -pub enum DisplayRawLine<'a> { +pub(crate) enum DisplayRawLine<'a> { /// A line which provides information about the location of the given /// slice in the project structure. Origin { @@ -566,23 +566,23 @@ pub enum DisplayRawLine<'a> { /// An inline text fragment which any label is composed of. #[derive(Debug, PartialEq)] -pub struct DisplayTextFragment<'a> { - pub content: &'a str, - pub style: DisplayTextStyle, +pub(crate) struct DisplayTextFragment<'a> { + pub(crate) content: &'a str, + pub(crate) style: DisplayTextStyle, } /// A style for the `DisplayTextFragment` which can be visually formatted. /// /// This information may be used to emphasis parts of the label. #[derive(Debug, Clone, Copy, PartialEq)] -pub enum DisplayTextStyle { +pub(crate) enum DisplayTextStyle { Regular, Emphasis, } /// An indicator of what part of the annotation a given `Annotation` is. #[derive(Debug, Clone, PartialEq)] -pub enum DisplayAnnotationPart { +pub(crate) enum DisplayAnnotationPart { /// A standalone, single-line annotation. Standalone, /// A continuation of a multi-line label of an annotation. @@ -595,14 +595,14 @@ pub enum DisplayAnnotationPart { /// A visual mark used in `inline_marks` field of the `DisplaySourceLine`. #[derive(Debug, Clone, PartialEq)] -pub struct DisplayMark { - pub mark_type: DisplayMarkType, - pub annotation_type: DisplayAnnotationType, +pub(crate) struct DisplayMark { + pub(crate) mark_type: DisplayMarkType, + pub(crate) annotation_type: DisplayAnnotationType, } /// A type of the `DisplayMark`. #[derive(Debug, Clone, PartialEq)] -pub enum DisplayMarkType { +pub(crate) enum DisplayMarkType { /// A mark indicating a multiline annotation going through the current line. AnnotationThrough, /// A mark indicating a multiline annotation starting on the given line. @@ -617,7 +617,7 @@ pub enum DisplayMarkType { /// * An underline for `Error` may be `^^^` while for `Warning` it could be `---`. /// * `ColorStylesheet` may use different colors for different annotations. #[derive(Debug, Clone, PartialEq)] -pub enum DisplayAnnotationType { +pub(crate) enum DisplayAnnotationType { None, Error, Warning, @@ -642,7 +642,7 @@ impl From for DisplayAnnotationType { /// for multi-slice cases. // TODO: private #[derive(Debug, Clone, PartialEq)] -pub enum DisplayHeaderType { +pub(crate) enum DisplayHeaderType { /// Initial header is the first header in the snippet. Initial, @@ -728,9 +728,9 @@ fn format_message( } if let Some(first) = sets.first_mut() { - body.into_iter().for_each(|line| { + for line in body { first.display_lines.insert(0, line); - }); + } } else { sets.push(DisplaySet { display_lines: body, @@ -1335,7 +1335,7 @@ const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ ]; fn normalize_whitespace(str: &str) -> String { - let mut s = str.to_string(); + let mut s = str.to_owned(); for (c, replacement) in OUTPUT_REPLACEMENTS { s = s.replace(*c, replacement); } diff --git a/src/renderer/margin.rs b/src/renderer/margin.rs index 3f1b28b..c484416 100644 --- a/src/renderer/margin.rs +++ b/src/renderer/margin.rs @@ -5,7 +5,7 @@ const LONG_WHITESPACE: usize = 20; const LONG_WHITESPACE_PADDING: usize = 4; #[derive(Clone, Copy, Debug, PartialEq)] -pub struct Margin { +pub(crate) struct Margin { /// The available whitespace in the left that can be consumed when centering. whitespace_left: usize, /// The column of the beginning of left-most span. @@ -24,7 +24,7 @@ pub struct Margin { } impl Margin { - pub fn new( + pub(crate) fn new( whitespace_left: usize, span_left: usize, span_right: usize, diff --git a/tests/fixtures/deserialize.rs b/tests/fixtures/deserialize.rs index 2d1452b..3ddef79 100644 --- a/tests/fixtures/deserialize.rs +++ b/tests/fixtures/deserialize.rs @@ -5,11 +5,11 @@ use annotate_snippets::renderer::DEFAULT_TERM_WIDTH; use annotate_snippets::{Annotation, Level, Message, Renderer, Snippet}; #[derive(Deserialize)] -pub struct Fixture<'a> { +pub(crate) struct Fixture<'a> { #[serde(default)] - pub renderer: RendererDef, + pub(crate) renderer: RendererDef, #[serde(borrow)] - pub message: MessageDef<'a>, + pub(crate) message: MessageDef<'a>, } #[derive(Deserialize)] @@ -88,7 +88,7 @@ impl<'a> From> for Snippet<'a> { } = val; let mut snippet = Snippet::source(source).line_start(line_start).fold(fold); if let Some(origin) = origin { - snippet = snippet.origin(origin) + snippet = snippet.origin(origin); } snippet = snippet.annotations(annotations); snippet @@ -127,11 +127,11 @@ impl<'a> From> for Annotation<'a> { } #[derive(Serialize, Deserialize)] -pub struct LabelDef<'a> { +pub(crate) struct LabelDef<'a> { #[serde(with = "LevelDef")] - pub level: Level, + pub(crate) level: Level, #[serde(borrow)] - pub label: &'a str, + pub(crate) label: &'a str, } #[allow(dead_code)] diff --git a/tests/fixtures/main.rs b/tests/fixtures/main.rs index c0e351c..81d0246 100644 --- a/tests/fixtures/main.rs +++ b/tests/fixtures/main.rs @@ -15,7 +15,7 @@ fn main() { fn setup(input_path: std::path::PathBuf) -> tryfn::Case { let name = input_path.file_name().unwrap().to_str().unwrap().to_owned(); - let expected = tryfn::Data::read_from(&input_path.with_extension("svg"), None); + let expected = Data::read_from(&input_path.with_extension("svg"), None); tryfn::Case { name, fixture: input_path, @@ -26,7 +26,7 @@ fn setup(input_path: std::path::PathBuf) -> tryfn::Case { fn test(input_path: &std::path::Path) -> Result> { let src = std::fs::read_to_string(input_path)?; let (renderer, message): (Renderer, Message<'_>) = - toml::from_str(&src).map(|a: Fixture| (a.renderer.into(), a.message.into()))?; + toml::from_str(&src).map(|a: Fixture<'_>| (a.renderer.into(), a.message.into()))?; let actual = renderer.render(message).to_string(); Ok(Data::from(actual).coerce_to(DataFormat::TermSvg)) }