diff --git a/coverage/amber.png b/coverage/amber.png new file mode 100644 index 000000000..2cab170d8 Binary files /dev/null and b/coverage/amber.png differ diff --git a/coverage/cargo-dylint/src/index-sort-f.html b/coverage/cargo-dylint/src/index-sort-f.html new file mode 100644 index 000000000..551cdb3fb --- /dev/null +++ b/coverage/cargo-dylint/src/index-sort-f.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - cargo-dylint/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - cargo-dylint/srcHitTotalCoverage
Test:unnamedLines:15016392.0 %
Date:2024-04-23 03:30:56Functions:134429.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
main.rs +
92.0%92.0%
+
92.0 %150 / 16329.5 %13 / 44
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/cargo-dylint/src/index-sort-l.html b/coverage/cargo-dylint/src/index-sort-l.html new file mode 100644 index 000000000..fdec8ff7c --- /dev/null +++ b/coverage/cargo-dylint/src/index-sort-l.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - cargo-dylint/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - cargo-dylint/srcHitTotalCoverage
Test:unnamedLines:15016392.0 %
Date:2024-04-23 03:30:56Functions:134429.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
main.rs +
92.0%92.0%
+
92.0 %150 / 16329.5 %13 / 44
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/cargo-dylint/src/index.html b/coverage/cargo-dylint/src/index.html new file mode 100644 index 000000000..60e41f162 --- /dev/null +++ b/coverage/cargo-dylint/src/index.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - cargo-dylint/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - cargo-dylint/srcHitTotalCoverage
Test:unnamedLines:15016392.0 %
Date:2024-04-23 03:30:56Functions:134429.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
main.rs +
92.0%92.0%
+
92.0 %150 / 16329.5 %13 / 44
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/cargo-dylint/src/main.rs.func-sort-c.html b/coverage/cargo-dylint/src/main.rs.func-sort-c.html new file mode 100644 index 000000000..686488b0e --- /dev/null +++ b/coverage/cargo-dylint/src/main.rs.func-sort-c.html @@ -0,0 +1,248 @@ + + + + + + + LCOV - unnamed - cargo-dylint/src/main.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - cargo-dylint/src - main.rs (source / functions)HitTotalCoverage
Test:unnamedLines:15016392.0 %
Date:2024-04-23 03:30:56Functions:134429.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#0}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#1}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#2}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#4}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#0}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#1}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#2}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#3}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#4}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#5}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#0}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#1}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#3}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#4}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#0}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#1}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#2}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#3}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#4}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#5}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#0}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#1}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#2}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#3}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#0}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#1}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#2}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#3}0
<cargo_dylint::OutputOptions as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#0}0
<cargo_dylint::OutputOptions as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#0}0
cargo_dylint::cargo_dylint::<_>0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#5}1
cargo_dylint::tests::usage1
cargo_dylint::tests::verify_cli1
cargo_dylint::tests::version1
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#3}2
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#5}3
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#2}9
<cargo_dylint::LibrarySelection>::absorb9
<dylint::opts::LibrarySelection as core::convert::From<cargo_dylint::LibrarySelection>>::from35
<dylint::opts::Dylint as core::convert::From<cargo_dylint::Dylint>>::from39
cargo_dylint::cargo_dylint::<std::ffi::os_str::OsString>41
cargo_dylint::main41
cargo_dylint::main::{closure#0}41
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/cargo-dylint/src/main.rs.func.html b/coverage/cargo-dylint/src/main.rs.func.html new file mode 100644 index 000000000..84c7b00a7 --- /dev/null +++ b/coverage/cargo-dylint/src/main.rs.func.html @@ -0,0 +1,248 @@ + + + + + + + LCOV - unnamed - cargo-dylint/src/main.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - cargo-dylint/src - main.rs (source / functions)HitTotalCoverage
Test:unnamedLines:15016392.0 %
Date:2024-04-23 03:30:56Functions:134429.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#0}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#1}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#2}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#3}2
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#4}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#5}1
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#0}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#1}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#2}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#3}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#4}0
<cargo_dylint::Dylint as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#5}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#0}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#1}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#2}9
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#3}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#4}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#5}3
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#0}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#1}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#2}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#3}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#4}0
<cargo_dylint::LibrarySelection as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#5}0
<cargo_dylint::LibrarySelection>::absorb9
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#0}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#1}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#2}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#3}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#0}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#1}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#2}0
<cargo_dylint::Operation as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#3}0
<cargo_dylint::OutputOptions as clap_builder::derive::FromArgMatches>::from_arg_matches_mut::{closure#0}0
<cargo_dylint::OutputOptions as clap_builder::derive::FromArgMatches>::update_from_arg_matches_mut::{closure#0}0
<dylint::opts::Dylint as core::convert::From<cargo_dylint::Dylint>>::from39
<dylint::opts::LibrarySelection as core::convert::From<cargo_dylint::LibrarySelection>>::from35
cargo_dylint::cargo_dylint::<_>0
cargo_dylint::cargo_dylint::<std::ffi::os_str::OsString>41
cargo_dylint::main41
cargo_dylint::main::{closure#0}41
cargo_dylint::tests::usage1
cargo_dylint::tests::verify_cli1
cargo_dylint::tests::version1
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/cargo-dylint/src/main.rs.gcov.html b/coverage/cargo-dylint/src/main.rs.gcov.html new file mode 100644 index 000000000..7211a34a6 --- /dev/null +++ b/coverage/cargo-dylint/src/main.rs.gcov.html @@ -0,0 +1,519 @@ + + + + + + + LCOV - unnamed - cargo-dylint/src/main.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - cargo-dylint/src - main.rs (source / functions)HitTotalCoverage
Test:unnamedLines:15016392.0 %
Date:2024-04-23 03:30:56Functions:134429.5 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use clap::{crate_version, ArgAction, Parser};
+       2             : use std::{
+       3             :     ffi::{OsStr, OsString},
+       4             :     fmt::Debug,
+       5             : };
+       6             : 
+       7             : #[derive(Debug, Parser)]
+       8             : #[clap(bin_name = "cargo", display_name = "cargo")]
+       9             : struct Opts {
+      10             :     #[clap(subcommand)]
+      11             :     subcmd: CargoSubcommand,
+      12             : }
+      13             : 
+      14             : #[derive(Debug, Parser)]
+      15             : enum CargoSubcommand {
+      16             :     Dylint(Dylint),
+      17             : }
+      18             : 
+      19             : #[allow(clippy::struct_excessive_bools)]
+      20             : #[derive(Debug, Parser)]
+      21             : #[clap(
+      22             :     version = crate_version!(),
+      23             :     args_conflicts_with_subcommands = true,
+      24             :     after_help = r#"ENVIRONMENT VARIABLES:
+      25             : 
+      26             : DYLINT_DRIVER_PATH (default: $HOME/.dylint_drivers) is the directory where Dylint stores rustc
+      27             : drivers.
+      28             : 
+      29             : DYLINT_LIBRARY_PATH (default: none) is a colon-separated list of directories where Dylint searches
+      30             : for libraries.
+      31             : 
+      32             : DYLINT_RUSTFLAGS (default: none) is a space-separated list of flags that Dylint passes to `rustc`
+      33             : when checking the packages in the workspace.
+      34             : 
+      35             : METADATA EXAMPLE:
+      36             : 
+      37             :     [workspace.metadata.dylint]
+      38             :     libraries = [
+      39             :         { git = "https://github.com/trailofbits/dylint", pattern = "examples/*/*" },
+      40             :         { path = "libs/*" },
+      41             :     ]
+      42             : "#,
+      43             : )]
+      44             : // smoelius: Please keep the last four fields `args`, `operation`, `lib_sel`, and `output`, in that
+      45             : // order. Please keep all other fields sorted.
+      46             : struct Dylint {
+      47             :     #[clap(long, help = "Automatically apply lint suggestions")]
+      48           0 :     fix: bool,
+      49             : 
+      50             :     #[clap(long, help = "Continue if `cargo check` fails")]
+      51           0 :     keep_going: bool,
+      52             : 
+      53             :     #[clap(long, help = "Do not check other packages within the workspace")]
+      54           0 :     no_deps: bool,
+      55             : 
+      56             :     #[clap(
+      57             :         action = ArgAction::Append,
+      58             :         number_of_values = 1,
+      59             :         short,
+      60             :         long = "package",
+      61             :         value_name = "spec",
+      62             :         help = "Package to check"
+      63             :     )]
+      64           2 :     packages: Vec<String>,
+      65             : 
+      66             :     #[clap(long, help = "Check all packages in the workspace")]
+      67           0 :     workspace: bool,
+      68             : 
+      69             :     #[clap(last = true, help = "Arguments for `cargo check`")]
+      70           1 :     args: Vec<String>,
+      71             : 
+      72             :     #[clap(subcommand)]
+      73             :     operation: Option<Operation>,
+      74             : 
+      75             :     #[clap(flatten)]
+      76             :     lib_sel: LibrarySelection,
+      77             : 
+      78             :     #[clap(flatten)]
+      79             :     output: OutputOptions,
+      80             : }
+      81             : 
+      82             : #[derive(Debug, Parser)]
+      83             : enum Operation {
+      84             :     #[clap(
+      85             :         about = "List libraries or lints",
+      86             :         long_about = "If no libraries are named, list the name, toolchain, and location of all \
+      87             : discovered libraries.
+      88             : 
+      89             : If at least one library is named, list the name, level, and description of all lints in all named \
+      90             : libraries.
+      91             : 
+      92             : Combine with `--all` to list all lints in all discovered libraries."
+      93             :     )]
+      94             :     List {
+      95             :         #[clap(flatten)]
+      96             :         lib_sel: LibrarySelection,
+      97             :     },
+      98             : 
+      99             :     #[clap(
+     100             :         about = "Create a new library package",
+     101             :         long_about = "Create a new library package at <PATH>"
+     102             :     )]
+     103             :     New {
+     104             :         #[clap(long, help = "Put the package in its own workspace")]
+     105           0 :         isolate: bool,
+     106             : 
+     107             :         #[clap(help = "Path to library package")]
+     108           0 :         path: String,
+     109             :     },
+     110             : 
+     111             :     #[clap(
+     112             :         about = "Upgrade library package",
+     113             :         long_about = "Upgrade the library package at <PATH> to the latest version of \
+     114             :                       `clippy_utils`"
+     115             :     )]
+     116             :     Upgrade {
+     117             :         #[clap(long, hide = true)]
+     118           0 :         allow_downgrade: bool,
+     119             : 
+     120             :         #[clap(
+     121             :             long,
+     122             :             value_name = "version",
+     123             :             help = "Upgrade to the version of `clippy_utils` with tag `rust-<version>`"
+     124             :         )]
+     125             :         rust_version: Option<String>,
+     126             : 
+     127             :         #[clap(help = "Path to library package")]
+     128           0 :         path: String,
+     129             :     },
+     130             : }
+     131             : 
+     132             : #[derive(Debug, Parser)]
+     133             : #[cfg_attr(feature = "__clap_headings", clap(next_help_heading = Some("Library Selection")))]
+     134             : struct LibrarySelection {
+     135             :     #[clap(long, help = "Load all discovered libraries")]
+     136           0 :     all: bool,
+     137             : 
+     138             :     #[clap(
+     139             :         long,
+     140             :         requires("git"),
+     141             :         help = "Branch to use when downloading library packages"
+     142             :     )]
+     143             :     branch: Option<String>,
+     144             : 
+     145             :     #[clap(
+     146             :         long,
+     147             :         value_name = "url",
+     148             :         conflicts_with("paths"),
+     149             :         help = "Git url containing library packages"
+     150             :     )]
+     151             :     git: Option<String>,
+     152             : 
+     153             :     #[clap(
+     154             :         action = ArgAction::Append,
+     155             :         number_of_values = 1,
+     156             :         long = "lib-path",
+     157             :         value_name = "path",
+     158             :         help = "Library path to load lints from"
+     159             :     )]
+     160           0 :     lib_paths: Vec<String>,
+     161             : 
+     162             :     #[clap(
+     163             :         action = ArgAction::Append,
+     164             :         number_of_values = 1,
+     165             :         long = "lib",
+     166             :         value_name = "name",
+     167             :         help = "Library name to load lints from. A file with a name of the form \"DLL_PREFIX \
+     168             :         <name> '@' TOOLCHAIN DLL_SUFFIX\" is searched for in the directories listed in \
+     169             :         DYLINT_LIBRARY_PATH, and in the `target/release` directories produced by building the \
+     170             :         current workspace's metadata entries (see example below)."
+     171             :     )]
+     172           9 :     libs: Vec<String>,
+     173             : 
+     174             :     #[clap(
+     175             :         long,
+     176             :         value_name = "path",
+     177             :         help = "Path to Cargo.toml. Note: if the manifest uses metadata, then `--manifest-path \
+     178             :                 <path>` must appear before `--`, not after."
+     179             :     )]
+     180             :     manifest_path: Option<String>,
+     181             : 
+     182             :     #[clap(long, help = "Do not build metadata entries")]
+     183           0 :     no_build: bool,
+     184             : 
+     185             :     #[clap(long, help = "Ignore metadata entirely")]
+     186           0 :     no_metadata: bool,
+     187             : 
+     188             :     #[clap(
+     189             :         action = ArgAction::Append,
+     190             :         number_of_values = 1,
+     191             :         long = "path",
+     192             :         value_name = "path",
+     193             :         conflicts_with("git"),
+     194             :         help = "Path containing library packages"
+     195             :     )]
+     196           3 :     paths: Vec<String>,
+     197             : 
+     198             :     #[clap(
+     199             :         long,
+     200             :         help = "Subdirectories of the `--git` or `--path` argument containing library packages"
+     201             :     )]
+     202             :     pattern: Option<String>,
+     203             : 
+     204             :     #[clap(
+     205             :         long,
+     206             :         requires("git"),
+     207             :         help = "Specific commit to use when downloading library packages"
+     208             :     )]
+     209             :     rev: Option<String>,
+     210             : 
+     211             :     #[clap(
+     212             :         long,
+     213             :         requires("git"),
+     214             :         help = "Tag to use when downloading library packages"
+     215             :     )]
+     216             :     tag: Option<String>,
+     217             : }
+     218             : 
+     219             : #[derive(Debug, Parser)]
+     220             : #[cfg_attr(feature = "__clap_headings", clap(next_help_heading = Some("Output Options")))]
+     221             : struct OutputOptions {
+     222             :     #[clap(long, value_name = "path", help = "Path to pipe stderr to")]
+     223             :     pipe_stderr: Option<String>,
+     224             : 
+     225             :     #[clap(long, value_name = "path", help = "Path to pipe stdout to")]
+     226             :     pipe_stdout: Option<String>,
+     227             : 
+     228             :     #[clap(
+     229             :         global = true,
+     230             :         short,
+     231             :         long,
+     232             :         help = "Do not show warnings or progress running commands besides `cargo check` and \
+     233             :                 `cargo fix`"
+     234             :     )]
+     235           0 :     quiet: bool,
+     236             : }
+     237             : 
+     238             : impl From<Dylint> for dylint::opts::Dylint {
+     239          39 :     fn from(opts: Dylint) -> Self {
+     240          39 :         let Dylint {
+     241          39 :             fix,
+     242          39 :             keep_going,
+     243          39 :             no_deps,
+     244          39 :             packages,
+     245          39 :             workspace,
+     246          39 :             args,
+     247          39 :             operation,
+     248          39 :             mut lib_sel,
+     249          39 :             output:
+     250          39 :                 OutputOptions {
+     251          39 :                     pipe_stderr,
+     252          39 :                     pipe_stdout,
+     253          39 :                     quiet,
+     254          39 :                 },
+     255          39 :         } = opts;
+     256          39 :         let operation = match operation {
+     257          26 :             None => dylint::opts::Operation::Check({
+     258          26 :                 dylint::opts::Check {
+     259          26 :                     lib_sel: lib_sel.into(),
+     260          26 :                     fix,
+     261          26 :                     keep_going,
+     262          26 :                     no_deps,
+     263          26 :                     packages,
+     264          26 :                     workspace,
+     265          26 :                     args,
+     266          26 :                 }
+     267          26 :             }),
+     268           9 :             Some(Operation::List { lib_sel: other }) => {
+     269           9 :                 lib_sel.absorb(other);
+     270           9 :                 dylint::opts::Operation::List(dylint::opts::List {
+     271           9 :                     lib_sel: lib_sel.into(),
+     272           9 :                 })
+     273             :             }
+     274           1 :             Some(Operation::New { isolate, path }) => {
+     275           1 :                 dylint::opts::Operation::New(dylint::opts::New { isolate, path })
+     276             :             }
+     277             :             Some(Operation::Upgrade {
+     278           3 :                 allow_downgrade,
+     279           3 :                 rust_version,
+     280           3 :                 path,
+     281           3 :             }) => dylint::opts::Operation::Upgrade(dylint::opts::Upgrade {
+     282           3 :                 allow_downgrade,
+     283           3 :                 rust_version,
+     284           3 :                 path,
+     285           3 :             }),
+     286             :         };
+     287          39 :         Self {
+     288          39 :             pipe_stderr,
+     289          39 :             pipe_stdout,
+     290          39 :             quiet,
+     291          39 :             operation,
+     292          39 :         }
+     293          39 :     }
+     294             : }
+     295             : 
+     296             : macro_rules! option_absorb {
+     297             :     ($this:expr, $other:expr) => {
+     298             :         if $other.is_some() {
+     299             :             assert!(
+     300             :                 $this.is_none(),
+     301             :                 "`--{}` used multiple times",
+     302             :                 stringify!($other).replace("_", "-")
+     303             :             );
+     304             :             *$this = $other;
+     305             :         }
+     306             :     };
+     307             : }
+     308             : 
+     309             : impl LibrarySelection {
+     310           9 :     pub fn absorb(&mut self, other: Self) {
+     311           9 :         let Self {
+     312           9 :             all,
+     313           9 :             branch,
+     314           9 :             git,
+     315           9 :             lib_paths,
+     316           9 :             libs,
+     317           9 :             manifest_path,
+     318           9 :             no_build,
+     319           9 :             no_metadata,
+     320           9 :             paths,
+     321           9 :             pattern,
+     322           9 :             rev,
+     323           9 :             tag,
+     324           9 :         } = other;
+     325           9 :         self.all |= all;
+     326           9 :         option_absorb!(&mut self.branch, branch);
+     327           9 :         option_absorb!(&mut self.git, git);
+     328           9 :         self.lib_paths.extend(lib_paths);
+     329           9 :         self.libs.extend(libs);
+     330           9 :         option_absorb!(&mut self.manifest_path, manifest_path);
+     331           9 :         self.no_build |= no_build;
+     332           9 :         self.no_metadata |= no_metadata;
+     333           9 :         self.paths.extend(paths);
+     334           9 :         option_absorb!(&mut self.pattern, pattern);
+     335           9 :         option_absorb!(&mut self.rev, rev);
+     336           9 :         option_absorb!(&mut self.tag, tag);
+     337           9 :     }
+     338             : }
+     339             : 
+     340             : impl From<LibrarySelection> for dylint::opts::LibrarySelection {
+     341          35 :     fn from(lib_sel: LibrarySelection) -> Self {
+     342          35 :         let LibrarySelection {
+     343          35 :             all,
+     344          35 :             branch,
+     345          35 :             git,
+     346          35 :             lib_paths,
+     347          35 :             libs,
+     348          35 :             manifest_path,
+     349          35 :             no_build,
+     350          35 :             no_metadata,
+     351          35 :             paths,
+     352          35 :             pattern,
+     353          35 :             rev,
+     354          35 :             tag,
+     355          35 :         } = lib_sel;
+     356          35 :         Self {
+     357          35 :             all,
+     358          35 :             branch,
+     359          35 :             git,
+     360          35 :             lib_paths,
+     361          35 :             libs,
+     362          35 :             manifest_path,
+     363          35 :             no_build,
+     364          35 :             no_metadata,
+     365          35 :             paths,
+     366          35 :             pattern,
+     367          35 :             rev,
+     368          35 :             tag,
+     369          35 :         }
+     370          35 :     }
+     371             : }
+     372             : 
+     373          41 : fn main() -> dylint::ColorizedResult<()> {
+     374          41 :     env_logger::try_init().unwrap_or_else(|error| {
+     375          41 :         dylint::__warn(
+     376          41 :             &dylint::opts::Dylint::default(),
+     377          41 :             &format!("`env_logger` already initialized: {error}"),
+     378          41 :         );
+     379          41 :     });
+     380          41 : 
+     381          41 :     let args: Vec<_> = std::env::args().map(OsString::from).collect();
+     382          41 : 
+     383          41 :     cargo_dylint(&args)
+     384          41 : }
+     385             : 
+     386          41 : fn cargo_dylint<T: AsRef<OsStr>>(args: &[T]) -> dylint::ColorizedResult<()> {
+     387          41 :     match Opts::parse_from(args).subcmd {
+     388          41 :         CargoSubcommand::Dylint(opts) => dylint::run(&dylint::opts::Dylint::from(opts)),
+     389          41 :     }
+     390          41 :     .map_err(dylint::ColorizedError::new)
+     391          41 : }
+     392             : 
+     393             : #[cfg(test)]
+     394             : mod tests {
+     395             :     use super::*;
+     396             :     use assert_cmd::prelude::*;
+     397             :     use clap::CommandFactory;
+     398             : 
+     399             :     #[test]
+     400           1 :     fn verify_cli() {
+     401           1 :         Opts::command().debug_assert();
+     402           1 :     }
+     403             : 
+     404             :     #[test]
+     405           1 :     fn usage() {
+     406           1 :         std::process::Command::cargo_bin("cargo-dylint")
+     407           1 :             .unwrap()
+     408           1 :             .args(["dylint", "--help"])
+     409           1 :             .assert()
+     410           1 :             .success()
+     411           1 :             .stdout(predicates::str::contains("Usage: cargo dylint"));
+     412           1 :     }
+     413             : 
+     414             :     #[test]
+     415           1 :     fn version() {
+     416           1 :         std::process::Command::cargo_bin("cargo-dylint")
+     417           1 :             .unwrap()
+     418           1 :             .args(["dylint", "--version"])
+     419           1 :             .assert()
+     420           1 :             .success()
+     421           1 :             .stdout(format!("cargo-dylint {}\n", env!("CARGO_PKG_VERSION")));
+     422           1 :     }
+     423             : 
+     424             :     // `no_env_logger_warning` fails if [`std::process::Command::new`] is replaced with
+     425             :     // [`assert_cmd::cargo::CommandCargoExt::cargo_bin`]. I don't understand why.
+     426             :     //
+     427             :     // [`assert_cmd::cargo::CommandCargoExt::cargo_bin`]: https://docs.rs/assert_cmd/latest/assert_cmd/cargo/trait.CommandCargoExt.html#tymethod.cargo_bin
+     428             :     // [`std::process::Command::new`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.new
+     429             :     //
+     430             :     // smoelius: I am switching to `assert_cmd::cargo::CommandCargoExt::cargo_bin` and disabling
+     431             :     // this test. `cargo run` without a `--features=...` argument can cause `cargo-dylint` to be
+     432             :     // rebuilt with the wrong features.
+     433             :     #[cfg(any())]
+     434             :     #[test]
+     435             :     fn no_env_logger_warning() {
+     436             :         std::process::Command::cargo_bin("cargo-dylint")
+     437             :             .unwrap()
+     438             :             .arg("dylint")
+     439             :             .assert()
+     440             :             .failure()
+     441             :             .stderr(predicates::str::contains("`env_logger` already initialized").not());
+     442             :     }
+     443             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/driver/src/index-sort-f.html b/coverage/driver/src/index-sort-f.html new file mode 100644 index 000000000..1dd4f2206 --- /dev/null +++ b/coverage/driver/src/index-sort-f.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - driver/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - driver/srcHitTotalCoverage
Test:unnamedLines:6929123.7 %
Date:2024-04-23 03:30:56Functions:53414.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
lib.rs +
23.7%23.7%
+
23.7 %69 / 29114.7 %5 / 34
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/driver/src/index-sort-l.html b/coverage/driver/src/index-sort-l.html new file mode 100644 index 000000000..32bb35c75 --- /dev/null +++ b/coverage/driver/src/index-sort-l.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - driver/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - driver/srcHitTotalCoverage
Test:unnamedLines:6929123.7 %
Date:2024-04-23 03:30:56Functions:53414.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
lib.rs +
23.7%23.7%
+
23.7 %69 / 29114.7 %5 / 34
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/driver/src/index.html b/coverage/driver/src/index.html new file mode 100644 index 000000000..d3a72e723 --- /dev/null +++ b/coverage/driver/src/index.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - driver/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - driver/srcHitTotalCoverage
Test:unnamedLines:6929123.7 %
Date:2024-04-23 03:30:56Functions:53414.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
lib.rs +
23.7%23.7%
+
23.7 %69 / 29114.7 %5 / 34
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/driver/src/lib.rs.func-sort-c.html b/coverage/driver/src/lib.rs.func-sort-c.html new file mode 100644 index 000000000..0ef755e43 --- /dev/null +++ b/coverage/driver/src/lib.rs.func-sort-c.html @@ -0,0 +1,208 @@ + + + + + + + LCOV - unnamed - driver/src/lib.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - driver/src - lib.rs (source / functions)HitTotalCoverage
Test:unnamedLines:6929123.7 %
Date:2024-04-23 03:30:56Functions:53414.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint_driver::Callbacks as rustc_driver_impl::Callbacks>::config0
<dylint_driver::Callbacks as rustc_driver_impl::Callbacks>::config::{closure#0}0
<dylint_driver::Callbacks as rustc_driver_impl::Callbacks>::config::{closure#0}::{closure#0}0
<dylint_driver::Callbacks as rustc_driver_impl::Callbacks>::config::{closure#0}::{closure#1}0
<dylint_driver::Callbacks as rustc_driver_impl::Callbacks>::config::{closure#0}::{closure#2}0
<dylint_driver::Callbacks>::new0
<dylint_driver::Callbacks>::new::{closure#0}0
<dylint_driver::Lint as core::convert::From<&rustc_lint_defs::Lint>>::from0
<dylint_driver::LoadedLibrary>::register_lints0
<dylint_driver::LoadedLibrary>::register_lints::{closure#0}0
<dylint_driver::LoadedLibrary>::register_lints::{closure#1}0
<rustc_session::session::Session as dylint_driver::ParseSess>::parse_sess0
dylint_driver::dylint_driver::<_>0
dylint_driver::dylint_driver::<_>::{closure#0}0
dylint_driver::early_error::<_>0
dylint_driver::list_enabled0
dylint_driver::list_enabled::{closure#0}0
dylint_driver::list_lints0
dylint_driver::list_lints::{closure#0}0
dylint_driver::list_lints::{closure#1}0
dylint_driver::paths0
dylint_driver::paths::{closure#0}0
dylint_driver::run::<_>0
dylint_driver::rustflags0
dylint_driver::rustflags::{closure#0}0
dylint_driver::rustflags::{closure#1}0
dylint_driver::session_err::<_>0
dylint_driver::sysroot0
dylint_driver::zero_mir_opt_level0
dylint_driver::test::channel_is_nightly1
dylint_driver::test::no_rustc1
dylint_driver::test::plain_rustc1
dylint_driver::test::qualified_rustc1
dylint_driver::rustc_args::<&str12
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/driver/src/lib.rs.func.html b/coverage/driver/src/lib.rs.func.html new file mode 100644 index 000000000..ca31bf442 --- /dev/null +++ b/coverage/driver/src/lib.rs.func.html @@ -0,0 +1,208 @@ + + + + + + + LCOV - unnamed - driver/src/lib.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - driver/src - lib.rs (source / functions)HitTotalCoverage
Test:unnamedLines:6929123.7 %
Date:2024-04-23 03:30:56Functions:53414.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint_driver::Callbacks as rustc_driver_impl::Callbacks>::config0
<dylint_driver::Callbacks as rustc_driver_impl::Callbacks>::config::{closure#0}0
<dylint_driver::Callbacks as rustc_driver_impl::Callbacks>::config::{closure#0}::{closure#0}0
<dylint_driver::Callbacks as rustc_driver_impl::Callbacks>::config::{closure#0}::{closure#1}0
<dylint_driver::Callbacks as rustc_driver_impl::Callbacks>::config::{closure#0}::{closure#2}0
<dylint_driver::Callbacks>::new0
<dylint_driver::Callbacks>::new::{closure#0}0
<dylint_driver::Lint as core::convert::From<&rustc_lint_defs::Lint>>::from0
<dylint_driver::LoadedLibrary>::register_lints0
<dylint_driver::LoadedLibrary>::register_lints::{closure#0}0
<dylint_driver::LoadedLibrary>::register_lints::{closure#1}0
<rustc_session::session::Session as dylint_driver::ParseSess>::parse_sess0
dylint_driver::dylint_driver::<_>0
dylint_driver::dylint_driver::<_>::{closure#0}0
dylint_driver::early_error::<_>0
dylint_driver::list_enabled0
dylint_driver::list_enabled::{closure#0}0
dylint_driver::list_lints0
dylint_driver::list_lints::{closure#0}0
dylint_driver::list_lints::{closure#1}0
dylint_driver::paths0
dylint_driver::paths::{closure#0}0
dylint_driver::run::<_>0
dylint_driver::rustc_args::<&str12
dylint_driver::rustflags0
dylint_driver::rustflags::{closure#0}0
dylint_driver::rustflags::{closure#1}0
dylint_driver::session_err::<_>0
dylint_driver::sysroot0
dylint_driver::test::channel_is_nightly1
dylint_driver::test::no_rustc1
dylint_driver::test::plain_rustc1
dylint_driver::test::qualified_rustc1
dylint_driver::zero_mir_opt_level0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/driver/src/lib.rs.gcov.html b/coverage/driver/src/lib.rs.gcov.html new file mode 100644 index 000000000..a3de83340 --- /dev/null +++ b/coverage/driver/src/lib.rs.gcov.html @@ -0,0 +1,552 @@ + + + + + + + LCOV - unnamed - driver/src/lib.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - driver/src - lib.rs (source / functions)HitTotalCoverage
Test:unnamedLines:6929123.7 %
Date:2024-04-23 03:30:56Functions:53414.7 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : #![feature(rustc_private)]
+       2             : #![deny(clippy::expect_used)]
+       3             : #![deny(clippy::unwrap_used)]
+       4             : #![deny(clippy::panic)]
+       5             : #![deny(unused_extern_crates)]
+       6             : 
+       7             : extern crate rustc_driver;
+       8             : extern crate rustc_interface;
+       9             : extern crate rustc_lint;
+      10             : extern crate rustc_session;
+      11             : extern crate rustc_span;
+      12             : 
+      13             : use anyhow::{bail, ensure, Result};
+      14             : use dylint_internal::{env, parse_path_filename, rustup::is_rustc};
+      15             : use std::{
+      16             :     collections::BTreeSet,
+      17             :     ffi::{CString, OsStr},
+      18             :     path::{Path, PathBuf},
+      19             : };
+      20             : 
+      21             : pub const DYLINT_VERSION: &str = "0.1.0";
+      22             : 
+      23             : type DylintVersionFunc = unsafe fn() -> *mut std::os::raw::c_char;
+      24             : 
+      25             : type RegisterLintsFunc =
+      26             :     unsafe fn(sess: &rustc_session::Session, store: &mut rustc_lint::LintStore);
+      27             : 
+      28             : /// A library that has been loaded but whose lints have not necessarily been registered.
+      29             : struct LoadedLibrary {
+      30             :     path: PathBuf,
+      31             :     lib: libloading::Library,
+      32             : }
+      33             : 
+      34             : #[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
+      35             : struct Lint {
+      36             :     name: &'static str,
+      37             :     level: rustc_lint::Level,
+      38             :     desc: &'static str,
+      39             : }
+      40             : 
+      41             : impl From<&rustc_lint::Lint> for Lint {
+      42           0 :     fn from(lint: &rustc_lint::Lint) -> Self {
+      43           0 :         Self {
+      44           0 :             name: lint.name,
+      45           0 :             level: lint.default_level,
+      46           0 :             desc: lint.desc,
+      47           0 :         }
+      48           0 :     }
+      49             : }
+      50             : 
+      51             : impl LoadedLibrary {
+      52           0 :     fn register_lints(
+      53           0 :         &self,
+      54           0 :         sess: &rustc_session::Session,
+      55           0 :         lint_store: &mut rustc_lint::LintStore,
+      56           0 :     ) {
+      57           0 :         (|| unsafe {
+      58           0 :             if let Ok(func) = self.lib.get::<DylintVersionFunc>(b"dylint_version") {
+      59           0 :                 let dylint_version = CString::from_raw(func()).into_string()?;
+      60           0 :                 ensure!(
+      61           0 :                     dylint_version == DYLINT_VERSION,
+      62           0 :                     "`{}` has dylint version `{}`, but `{}` was expected",
+      63           0 :                     self.path.to_string_lossy(),
+      64             :                     dylint_version,
+      65             :                     DYLINT_VERSION
+      66             :                 );
+      67             :             } else {
+      68           0 :                 bail!(
+      69           0 :                     "could not find `dylint_version` in `{}`",
+      70           0 :                     self.path.to_string_lossy()
+      71           0 :                 );
+      72             :             }
+      73           0 :             if let Ok(func) = self.lib.get::<RegisterLintsFunc>(b"register_lints") {
+      74           0 :                 func(sess, lint_store);
+      75           0 :             } else {
+      76           0 :                 bail!(
+      77           0 :                     "could not find `register_lints` in `{}`",
+      78           0 :                     self.path.to_string_lossy()
+      79           0 :                 );
+      80             :             }
+      81           0 :             Ok(())
+      82           0 :         })()
+      83           0 :         .unwrap_or_else(|err| {
+      84           0 :             session_err(sess, &err);
+      85           0 :         });
+      86           0 :     }
+      87             : }
+      88             : 
+      89             : #[rustversion::before(2023-12-18)]
+      90             : fn session_err(sess: &rustc_session::Session, err: &impl ToString) -> rustc_span::ErrorGuaranteed {
+      91             :     sess.diagnostic().err(err.to_string())
+      92             : }
+      93             : 
+      94             : #[rustversion::since(2023-12-18)]
+      95           0 : fn session_err(sess: &rustc_session::Session, err: &impl ToString) -> rustc_span::ErrorGuaranteed {
+      96           0 :     sess.dcx().err(err.to_string())
+      97           0 : }
+      98             : 
+      99             : struct Callbacks {
+     100             :     loaded_libs: Vec<LoadedLibrary>,
+     101             : }
+     102             : 
+     103             : // smoelius: Use of thread local storage was added to Clippy by:
+     104             : // https://github.com/rust-lang/rust-clippy/commit/3c06e0b1ce003912f8fe0536d3a7fe22558e38cf
+     105             : // This results in a segfault after the Clippy library has been unloaded; see the following issue
+     106             : // for an explanation as to why: https://github.com/nagisa/rust_libloading/issues/5
+     107             : // The workaround I've chosen is:
+     108             : // https://github.com/nagisa/rust_libloading/issues/5#issuecomment-244195096
+     109             : impl Callbacks {
+     110             :     // smoelius: Load the libraries when `Callbacks` is created and not later (e.g., in `config`)
+     111             :     // to ensure that the libraries live long enough.
+     112           0 :     fn new(paths: Vec<PathBuf>) -> Self {
+     113           0 :         let mut loaded_libs = Vec::new();
+     114           0 :         for path in paths {
+     115           0 :             unsafe {
+     116           0 :                 // smoelius: `libloading` does not define `RTLD_NODELETE`.
+     117           0 :                 #[cfg(unix)]
+     118           0 :                 let result = libloading::os::unix::Library::open(
+     119           0 :                     Some(&path),
+     120           0 :                     libloading::os::unix::RTLD_LAZY
+     121           0 :                         | libloading::os::unix::RTLD_LOCAL
+     122           0 :                         | libc::RTLD_NODELETE,
+     123           0 :                 )
+     124           0 :                 .map(Into::into);
+     125           0 : 
+     126           0 :                 #[cfg(not(unix))]
+     127           0 :                 let result = libloading::Library::new(&path);
+     128           0 : 
+     129           0 :                 let lib = result.unwrap_or_else(|err| {
+     130           0 :                     // smoelius: rust-lang/rust#111633 changed the type of `early_error`'s `msg`
+     131           0 :                     // argument from `&str` to `impl Into<DiagnosticMessage>`.
+     132           0 :                     // smoelius: And rust-lang/rust#111748 made it that `msg` is borrowed for
+     133           0 :                     // `'static`. Since the program is about to exit, it's probably fine to leak the
+     134           0 :                     // string.
+     135           0 :                     let msg = format!(
+     136           0 :                         "could not load library `{}`: {}",
+     137           0 :                         path.to_string_lossy(),
+     138           0 :                         err
+     139           0 :                     );
+     140           0 :                     early_error(msg);
+     141           0 :                 });
+     142           0 : 
+     143           0 :                 loaded_libs.push(LoadedLibrary { path, lib });
+     144           0 :             }
+     145             :         }
+     146           0 :         Self { loaded_libs }
+     147           0 :     }
+     148             : }
+     149             : 
+     150             : #[rustversion::before(2023-06-28)]
+     151             : fn early_error(msg: String) -> ! {
+     152             :     rustc_session::early_error(
+     153             :         rustc_session::config::ErrorOutputType::default(),
+     154             :         Box::leak(msg.into_boxed_str()) as &str,
+     155             :     )
+     156             : }
+     157             : 
+     158             : #[rustversion::since(2023-06-28)]
+     159             : extern crate rustc_errors;
+     160             : 
+     161             : #[rustversion::all(since(2023-06-28), before(2023-12-18))]
+     162             : fn early_error(msg: impl Into<rustc_errors::DiagnosticMessage>) -> ! {
+     163             :     let handler =
+     164             :         rustc_session::EarlyErrorHandler::new(rustc_session::config::ErrorOutputType::default());
+     165             :     handler.early_error(msg)
+     166             : }
+     167             : 
+     168             : #[rustversion::all(since(2023-12-18), before(2023-12-23))]
+     169             : fn early_error(msg: impl Into<rustc_errors::DiagnosticMessage>) -> ! {
+     170             :     let handler =
+     171             :         rustc_session::EarlyDiagCtxt::new(rustc_session::config::ErrorOutputType::default());
+     172             :     handler.early_error(msg)
+     173             : }
+     174             : 
+     175             : #[rustversion::all(since(2023-12-23), before(2024-03-05))]
+     176             : fn early_error(msg: impl Into<rustc_errors::DiagnosticMessage>) -> ! {
+     177             :     let handler =
+     178             :         rustc_session::EarlyDiagCtxt::new(rustc_session::config::ErrorOutputType::default());
+     179             :     handler.early_fatal(msg)
+     180             : }
+     181             : 
+     182             : #[rustversion::since(2024-03-05)]
+     183           0 : fn early_error(msg: impl Into<rustc_errors::DiagMessage>) -> ! {
+     184           0 :     let handler =
+     185           0 :         rustc_session::EarlyDiagCtxt::new(rustc_session::config::ErrorOutputType::default());
+     186           0 :     handler.early_fatal(msg)
+     187             : }
+     188             : 
+     189             : trait ParseSess {
+     190             :     fn parse_sess(&self) -> &rustc_session::parse::ParseSess;
+     191             : }
+     192             : 
+     193             : impl ParseSess for rustc_session::Session {
+     194             :     #[rustversion::before(2024-03-05)]
+     195             :     fn parse_sess(&self) -> &rustc_session::parse::ParseSess {
+     196             :         &self.parse_sess
+     197             :     }
+     198             : 
+     199             :     #[rustversion::since(2024-03-05)]
+     200           0 :     fn parse_sess(&self) -> &rustc_session::parse::ParseSess {
+     201           0 :         &self.psess
+     202           0 :     }
+     203             : }
+     204             : 
+     205             : #[rustversion::before(2022-07-14)]
+     206             : fn zero_mir_opt_level(config: &mut rustc_interface::Config) {
+     207             :     trait Zeroable {
+     208             :         fn zero(&mut self);
+     209             :     }
+     210             : 
+     211             :     impl Zeroable for usize {
+     212             :         fn zero(&mut self) {
+     213             :             *self = 0;
+     214             :         }
+     215             :     }
+     216             : 
+     217             :     impl Zeroable for Option<usize> {
+     218             :         fn zero(&mut self) {
+     219             :             *self = Some(0);
+     220             :         }
+     221             :     }
+     222             : 
+     223             :     // smoelius: `Zeroable` is a hack to make the next line compile for different Rust versions:
+     224             :     // https://github.com/rust-lang/rust-clippy/commit/0941fc0bb5d655cdd0816f862af8cfe70556dad6
+     225             :     config.opts.debugging_opts.mir_opt_level.zero();
+     226             : }
+     227             : 
+     228             : // smoelius: Relevant PR and merge commit:
+     229             : // - https://github.com/rust-lang/rust/pull/98975
+     230             : // - https://github.com/rust-lang/rust/commit/0ed9c64c3e63acac9bd77abce62501696c390450
+     231             : #[rustversion::since(2022-07-14)]
+     232           0 : fn zero_mir_opt_level(config: &mut rustc_interface::Config) {
+     233           0 :     config.opts.unstable_opts.mir_opt_level = Some(0);
+     234           0 : }
+     235             : 
+     236             : impl rustc_driver::Callbacks for Callbacks {
+     237           0 :     fn config(&mut self, config: &mut rustc_interface::Config) {
+     238           0 :         let previous = config.register_lints.take();
+     239           0 :         let loaded_libs = self.loaded_libs.split_off(0);
+     240           0 :         config.register_lints = Some(Box::new(move |sess, lint_store| {
+     241           0 :             if let Some(previous) = &previous {
+     242           0 :                 previous(sess, lint_store);
+     243           0 :             }
+     244             : 
+     245           0 :             let dylint_libs = env::var(env::DYLINT_LIBS).ok();
+     246           0 :             let dylint_metadata = env::var(env::DYLINT_METADATA).ok();
+     247           0 :             let dylint_no_deps = env::var(env::DYLINT_NO_DEPS).ok();
+     248           0 :             let dylint_no_deps_enabled =
+     249           0 :                 dylint_no_deps.as_ref().map_or(false, |value| value != "0");
+     250           0 :             let cargo_primary_package_is_set = env::var(env::CARGO_PRIMARY_PACKAGE).is_ok();
+     251           0 : 
+     252           0 :             sess.parse_sess().env_depinfo.lock().insert((
+     253           0 :                 rustc_span::Symbol::intern(env::DYLINT_LIBS),
+     254           0 :                 dylint_libs.as_deref().map(rustc_span::Symbol::intern),
+     255           0 :             ));
+     256           0 :             sess.parse_sess().env_depinfo.lock().insert((
+     257           0 :                 rustc_span::Symbol::intern(env::DYLINT_METADATA),
+     258           0 :                 dylint_metadata.as_deref().map(rustc_span::Symbol::intern),
+     259           0 :             ));
+     260           0 :             sess.parse_sess().env_depinfo.lock().insert((
+     261           0 :                 rustc_span::Symbol::intern(env::DYLINT_NO_DEPS),
+     262           0 :                 dylint_no_deps.as_deref().map(rustc_span::Symbol::intern),
+     263           0 :             ));
+     264           0 : 
+     265           0 :             if dylint_no_deps_enabled && !cargo_primary_package_is_set {
+     266           0 :                 return;
+     267           0 :             }
+     268           0 : 
+     269           0 :             let mut before = BTreeSet::<Lint>::new();
+     270           0 :             if list_enabled() {
+     271           0 :                 lint_store.get_lints().iter().for_each(|&lint| {
+     272           0 :                     before.insert(lint.into());
+     273           0 :                 });
+     274           0 :             }
+     275           0 :             for loaded_lib in &loaded_libs {
+     276           0 :                 if let Some(path) = loaded_lib.path.to_str() {
+     277           0 :                     sess.parse_sess()
+     278           0 :                         .file_depinfo
+     279           0 :                         .lock()
+     280           0 :                         .insert(rustc_span::Symbol::intern(path));
+     281           0 :                 }
+     282           0 :                 loaded_lib.register_lints(sess, lint_store);
+     283             :             }
+     284           0 :             if list_enabled() {
+     285           0 :                 let mut after = BTreeSet::<Lint>::new();
+     286           0 :                 lint_store.get_lints().iter().for_each(|&lint| {
+     287           0 :                     after.insert(lint.into());
+     288           0 :                 });
+     289           0 :                 list_lints(&before, &after);
+     290           0 :                 std::process::exit(0);
+     291           0 :             }
+     292           0 :         }));
+     293           0 : 
+     294           0 :         // smoelius: Choose to be compatible with Clippy:
+     295           0 :         // https://github.com/rust-lang/rust-clippy/commit/7bae5bd828e98af9d245b77118c075a7f1a036b9
+     296           0 :         zero_mir_opt_level(config);
+     297           0 :     }
+     298             : }
+     299             : 
+     300             : #[must_use]
+     301           0 : fn list_enabled() -> bool {
+     302           0 :     env::var(env::DYLINT_LIST).map_or(false, |value| value != "0")
+     303           0 : }
+     304             : 
+     305           0 : fn list_lints(before: &BTreeSet<Lint>, after: &BTreeSet<Lint>) {
+     306           0 :     let difference: Vec<Lint> = after.difference(before).cloned().collect();
+     307           0 : 
+     308           0 :     let name_width = difference
+     309           0 :         .iter()
+     310           0 :         .map(|lint| lint.name.len())
+     311           0 :         .max()
+     312           0 :         .unwrap_or_default();
+     313           0 : 
+     314           0 :     let level_width = difference
+     315           0 :         .iter()
+     316           0 :         .map(|lint| lint.level.as_str().len())
+     317           0 :         .max()
+     318           0 :         .unwrap_or_default();
+     319             : 
+     320           0 :     for Lint { name, level, desc } in difference {
+     321           0 :         println!(
+     322           0 :             "    {:<name_width$}    {:<level_width$}    {}",
+     323           0 :             name.to_lowercase(),
+     324           0 :             level.as_str(),
+     325           0 :             desc,
+     326           0 :             name_width = name_width,
+     327           0 :             level_width = level_width
+     328           0 :         );
+     329           0 :     }
+     330           0 : }
+     331             : 
+     332           0 : pub fn dylint_driver<T: AsRef<OsStr>>(args: &[T]) -> Result<()> {
+     333           0 :     if args.len() <= 1 || args.iter().any(|arg| arg.as_ref() == "-V") {
+     334           0 :         println!("{} {}", env!("RUSTUP_TOOLCHAIN"), env!("CARGO_PKG_VERSION"));
+     335           0 :         return Ok(());
+     336           0 :     }
+     337           0 : 
+     338           0 :     run(&args[1..])
+     339           0 : }
+     340             : 
+     341           0 : pub fn run<T: AsRef<OsStr>>(args: &[T]) -> Result<()> {
+     342           0 :     let sysroot = sysroot().ok();
+     343           0 :     let rustflags = rustflags();
+     344           0 :     let paths = paths();
+     345             : 
+     346           0 :     let rustc_args = rustc_args(args, &sysroot, &rustflags, &paths)?;
+     347             : 
+     348           0 :     let mut callbacks = Callbacks::new(paths);
+     349           0 : 
+     350           0 :     // smoelius: I am not sure that this should be here. `RUST_LOG=debug cargo test` fails because
+     351           0 :     // of the log messages.
+     352           0 :     log::debug!("{:?}", rustc_args);
+     353             : 
+     354           0 :     rustc_driver::RunCompiler::new(&rustc_args, &mut callbacks)
+     355           0 :         .run()
+     356           0 :         .map_err(|_| std::process::exit(1))
+     357           0 : }
+     358             : 
+     359           0 : fn sysroot() -> Result<PathBuf> {
+     360           0 :     let rustup_home = env::var(env::RUSTUP_HOME)?;
+     361           0 :     let rustup_toolchain = env::var(env::RUSTUP_TOOLCHAIN)?;
+     362           0 :     Ok(PathBuf::from(rustup_home)
+     363           0 :         .join("toolchains")
+     364           0 :         .join(rustup_toolchain))
+     365           0 : }
+     366             : 
+     367           0 : fn rustflags() -> Vec<String> {
+     368           0 :     env::var(env::DYLINT_RUSTFLAGS).map_or_else(
+     369           0 :         |_| Vec::new(),
+     370           0 :         |rustflags| rustflags.split_whitespace().map(String::from).collect(),
+     371           0 :     )
+     372           0 : }
+     373             : 
+     374           0 : fn paths() -> Vec<PathBuf> {
+     375           0 :     (|| -> Result<_> {
+     376           0 :         let dylint_libs = env::var(env::DYLINT_LIBS)?;
+     377           0 :         serde_json::from_str(&dylint_libs).map_err(Into::into)
+     378           0 :     })()
+     379           0 :     .unwrap_or_default()
+     380           0 : }
+     381             : 
+     382           3 : fn rustc_args<T: AsRef<OsStr>, U: AsRef<str>, V: AsRef<Path>>(
+     383           3 :     args: &[T],
+     384           3 :     sysroot: &Option<PathBuf>,
+     385           3 :     rustflags: &[U],
+     386           3 :     paths: &[V],
+     387           3 : ) -> Result<Vec<String>> {
+     388           3 :     let mut args = args.iter().peekable();
+     389           3 :     let mut rustc_args = Vec::new();
+     390           3 : 
+     391           3 :     let first_arg = args.peek();
+     392           3 :     if first_arg.map_or(true, |arg| !is_rustc(arg)) {
+     393           1 :         rustc_args.push("rustc".to_owned());
+     394           2 :     }
+     395           3 :     if let Some(arg) = first_arg {
+     396           3 :         if is_rustc(arg) {
+     397           2 :             rustc_args.push(arg.as_ref().to_string_lossy().to_string());
+     398           2 :             let _ = args.next();
+     399           2 :         }
+     400           0 :     }
+     401           3 :     if let Some(sysroot) = sysroot {
+     402           0 :         rustc_args.extend([
+     403           0 :             "--sysroot".to_owned(),
+     404           0 :             sysroot.to_string_lossy().to_string(),
+     405           0 :         ]);
+     406           3 :     }
+     407           3 :     for path in paths {
+     408           0 :         if let Some((name, _)) = parse_path_filename(path.as_ref()) {
+     409           0 :             rustc_args.push(format!(r#"--cfg=dylint_lib="{name}""#));
+     410           0 :         } else {
+     411           0 :             bail!("could not parse `{}`", path.as_ref().to_string_lossy());
+     412             :         }
+     413             :     }
+     414           6 :     rustc_args.extend(args.map(|s| s.as_ref().to_string_lossy().to_string()));
+     415           3 :     rustc_args.extend(
+     416           3 :         rustflags
+     417           3 :             .iter()
+     418           3 :             .map(|rustflag| rustflag.as_ref().to_owned()),
+     419           3 :     );
+     420           3 : 
+     421           3 :     Ok(rustc_args)
+     422           3 : }
+     423             : 
+     424             : #[allow(clippy::unwrap_used)]
+     425             : #[cfg(test)]
+     426             : mod test {
+     427             :     use super::*;
+     428             :     use rustc_version::{version_meta, Channel};
+     429             : 
+     430             :     #[test]
+     431           1 :     fn channel_is_nightly() {
+     432           1 :         assert!(matches!(version_meta().unwrap().channel, Channel::Nightly));
+     433           1 :     }
+     434             : 
+     435             :     #[test]
+     436           1 :     fn no_rustc() {
+     437           1 :         assert_eq!(
+     438           1 :             rustc_args(
+     439           1 :                 &["--crate-name", "name"],
+     440           1 :                 &None,
+     441           1 :                 &[] as &[&str],
+     442           1 :                 &[] as &[&Path]
+     443           1 :             )
+     444           1 :             .unwrap(),
+     445           1 :             vec!["rustc", "--crate-name", "name"]
+     446           1 :         );
+     447           1 :     }
+     448             : 
+     449             :     #[test]
+     450           1 :     fn plain_rustc() {
+     451           1 :         assert_eq!(
+     452           1 :             rustc_args(
+     453           1 :                 &["rustc", "--crate-name", "name"],
+     454           1 :                 &None,
+     455           1 :                 &[] as &[&str],
+     456           1 :                 &[] as &[&Path]
+     457           1 :             )
+     458           1 :             .unwrap(),
+     459           1 :             vec!["rustc", "--crate-name", "name"]
+     460           1 :         );
+     461           1 :     }
+     462             : 
+     463             :     #[test]
+     464           1 :     fn qualified_rustc() {
+     465           1 :         assert_eq!(
+     466           1 :             rustc_args(
+     467           1 :                 &["/bin/rustc", "--crate-name", "name"],
+     468           1 :                 &None,
+     469           1 :                 &[] as &[&str],
+     470           1 :                 &[] as &[&Path]
+     471           1 :             )
+     472           1 :             .unwrap(),
+     473           1 :             vec!["/bin/rustc", "--crate-name", "name"]
+     474           1 :         );
+     475           1 :     }
+     476             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint-link/src/index-sort-f.html b/coverage/dylint-link/src/index-sort-f.html new file mode 100644 index 000000000..a2e5dece3 --- /dev/null +++ b/coverage/dylint-link/src/index-sort-f.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - dylint-link/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint-link/srcHitTotalCoverage
Test:unnamedLines:8418046.7 %
Date:2024-04-23 03:30:56Functions:52420.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
main.rs +
46.7%46.7%
+
46.7 %84 / 18020.8 %5 / 24
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint-link/src/index-sort-l.html b/coverage/dylint-link/src/index-sort-l.html new file mode 100644 index 000000000..6a36f9cd5 --- /dev/null +++ b/coverage/dylint-link/src/index-sort-l.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - dylint-link/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint-link/srcHitTotalCoverage
Test:unnamedLines:8418046.7 %
Date:2024-04-23 03:30:56Functions:52420.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
main.rs +
46.7%46.7%
+
46.7 %84 / 18020.8 %5 / 24
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint-link/src/index.html b/coverage/dylint-link/src/index.html new file mode 100644 index 000000000..14a1ffdc3 --- /dev/null +++ b/coverage/dylint-link/src/index.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - dylint-link/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint-link/srcHitTotalCoverage
Test:unnamedLines:8418046.7 %
Date:2024-04-23 03:30:56Functions:52420.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
main.rs +
46.7%46.7%
+
46.7 %84 / 18020.8 %5 / 24
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint-link/src/main.rs.func-sort-c.html b/coverage/dylint-link/src/main.rs.func-sort-c.html new file mode 100644 index 000000000..efa403bae --- /dev/null +++ b/coverage/dylint-link/src/main.rs.func-sort-c.html @@ -0,0 +1,168 @@ + + + + + + + LCOV - unnamed - dylint-link/src/main.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint-link/src - main.rs (source / functions)HitTotalCoverage
Test:unnamedLines:8418046.7 %
Date:2024-04-23 03:30:56Functions:52420.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_link::copy_library0
dylint_link::copy_library::{closure#0}0
dylint_link::copy_library::{closure#1}0
dylint_link::default_linker0
dylint_link::linker0
dylint_link::linker::{closure#0}0
dylint_link::linker::{closure#1}0
dylint_link::linker::{closure#2}0
dylint_link::linker::{closure#3}0
dylint_link::linker::{closure#4}0
dylint_link::linker::{closure#5}0
dylint_link::linker::{closure#6}0
dylint_link::main0
dylint_link::output_path::<_>0
dylint_link::parse_path_plain_filename0
dylint_link::parse_toolchain0
dylint_link::parse_toolchain::{closure#0}0
dylint_link::parse_toolchain::{closure#1}0
dylint_link::strip_deps0
dylint_link::test::architectures_are_current1
dylint_link::test::architectures_are_sorted1
dylint_link::test::global_config1
dylint_link::test::architectures_are_current::{closure#0}231
dylint_link::test::architectures_are_current::{closure#0}::{closure#0}231
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint-link/src/main.rs.func.html b/coverage/dylint-link/src/main.rs.func.html new file mode 100644 index 000000000..f2827e409 --- /dev/null +++ b/coverage/dylint-link/src/main.rs.func.html @@ -0,0 +1,168 @@ + + + + + + + LCOV - unnamed - dylint-link/src/main.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint-link/src - main.rs (source / functions)HitTotalCoverage
Test:unnamedLines:8418046.7 %
Date:2024-04-23 03:30:56Functions:52420.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_link::copy_library0
dylint_link::copy_library::{closure#0}0
dylint_link::copy_library::{closure#1}0
dylint_link::default_linker0
dylint_link::linker0
dylint_link::linker::{closure#0}0
dylint_link::linker::{closure#1}0
dylint_link::linker::{closure#2}0
dylint_link::linker::{closure#3}0
dylint_link::linker::{closure#4}0
dylint_link::linker::{closure#5}0
dylint_link::linker::{closure#6}0
dylint_link::main0
dylint_link::output_path::<_>0
dylint_link::parse_path_plain_filename0
dylint_link::parse_toolchain0
dylint_link::parse_toolchain::{closure#0}0
dylint_link::parse_toolchain::{closure#1}0
dylint_link::strip_deps0
dylint_link::test::architectures_are_current1
dylint_link::test::architectures_are_current::{closure#0}231
dylint_link::test::architectures_are_current::{closure#0}::{closure#0}231
dylint_link::test::architectures_are_sorted1
dylint_link::test::global_config1
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint-link/src/main.rs.gcov.html b/coverage/dylint-link/src/main.rs.gcov.html new file mode 100644 index 000000000..fc6468cb4 --- /dev/null +++ b/coverage/dylint-link/src/main.rs.gcov.html @@ -0,0 +1,457 @@ + + + + + + + LCOV - unnamed - dylint-link/src/main.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint-link/src - main.rs (source / functions)HitTotalCoverage
Test:unnamedLines:8418046.7 %
Date:2024-04-23 03:30:56Functions:52420.8 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : #![deny(clippy::expect_used)]
+       2             : #![deny(clippy::unwrap_used)]
+       3             : #![deny(clippy::panic)]
+       4             : 
+       5             : #[cfg(target_os = "windows")]
+       6             : use anyhow::ensure;
+       7             : use anyhow::{anyhow, Context, Result};
+       8             : use dylint_internal::{cargo::cargo_home, env, library_filename, CommandExt};
+       9             : use if_chain::if_chain;
+      10             : use std::{
+      11             :     env::{args, consts},
+      12             :     ffi::OsStr,
+      13             :     fs::{copy, read_to_string},
+      14             :     path::{Path, PathBuf},
+      15             :     process::Command,
+      16             : };
+      17             : #[cfg(target_os = "windows")]
+      18             : use std::{fs::File, io::Read};
+      19             : use toml_edit::{DocumentMut, Item};
+      20             : 
+      21           0 : fn main() -> Result<()> {
+      22           0 :     env_logger::init();
+      23             : 
+      24           0 :     let linker = linker()?;
+      25           0 :     let args: Vec<String> = args().collect();
+      26           0 :     Command::new(linker).args(&args[1..]).success()?;
+      27             : 
+      28           0 :     if let Some(path) = output_path(args.iter())? {
+      29           0 :         copy_library(&path)?;
+      30           0 :     }
+      31             : 
+      32           0 :     Ok(())
+      33           0 : }
+      34             : 
+      35           0 : fn linker() -> Result<PathBuf> {
+      36           0 :     let rustup_toolchain = env::var(env::RUSTUP_TOOLCHAIN)?;
+      37           0 :     let target = parse_toolchain(&rustup_toolchain)
+      38           0 :         .map_or_else(|| env!("TARGET").to_owned(), |(_, target)| target);
+      39           0 :     let cargo_home = cargo_home().with_context(|| "Could not determine `CARGO_HOME`")?;
+      40           0 :     let config_toml = cargo_home.join("config.toml");
+      41           0 :     if config_toml.is_file() {
+      42           0 :         let contents = read_to_string(&config_toml).with_context(|| {
+      43           0 :             format!(
+      44           0 :                 "`read_to_string` failed for `{}`",
+      45           0 :                 config_toml.to_string_lossy()
+      46           0 :             )
+      47           0 :         })?;
+      48           0 :         let document = contents.parse::<DocumentMut>()?;
+      49           0 :         document
+      50           0 :             .as_table()
+      51           0 :             .get("target")
+      52           0 :             .and_then(Item::as_table)
+      53           0 :             .and_then(|table| table.get(&target))
+      54           0 :             .and_then(Item::as_table)
+      55           0 :             .and_then(|table| table.get("linker"))
+      56           0 :             .and_then(Item::as_str)
+      57           0 :             .map_or_else(default_linker, |s| Ok(PathBuf::from(s)))
+      58             :     } else {
+      59           0 :         default_linker()
+      60             :     }
+      61           0 : }
+      62             : 
+      63             : #[cfg(target_os = "windows")]
+      64             : fn default_linker() -> Result<PathBuf> {
+      65             :     let rustup_toolchain = env::var(env::RUSTUP_TOOLCHAIN)?;
+      66             :     if rustup_toolchain.split('-').last() == Some("msvc") {
+      67             :         // MinerSebas: Removes the Release Information: "nightly-2021-04-08-x86_64-pc-windows-msvc"
+      68             :         // -> "x86_64-pc-windows-msvc"
+      69             :         // smoelius: The approach has changed slightly.
+      70             :         if let Some(tool) = parse_toolchain(&rustup_toolchain)
+      71             :             .and_then(|(_, target)| cc::windows_registry::find_tool(&target, "link.exe"))
+      72             :         {
+      73             :             Ok(tool.path().into())
+      74             :         } else {
+      75             :             Err(anyhow!("Could not find the MSVC Linker"))
+      76             :         }
+      77             :     } else {
+      78             :         Err(anyhow!("Only the MSVC toolchain is supported on Windows"))
+      79             :     }
+      80             : }
+      81             : 
+      82             : #[cfg(not(target_os = "windows"))]
+      83             : #[allow(clippy::unnecessary_wraps)]
+      84           0 : fn default_linker() -> Result<PathBuf> {
+      85           0 :     Ok(PathBuf::from("cc"))
+      86           0 : }
+      87             : 
+      88             : #[cfg(target_os = "windows")]
+      89             : fn output_path<'a, I>(iter: I) -> Result<Option<PathBuf>>
+      90             : where
+      91             :     I: Iterator<Item = &'a String>,
+      92             : {
+      93             :     for arg in iter {
+      94             :         if let Some(path) = arg.strip_prefix("/OUT:") {
+      95             :             return Ok(Some(path.into()));
+      96             :         }
+      97             :         if let Some(path) = arg.strip_prefix('@') {
+      98             :             return extract_out_path_from_linker_response_file(path);
+      99             :         }
+     100             :     }
+     101             : 
+     102             :     Ok(None)
+     103             : }
+     104             : 
+     105             : #[cfg(not(target_os = "windows"))]
+     106             : #[allow(clippy::unnecessary_wraps)]
+     107           0 : fn output_path<'a, I>(mut iter: I) -> Result<Option<PathBuf>>
+     108           0 : where
+     109           0 :     I: Iterator<Item = &'a String>,
+     110           0 : {
+     111           0 :     while let Some(arg) = iter.next() {
+     112           0 :         if arg == "-o" {
+     113           0 :             if let Some(path) = iter.next() {
+     114           0 :                 return Ok(Some(path.into()));
+     115           0 :             }
+     116           0 :         }
+     117             :     }
+     118             : 
+     119           0 :     Ok(None)
+     120           0 : }
+     121             : 
+     122             : #[cfg(target_os = "windows")]
+     123             : fn extract_out_path_from_linker_response_file(path: impl AsRef<Path>) -> Result<Option<PathBuf>> {
+     124             :     // MinerSebas: On Windows the cmd line has a Limit of 8191 Characters.
+     125             :     // If your command would exceed this you can instead use a Linker Response File to set
+     126             :     // arguments. (https://docs.microsoft.com/en-us/cpp/build/reference/at-specify-a-linker-response-file?view=msvc-160)
+     127             : 
+     128             :     // MinerSebas: Read the Linker Response File
+     129             :     let mut buf: Vec<u8> = Vec::new();
+     130             :     File::open(path)?.read_to_end(&mut buf)?;
+     131             : 
+     132             :     // MinerSebas: Convert the File from UTF-16 to a Rust UTF-8 String
+     133             :     // (Only necessary for MSVC, the GNU Linker uses UTF-8 isntead.)
+     134             :     // Based on: https://stackoverflow.com/a/57172592
+     135             :     let file: Vec<u16> = buf
+     136             :         .chunks_exact(2)
+     137             :         .into_iter()
+     138             :         .map(|a| u16::from_ne_bytes([a[0], a[1]]))
+     139             :         .collect();
+     140             :     let file = String::from_utf16_lossy(file.as_slice());
+     141             : 
+     142             :     let paths: Vec<_> = file
+     143             :         .lines()
+     144             :         .flat_map(|line| line.trim().trim_matches('"').strip_prefix("/OUT:"))
+     145             :         .collect();
+     146             : 
+     147             :     ensure!(paths.len() <= 1, "Found multiple output paths");
+     148             : 
+     149             :     // smoelius: Do not raise an error if no output path is found.
+     150             :     Ok(paths.last().map(Into::into))
+     151             : }
+     152             : 
+     153           0 : fn copy_library(path: &Path) -> Result<()> {
+     154           0 :     if_chain! {
+     155           0 :         if let Some(lib_name) = parse_path_plain_filename(path);
+     156           0 :         let cargo_pkg_name = env::var(env::CARGO_PKG_NAME)?;
+     157           0 :         if lib_name == cargo_pkg_name.replace('-', "_");
+     158             :         then {
+     159           0 :             let rustup_toolchain = env::var(env::RUSTUP_TOOLCHAIN)?;
+     160           0 :             let filename_with_toolchain = library_filename(&lib_name, &rustup_toolchain);
+     161           0 :             let parent = path
+     162           0 :                 .parent()
+     163           0 :                 .ok_or_else(|| anyhow!("Could not get parent directory"))?;
+     164           0 :             let path_with_toolchain = strip_deps(parent).join(filename_with_toolchain);
+     165           0 :             copy(path, &path_with_toolchain).with_context(|| {
+     166           0 :                 format!(
+     167           0 :                     "Could not copy `{}` to `{}`",
+     168           0 :                     path.to_string_lossy(),
+     169           0 :                     path_with_toolchain.to_string_lossy()
+     170           0 :                 )
+     171           0 :             })?;
+     172             :         }
+     173             :     }
+     174             : 
+     175           0 :     Ok(())
+     176           0 : }
+     177             : 
+     178             : // smoelius: I do not know what the right/best way to parse a toolchain is. `parse_toolchain` does
+     179             : // so by looking for the architecture.
+     180           0 : fn parse_toolchain(toolchain: &str) -> Option<(String, String)> {
+     181           0 :     let split_toolchain: Vec<_> = toolchain.split('-').collect();
+     182           0 :     split_toolchain
+     183           0 :         .iter()
+     184           0 :         .rposition(|s| ARCHITECTURES.binary_search(s).is_ok())
+     185           0 :         .map(|i| {
+     186           0 :             (
+     187           0 :                 split_toolchain[..i].join("-"),
+     188           0 :                 split_toolchain[i..].join("-"),
+     189           0 :             )
+     190           0 :         })
+     191           0 : }
+     192             : 
+     193           0 : fn parse_path_plain_filename(path: &Path) -> Option<String> {
+     194           0 :     let filename = path.file_name()?;
+     195           0 :     let s = filename.to_string_lossy();
+     196           0 :     let file_stem = s.strip_suffix(consts::DLL_SUFFIX)?;
+     197           0 :     let lib_name = file_stem.strip_prefix(consts::DLL_PREFIX)?;
+     198           0 :     Some(lib_name.to_owned())
+     199           0 : }
+     200             : 
+     201           0 : fn strip_deps(path: &Path) -> PathBuf {
+     202           0 :     if path.file_name() == Some(OsStr::new("deps")) {
+     203           0 :         path.parent()
+     204             :     } else {
+     205           0 :         None
+     206             :     }
+     207           0 :     .unwrap_or(path)
+     208           0 :     .to_path_buf()
+     209           0 : }
+     210             : 
+     211             : // smoelius: `ARCHITECTURES` is based on: https://doc.rust-lang.org/rustc/platform-support.html
+     212             : const ARCHITECTURES: &[&str] = &[
+     213             :     "aarch64",
+     214             :     "aarch64_be",
+     215             :     "arm",
+     216             :     "arm64_32",
+     217             :     "arm64e",
+     218             :     "armeb",
+     219             :     "armebv7r",
+     220             :     "armv4t",
+     221             :     "armv5te",
+     222             :     "armv6",
+     223             :     "armv6k",
+     224             :     "armv7",
+     225             :     "armv7a",
+     226             :     "armv7k",
+     227             :     "armv7r",
+     228             :     "armv7s",
+     229             :     "avr",
+     230             :     "bpfeb",
+     231             :     "bpfel",
+     232             :     "csky",
+     233             :     "hexagon",
+     234             :     "i386",
+     235             :     "i586",
+     236             :     "i686",
+     237             :     "loongarch64",
+     238             :     "m68k",
+     239             :     "mips",
+     240             :     "mips64",
+     241             :     "mips64el",
+     242             :     "mipsel",
+     243             :     "mipsisa32r6",
+     244             :     "mipsisa32r6el",
+     245             :     "mipsisa64r6",
+     246             :     "mipsisa64r6el",
+     247             :     "msp430",
+     248             :     "nvptx64",
+     249             :     "powerpc",
+     250             :     "powerpc64",
+     251             :     "powerpc64le",
+     252             :     "riscv32gc",
+     253             :     "riscv32i",
+     254             :     "riscv32im",
+     255             :     "riscv32imac",
+     256             :     "riscv32imafc",
+     257             :     "riscv32imc",
+     258             :     "riscv64",
+     259             :     "riscv64gc",
+     260             :     "riscv64imac",
+     261             :     "s390x",
+     262             :     "sparc",
+     263             :     "sparc64",
+     264             :     "sparcv9",
+     265             :     "thumbv4t",
+     266             :     "thumbv5te",
+     267             :     "thumbv6m",
+     268             :     "thumbv7a",
+     269             :     "thumbv7em",
+     270             :     "thumbv7m",
+     271             :     "thumbv7neon",
+     272             :     "thumbv8m.base",
+     273             :     "thumbv8m.main",
+     274             :     "wasm32",
+     275             :     "wasm64",
+     276             :     "x86_64",
+     277             :     "x86_64h",
+     278             : ];
+     279             : 
+     280             : #[allow(clippy::unwrap_used)]
+     281             : #[cfg(test)]
+     282             : mod test {
+     283             :     use super::{env, ARCHITECTURES};
+     284             :     use assert_cmd::prelude::*;
+     285             :     use dylint_internal::{packaging::isolate, CommandExt};
+     286             :     use predicates::prelude::*;
+     287             :     use std::fs::{create_dir, write};
+     288             :     use tempfile::{tempdir, tempdir_in};
+     289             : 
+     290             :     #[test]
+     291           1 :     fn architectures_are_current() {
+     292           1 :         let output = std::process::Command::new("rustc")
+     293           1 :             .args(["--print", "target-list"])
+     294           1 :             .unwrap();
+     295           1 :         let mut architectures = std::str::from_utf8(&output.stdout)
+     296           1 :             .unwrap()
+     297           1 :             .lines()
+     298         231 :             .filter_map(|line| line.split_once('-').map(|(architecture, _)| architecture))
+     299           1 :             .collect::<Vec<_>>();
+     300           1 :         architectures.sort_unstable();
+     301           1 :         architectures.dedup();
+     302           1 :         assert_eq!(ARCHITECTURES, architectures);
+     303           1 :     }
+     304             : 
+     305             :     #[test]
+     306           1 :     fn architectures_are_sorted() {
+     307           1 :         let mut architectures = ARCHITECTURES.to_vec();
+     308           1 :         architectures.sort_unstable();
+     309           1 :         architectures.dedup();
+     310           1 :         assert_eq!(ARCHITECTURES, architectures);
+     311           1 :     }
+     312             : 
+     313             :     #[cfg_attr(not(all(target_arch = "x86_64", target_os = "linux")), ignore)]
+     314             :     #[cfg_attr(dylint_lib = "general", allow(non_thread_safe_call_in_test))]
+     315             :     #[test]
+     316           1 :     fn global_config() {
+     317           1 :         let cargo_home = tempdir().unwrap();
+     318           1 :         let package = tempdir_in(".").unwrap();
+     319           1 : 
+     320           1 :         dylint_internal::cargo::build("dylint-link")
+     321           1 :             .build()
+     322           1 :             .current_dir(env!("CARGO_MANIFEST_DIR"))
+     323           1 :             .success()
+     324           1 :             .unwrap();
+     325           1 : 
+     326           1 :         dylint_internal::cargo::init("package `global_config_test`")
+     327           1 :             .build()
+     328           1 :             .current_dir(&package)
+     329           1 :             .args(["--name", "global_config_test"])
+     330           1 :             .success()
+     331           1 :             .unwrap();
+     332           1 : 
+     333           1 :         isolate(package.path()).unwrap();
+     334           1 : 
+     335           1 :         let package_cargo = package.path().join(".cargo");
+     336           1 :         create_dir(&package_cargo).unwrap();
+     337           1 :         write(
+     338           1 :             package_cargo.join("config.toml"),
+     339           1 :             r#"
+     340           1 : [target.x86_64-unknown-linux-gnu]
+     341           1 : linker = "../../target/debug/dylint-link"
+     342           1 : "#,
+     343           1 :         )
+     344           1 :         .unwrap();
+     345           1 : 
+     346           1 :         std::process::Command::new("cargo")
+     347           1 :             .current_dir(&package)
+     348           1 :             .arg("build")
+     349           1 :             .assert()
+     350           1 :             .success();
+     351           1 : 
+     352           1 :         write(
+     353           1 :             cargo_home.path().join("config.toml"),
+     354           1 :             r#"
+     355           1 : [target.x86_64-unknown-linux-gnu]
+     356           1 : linker = "false"
+     357           1 : "#,
+     358           1 :         )
+     359           1 :         .unwrap();
+     360           1 : 
+     361           1 :         std::process::Command::new("cargo")
+     362           1 :             .current_dir(&package)
+     363           1 :             .arg("clean")
+     364           1 :             .assert()
+     365           1 :             .success();
+     366           1 : 
+     367           1 :         std::process::Command::new("cargo")
+     368           1 :             .env(env::CARGO_HOME, cargo_home.path())
+     369           1 :             .env(env::CARGO_TERM_COLOR, "never")
+     370           1 :             .current_dir(&package)
+     371           1 :             .arg("build")
+     372           1 :             .assert()
+     373           1 :             .failure()
+     374           1 :             .stderr(
+     375           1 :                 predicate::str::is_match(
+     376           1 :                     "error: linking with `[^`]*/target/debug/dylint-link` failed",
+     377           1 :                 )
+     378           1 :                 .unwrap(),
+     379           1 :             );
+     380           1 :     }
+     381             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/driver_builder.rs.func-sort-c.html b/coverage/dylint/src/driver_builder.rs.func-sort-c.html new file mode 100644 index 000000000..fcca4384c --- /dev/null +++ b/coverage/dylint/src/driver_builder.rs.func-sort-c.html @@ -0,0 +1,168 @@ + + + + + + + LCOV - unnamed - dylint/src/driver_builder.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src - driver_builder.rs (source / functions)HitTotalCoverage
Test:unnamedLines:12915782.2 %
Date:2024-04-23 03:30:56Functions:112445.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint::driver_builder::build::{closure#0}0
dylint::driver_builder::build::{closure#1}0
dylint::driver_builder::dylint_drivers::{closure#0}0
dylint::driver_builder::dylint_drivers::{closure#1}0
dylint::driver_builder::dylint_drivers::{closure#2}0
dylint::driver_builder::get::{closure#0}0
dylint::driver_builder::initialize::{closure#1}0
dylint::driver_builder::initialize::{closure#2}0
dylint::driver_builder::initialize::{closure#3}0
dylint::driver_builder::initialize::{closure#4}0
dylint::driver_builder::is_outdated::{closure#0}::{closure#1}0
dylint::driver_builder::is_outdated::{closure#0}::{closure#2}0
dylint::driver_builder::is_outdated::{closure#1}0
dylint::driver_builder::test::nightly1
dylint::driver_builder::build5
dylint::driver_builder::cargo_toml5
dylint::driver_builder::initialize5
dylint::driver_builder::initialize::{closure#0}5
dylint::driver_builder::rust_toolchain5
dylint::driver_builder::is_outdated25
dylint::driver_builder::is_outdated::{closure#0}25
dylint::driver_builder::is_outdated::{closure#0}::{closure#0}25
dylint::driver_builder::dylint_drivers29
dylint::driver_builder::get29
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/driver_builder.rs.func.html b/coverage/dylint/src/driver_builder.rs.func.html new file mode 100644 index 000000000..f9c62377f --- /dev/null +++ b/coverage/dylint/src/driver_builder.rs.func.html @@ -0,0 +1,168 @@ + + + + + + + LCOV - unnamed - dylint/src/driver_builder.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src - driver_builder.rs (source / functions)HitTotalCoverage
Test:unnamedLines:12915782.2 %
Date:2024-04-23 03:30:56Functions:112445.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint::driver_builder::build5
dylint::driver_builder::build::{closure#0}0
dylint::driver_builder::build::{closure#1}0
dylint::driver_builder::cargo_toml5
dylint::driver_builder::dylint_drivers29
dylint::driver_builder::dylint_drivers::{closure#0}0
dylint::driver_builder::dylint_drivers::{closure#1}0
dylint::driver_builder::dylint_drivers::{closure#2}0
dylint::driver_builder::get29
dylint::driver_builder::get::{closure#0}0
dylint::driver_builder::initialize5
dylint::driver_builder::initialize::{closure#0}5
dylint::driver_builder::initialize::{closure#1}0
dylint::driver_builder::initialize::{closure#2}0
dylint::driver_builder::initialize::{closure#3}0
dylint::driver_builder::initialize::{closure#4}0
dylint::driver_builder::is_outdated25
dylint::driver_builder::is_outdated::{closure#0}25
dylint::driver_builder::is_outdated::{closure#0}::{closure#0}25
dylint::driver_builder::is_outdated::{closure#0}::{closure#1}0
dylint::driver_builder::is_outdated::{closure#0}::{closure#2}0
dylint::driver_builder::is_outdated::{closure#1}0
dylint::driver_builder::rust_toolchain5
dylint::driver_builder::test::nightly1
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/driver_builder.rs.gcov.html b/coverage/dylint/src/driver_builder.rs.gcov.html new file mode 100644 index 000000000..36bb25a1f --- /dev/null +++ b/coverage/dylint/src/driver_builder.rs.gcov.html @@ -0,0 +1,315 @@ + + + + + + + LCOV - unnamed - dylint/src/driver_builder.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src - driver_builder.rs (source / functions)HitTotalCoverage
Test:unnamedLines:12915782.2 %
Date:2024-04-23 03:30:56Functions:112445.8 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use crate::{error::warn, opts};
+       2             : use anyhow::{anyhow, ensure, Context, Result};
+       3             : use cargo_metadata::MetadataCommand;
+       4             : use dylint_internal::{
+       5             :     driver as dylint_driver, env,
+       6             :     rustup::{toolchain_path, SanitizeEnvironment},
+       7             :     CommandExt,
+       8             : };
+       9             : use semver::Version;
+      10             : use std::{
+      11             :     env::consts,
+      12             :     fs::{copy, create_dir_all, write},
+      13             :     path::{Path, PathBuf},
+      14             : };
+      15             : use tempfile::tempdir;
+      16             : 
+      17             : include!(concat!(env!("OUT_DIR"), "/dylint_driver_manifest_dir.rs"));
+      18             : 
+      19             : const README_TXT: &str = "
+      20             : This directory contains Rust compiler drivers used by Dylint
+      21             : (https://github.com/trailofbits/dylint).
+      22             : 
+      23             : Deleting this directory will cause Dylint to rebuild the drivers
+      24             : the next time it needs them, but will have no ill effects.
+      25             : ";
+      26             : 
+      27           5 : fn cargo_toml(toolchain: &str, dylint_driver_spec: &str) -> String {
+      28           5 :     format!(
+      29           5 :         r#"
+      30           5 : [package]
+      31           5 : name = "dylint_driver-{toolchain}"
+      32           5 : version = "0.1.0"
+      33           5 : edition = "2018"
+      34           5 : 
+      35           5 : [dependencies]
+      36           5 : anyhow = "1.0"
+      37           5 : env_logger = "0.10"
+      38           5 : dylint_driver = {{ {dylint_driver_spec} }}
+      39           5 : "#,
+      40           5 :     )
+      41           5 : }
+      42             : 
+      43           5 : fn rust_toolchain(toolchain: &str) -> String {
+      44           5 :     format!(
+      45           5 :         r#"
+      46           5 : [toolchain]
+      47           5 : channel = "{toolchain}"
+      48           5 : components = ["llvm-tools-preview", "rustc-dev"]
+      49           5 : "#,
+      50           5 :     )
+      51           5 : }
+      52             : 
+      53             : const MAIN_RS: &str = r"
+      54             : use anyhow::Result;
+      55             : use std::env;
+      56             : use std::ffi::OsString;
+      57             : 
+      58             : pub fn main() -> Result<()> {
+      59             :     env_logger::init();
+      60             : 
+      61             :     let args: Vec<_> = env::args().map(OsString::from).collect();
+      62             : 
+      63             :     dylint_driver::dylint_driver(&args)
+      64             : }
+      65             : ";
+      66             : 
+      67             : #[cfg_attr(
+      68             :     dylint_lib = "question_mark_in_expression",
+      69             :     allow(question_mark_in_expression)
+      70             : )]
+      71          29 : pub fn get(opts: &opts::Dylint, toolchain: &str) -> Result<PathBuf> {
+      72          29 :     let dylint_drivers = dylint_drivers()?;
+      73             : 
+      74          29 :     let driver_dir = dylint_drivers.join(toolchain);
+      75          29 :     if !driver_dir.is_dir() {
+      76           4 :         create_dir_all(&driver_dir).with_context(|| {
+      77           0 :             format!(
+      78           0 :                 "`create_dir_all` failed for `{}`",
+      79           0 :                 driver_dir.to_string_lossy()
+      80           0 :             )
+      81           4 :         })?;
+      82          25 :     }
+      83             : 
+      84          29 :     let driver = driver_dir.join("dylint-driver");
+      85          29 :     if !driver.exists() || is_outdated(opts, toolchain, &driver)? {
+      86           4 :         build(opts, toolchain, &driver)?;
+      87          25 :     }
+      88             : 
+      89          29 :     Ok(driver)
+      90          29 : }
+      91             : 
+      92          29 : fn dylint_drivers() -> Result<PathBuf> {
+      93          29 :     if let Ok(dylint_driver_path) = env::var(env::DYLINT_DRIVER_PATH) {
+      94           0 :         let dylint_drivers = Path::new(&dylint_driver_path);
+      95           0 :         ensure!(dylint_drivers.is_dir());
+      96           0 :         Ok(dylint_drivers.to_path_buf())
+      97             :     } else {
+      98          29 :         let home = dirs::home_dir().ok_or_else(|| anyhow!("Could not find HOME directory"))?;
+      99          29 :         let dylint_drivers = Path::new(&home).join(".dylint_drivers");
+     100          29 :         if !dylint_drivers.is_dir() {
+     101           0 :             create_dir_all(&dylint_drivers).with_context(|| {
+     102           0 :                 format!(
+     103           0 :                     "`create_dir_all` failed for `{}`",
+     104           0 :                     dylint_drivers.to_string_lossy()
+     105           0 :                 )
+     106           0 :             })?;
+     107           0 :             let readme_txt = dylint_drivers.join("README.txt");
+     108           0 :             write(&readme_txt, README_TXT).with_context(|| {
+     109           0 :                 format!("`write` failed for `{}`", readme_txt.to_string_lossy())
+     110           0 :             })?;
+     111          29 :         }
+     112          29 :         Ok(dylint_drivers)
+     113             :     }
+     114          29 : }
+     115             : 
+     116          25 : fn is_outdated(opts: &opts::Dylint, toolchain: &str, driver: &Path) -> Result<bool> {
+     117          25 :     (|| -> Result<bool> {
+     118          25 :         let mut command = dylint_driver(toolchain, driver)?;
+     119          25 :         let output = command.args(["-V"]).logged_output(true)?;
+     120          25 :         let stdout = std::str::from_utf8(&output.stdout)?;
+     121          25 :         let theirs = stdout
+     122          25 :             .trim_end()
+     123          25 :             .rsplit_once(' ')
+     124          25 :             .map(|(_, s)| s)
+     125          25 :             .ok_or_else(|| anyhow!("Could not determine driver version"))?;
+     126             : 
+     127          25 :         let their_version = Version::parse(theirs)
+     128          25 :             .with_context(|| format!("Could not parse driver version `{theirs}`"))?;
+     129             : 
+     130          25 :         let our_version = Version::parse(env!("CARGO_PKG_VERSION"))?;
+     131             : 
+     132          25 :         Ok(their_version < our_version)
+     133          25 :     })()
+     134          25 :     .or_else(|error| {
+     135           0 :         warn(opts, &error.to_string());
+     136           0 :         Ok(true)
+     137          25 :     })
+     138          25 : }
+     139             : 
+     140             : #[cfg_attr(dylint_lib = "supplementary", allow(commented_code))]
+     141           5 : fn build(opts: &opts::Dylint, toolchain: &str, driver: &Path) -> Result<()> {
+     142           5 :     let tempdir = tempdir().with_context(|| "`tempdir` failed")?;
+     143           5 :     let package = tempdir.path();
+     144           5 : 
+     145           5 :     initialize(toolchain, package)?;
+     146             : 
+     147           5 :     let metadata = MetadataCommand::new()
+     148           5 :         .current_dir(package)
+     149           5 :         .no_deps()
+     150           5 :         .exec()?;
+     151             : 
+     152           5 :     let toolchain_path = toolchain_path(package)?;
+     153             : 
+     154             :     // smoelius: The commented code was the old behavior. It would cause the driver to have rpaths
+     155             :     // like `$ORIGIN/../../`... (see https://github.com/trailofbits/dylint/issues/54). The new
+     156             :     // behavior causes the driver to have absolute rpaths.
+     157             :     // let rustflags = "-C rpath=yes";
+     158           5 :     let rustflags = format!(
+     159           5 :         "-C link-args=-Wl,-rpath,{}/lib",
+     160           5 :         toolchain_path.to_string_lossy()
+     161           5 :     );
+     162           5 : 
+     163           5 :     #[cfg(debug_assertions)]
+     164           5 :     if DYLINT_DRIVER_MANIFEST_DIR.is_none() {
+     165           0 :         warn(opts, "In debug mode building driver from `crates.io`");
+     166           5 :     }
+     167             : 
+     168           5 :     dylint_internal::cargo::build(&format!("driver for toolchain `{toolchain}`"))
+     169           5 :         .quiet(opts.quiet)
+     170           5 :         .build()
+     171           5 :         .sanitize_environment()
+     172           5 :         .envs([(env::RUSTFLAGS, rustflags)])
+     173           5 :         .current_dir(package)
+     174           5 :         .success()?;
+     175             : 
+     176           5 :     let binary = metadata
+     177           5 :         .target_directory
+     178           5 :         .join("debug")
+     179           5 :         .join(format!("dylint_driver-{toolchain}{}", consts::EXE_SUFFIX));
+     180           5 :     #[cfg_attr(dylint_lib = "general", allow(non_thread_safe_call_in_test))]
+     181           5 :     copy(&binary, driver).with_context(|| {
+     182           0 :         format!(
+     183           0 :             "Could not copy `{binary}` to `{}`",
+     184           0 :             driver.to_string_lossy()
+     185           0 :         )
+     186           5 :     })?;
+     187             : 
+     188           5 :     Ok(())
+     189           5 : }
+     190             : 
+     191             : // smoelius: `package` is a temporary directory. So there should be no race here.
+     192             : #[cfg_attr(dylint_lib = "general", allow(non_thread_safe_call_in_test))]
+     193           5 : fn initialize(toolchain: &str, package: &Path) -> Result<()> {
+     194           5 :     let version_spec = format!("version = \"={}\"", env!("CARGO_PKG_VERSION"));
+     195           5 : 
+     196           5 :     let path_spec = DYLINT_DRIVER_MANIFEST_DIR.map_or(String::new(), |path| {
+     197           5 :         format!(", path = \"{}\"", path.replace('\\', "\\\\"))
+     198           5 :     });
+     199           5 : 
+     200           5 :     let dylint_driver_spec = format!("{version_spec}{path_spec}");
+     201           5 : 
+     202           5 :     let cargo_toml_path = package.join("Cargo.toml");
+     203           5 :     write(&cargo_toml_path, cargo_toml(toolchain, &dylint_driver_spec))
+     204           5 :         .with_context(|| format!("`write` failed for `{}`", cargo_toml_path.to_string_lossy()))?;
+     205           5 :     let rust_toolchain_path = package.join("rust-toolchain");
+     206           5 :     write(&rust_toolchain_path, rust_toolchain(toolchain)).with_context(|| {
+     207           0 :         format!(
+     208           0 :             "`write` failed for `{}`",
+     209           0 :             rust_toolchain_path.to_string_lossy()
+     210           0 :         )
+     211           5 :     })?;
+     212           5 :     let src = package.join("src");
+     213           5 :     create_dir_all(&src)
+     214           5 :         .with_context(|| format!("`create_dir_all` failed for `{}`", src.to_string_lossy()))?;
+     215           5 :     let main_rs = src.join("main.rs");
+     216           5 :     write(&main_rs, MAIN_RS)
+     217           5 :         .with_context(|| format!("`write` failed for `{}`", main_rs.to_string_lossy()))?;
+     218             : 
+     219           5 :     Ok(())
+     220           5 : }
+     221             : 
+     222             : #[allow(clippy::unwrap_used)]
+     223             : #[cfg(test)]
+     224             : mod test {
+     225             :     use super::*;
+     226             : 
+     227             :     // smoelius: `tempdir` is a temporary directory. So there should be no race here.
+     228             :     #[cfg_attr(dylint_lib = "general", allow(non_thread_safe_call_in_test))]
+     229             :     #[test]
+     230           1 :     fn nightly() {
+     231           1 :         let tempdir = tempdir().unwrap();
+     232           1 :         build(
+     233           1 :             &opts::Dylint::default(),
+     234           1 :             "nightly",
+     235           1 :             &tempdir.path().join("dylint-driver"),
+     236           1 :         )
+     237           1 :         .unwrap();
+     238           1 :     }
+     239             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/error.rs.func-sort-c.html b/coverage/dylint/src/error.rs.func-sort-c.html new file mode 100644 index 000000000..e9124c74a --- /dev/null +++ b/coverage/dylint/src/error.rs.func-sort-c.html @@ -0,0 +1,92 @@ + + + + + + + LCOV - unnamed - dylint/src/error.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src - error.rs (source / functions)HitTotalCoverage
Test:unnamedLines:212487.5 %
Date:2024-04-23 03:30:56Functions:3560.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::error::ColorizedError<_> as core::fmt::Debug>::fmt0
<dylint::error::ColorizedError<_>>::new0
<dylint::error::ColorizedError<anyhow::Error> as core::fmt::Debug>::fmt9
<dylint::error::ColorizedError<anyhow::Error>>::new9
dylint::error::warn46
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/error.rs.func.html b/coverage/dylint/src/error.rs.func.html new file mode 100644 index 000000000..306fd5195 --- /dev/null +++ b/coverage/dylint/src/error.rs.func.html @@ -0,0 +1,92 @@ + + + + + + + LCOV - unnamed - dylint/src/error.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src - error.rs (source / functions)HitTotalCoverage
Test:unnamedLines:212487.5 %
Date:2024-04-23 03:30:56Functions:3560.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::error::ColorizedError<_> as core::fmt::Debug>::fmt0
<dylint::error::ColorizedError<_>>::new0
<dylint::error::ColorizedError<anyhow::Error> as core::fmt::Debug>::fmt9
<dylint::error::ColorizedError<anyhow::Error>>::new9
dylint::error::warn46
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/error.rs.gcov.html b/coverage/dylint/src/error.rs.gcov.html new file mode 100644 index 000000000..7012683f6 --- /dev/null +++ b/coverage/dylint/src/error.rs.gcov.html @@ -0,0 +1,142 @@ + + + + + + + LCOV - unnamed - dylint/src/error.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src - error.rs (source / functions)HitTotalCoverage
Test:unnamedLines:212487.5 %
Date:2024-04-23 03:30:56Functions:3560.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use ansi_term::{
+       2             :     Color::{Red, Yellow},
+       3             :     Style,
+       4             : };
+       5             : use is_terminal::IsTerminal;
+       6             : use std::io::Write;
+       7             : 
+       8             : // smoelius: `ColorizedError` is currently used only by `cargo-dylint`. But given the similarity of
+       9             : // its implementation to `warn`, I prefer to keep it here for now. Also, FWIW, this limits the
+      10             : // packages that directly depend on `ansi_term`.
+      11             : 
+      12             : #[allow(clippy::module_name_repetitions)]
+      13             : pub struct ColorizedError<E>(E)
+      14             : where
+      15             :     E: std::fmt::Debug;
+      16             : 
+      17             : impl<E> ColorizedError<E>
+      18             : where
+      19             :     E: std::fmt::Debug,
+      20             : {
+      21             :     #[allow(clippy::missing_const_for_fn)]
+      22           9 :     pub fn new(error: E) -> Self {
+      23           9 :         Self(error)
+      24           9 :     }
+      25             : }
+      26             : 
+      27             : // smoelius: The use of `\r` is a bit of a hack, but it works, most notably with `anyhow`
+      28             : // backtraces. Another way might be to implement the `Termination` trait, but that trait is still
+      29             : // unstable: https://github.com/rust-lang/rust/issues/43301
+      30             : impl<E> std::fmt::Debug for ColorizedError<E>
+      31             : where
+      32             :     E: std::fmt::Debug,
+      33             : {
+      34           9 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+      35           9 :         write!(
+      36           9 :             f,
+      37           9 :             "{}{:?}",
+      38           9 :             if std::io::stderr().is_terminal() {
+      39           0 :                 format!("\r{}: ", Red.bold().paint("Error"))
+      40             :             } else {
+      41           9 :                 String::new()
+      42             :             },
+      43             :             self.0
+      44             :         )
+      45           9 :     }
+      46             : }
+      47             : 
+      48             : pub type ColorizedResult<T> = Result<T, ColorizedError<anyhow::Error>>;
+      49             : 
+      50             : #[allow(clippy::expect_used)]
+      51          46 : pub fn warn(opts: &crate::opts::Dylint, message: &str) {
+      52          46 :     if !opts.quiet {
+      53             :         // smoelius: Writing directly to `stderr` prevents capture by `libtest`.
+      54          46 :         std::io::stderr()
+      55          46 :             .write_fmt(format_args!(
+      56          46 :                 "{}: {message}\n",
+      57          46 :                 if std::io::stderr().is_terminal() {
+      58           0 :                     Yellow.bold()
+      59             :                 } else {
+      60          46 :                     Style::new()
+      61             :                 }
+      62          46 :                 .paint("Warning")
+      63          46 :             ))
+      64          46 :             .expect("Could not write to stderr");
+      65           0 :     }
+      66          46 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/index-sort-f.html b/coverage/dylint/src/index-sort-f.html new file mode 100644 index 000000000..9f0e0cfce --- /dev/null +++ b/coverage/dylint/src/index-sort-f.html @@ -0,0 +1,123 @@ + + + + + + + LCOV - unnamed - dylint/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/srcHitTotalCoverage
Test:unnamedLines:56866685.3 %
Date:2024-04-23 03:30:56Functions:436863.2 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
driver_builder.rs +
82.2%82.2%
+
82.2 %129 / 15745.8 %11 / 24
error.rs +
87.5%87.5%
+
87.5 %21 / 2460.0 %3 / 5
lib.rs +
85.9%85.9%
+
85.9 %383 / 44668.8 %22 / 32
opts.rs +
89.7%89.7%
+
89.7 %35 / 39100.0 %7 / 7
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/index-sort-l.html b/coverage/dylint/src/index-sort-l.html new file mode 100644 index 000000000..998ea4ab0 --- /dev/null +++ b/coverage/dylint/src/index-sort-l.html @@ -0,0 +1,123 @@ + + + + + + + LCOV - unnamed - dylint/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/srcHitTotalCoverage
Test:unnamedLines:56866685.3 %
Date:2024-04-23 03:30:56Functions:436863.2 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
driver_builder.rs +
82.2%82.2%
+
82.2 %129 / 15745.8 %11 / 24
lib.rs +
85.9%85.9%
+
85.9 %383 / 44668.8 %22 / 32
error.rs +
87.5%87.5%
+
87.5 %21 / 2460.0 %3 / 5
opts.rs +
89.7%89.7%
+
89.7 %35 / 39100.0 %7 / 7
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/index.html b/coverage/dylint/src/index.html new file mode 100644 index 000000000..ba290cf47 --- /dev/null +++ b/coverage/dylint/src/index.html @@ -0,0 +1,123 @@ + + + + + + + LCOV - unnamed - dylint/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/srcHitTotalCoverage
Test:unnamedLines:56866685.3 %
Date:2024-04-23 03:30:56Functions:436863.2 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
driver_builder.rs +
82.2%82.2%
+
82.2 %129 / 15745.8 %11 / 24
error.rs +
87.5%87.5%
+
87.5 %21 / 2460.0 %3 / 5
lib.rs +
85.9%85.9%
+
85.9 %383 / 44668.8 %22 / 32
opts.rs +
89.7%89.7%
+
89.7 %35 / 39100.0 %7 / 7
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/lib.rs.func-sort-c.html b/coverage/dylint/src/lib.rs.func-sort-c.html new file mode 100644 index 000000000..4d4ef7e57 --- /dev/null +++ b/coverage/dylint/src/lib.rs.func-sort-c.html @@ -0,0 +1,200 @@ + + + + + + + LCOV - unnamed - dylint/src/lib.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src - lib.rs (source / functions)HitTotalCoverage
Test:unnamedLines:38344685.9 %
Date:2024-04-23 03:30:56Functions:223268.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint::REQUIRED_FORM::{closure#0}0
dylint::check_or_fix::{closure#1}0
dylint::check_or_fix::{closure#2}0
dylint::display_location::{closure#0}0
dylint::display_location::{closure#1}0
dylint::list_lints::{closure#0}0
dylint::name_as_lib::{closure#0}0
dylint::resolve::{closure#1}0
dylint::resolve::{closure#2}0
dylint::run::{closure#0}::{closure#0}0
dylint::name_as_path1
dylint::test::OPTS::{closure#0}1
dylint::test::multiple_libraries_multiple_toolchains1
dylint::test::multiple_libraries_one_toolchain1
dylint::test::name_toolchain_map2
dylint::check_or_fix::{closure#3}3
dylint::run::{closure#0}3
dylint::list_libs4
dylint::display_location5
dylint::list_lints5
dylint::warn_if_empty5
dylint::is_valid_lib_name13
dylint::name_as_lib13
dylint::resolve::{closure#0}16
dylint::check_or_fix::{closure#0}17
dylint::check_or_fix21
dylint::clippy_disable_docs_links21
dylint::target_dir21
dylint::resolve31
dylint::run_with_name_toolchain_map37
dylint::flatten_toolchain_map::<alloc::collections::btree::set::BTreeSet<dylint::name_toolchain_map::maybe_library::MaybeLibrary>39
dylint::run39
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/lib.rs.func.html b/coverage/dylint/src/lib.rs.func.html new file mode 100644 index 000000000..0a1ea5b8d --- /dev/null +++ b/coverage/dylint/src/lib.rs.func.html @@ -0,0 +1,200 @@ + + + + + + + LCOV - unnamed - dylint/src/lib.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src - lib.rs (source / functions)HitTotalCoverage
Test:unnamedLines:38344685.9 %
Date:2024-04-23 03:30:56Functions:223268.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint::REQUIRED_FORM::{closure#0}0
dylint::check_or_fix21
dylint::check_or_fix::{closure#0}17
dylint::check_or_fix::{closure#1}0
dylint::check_or_fix::{closure#2}0
dylint::check_or_fix::{closure#3}3
dylint::clippy_disable_docs_links21
dylint::display_location5
dylint::display_location::{closure#0}0
dylint::display_location::{closure#1}0
dylint::flatten_toolchain_map::<alloc::collections::btree::set::BTreeSet<dylint::name_toolchain_map::maybe_library::MaybeLibrary>39
dylint::is_valid_lib_name13
dylint::list_libs4
dylint::list_lints5
dylint::list_lints::{closure#0}0
dylint::name_as_lib13
dylint::name_as_lib::{closure#0}0
dylint::name_as_path1
dylint::resolve31
dylint::resolve::{closure#0}16
dylint::resolve::{closure#1}0
dylint::resolve::{closure#2}0
dylint::run39
dylint::run::{closure#0}3
dylint::run::{closure#0}::{closure#0}0
dylint::run_with_name_toolchain_map37
dylint::target_dir21
dylint::test::OPTS::{closure#0}1
dylint::test::multiple_libraries_multiple_toolchains1
dylint::test::multiple_libraries_one_toolchain1
dylint::test::name_toolchain_map2
dylint::warn_if_empty5
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/lib.rs.gcov.html b/coverage/dylint/src/lib.rs.gcov.html new file mode 100644 index 000000000..7dd958679 --- /dev/null +++ b/coverage/dylint/src/lib.rs.gcov.html @@ -0,0 +1,711 @@ + + + + + + + LCOV - unnamed - dylint/src/lib.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src - lib.rs (source / functions)HitTotalCoverage
Test:unnamedLines:38344685.9 %
Date:2024-04-23 03:30:56Functions:223268.8 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : #![cfg_attr(dylint_lib = "general", allow(crate_wide_allow))]
+       2             : #![deny(clippy::expect_used)]
+       3             : #![deny(clippy::unwrap_used)]
+       4             : #![deny(clippy::panic)]
+       5             : 
+       6             : use anyhow::{anyhow, bail, ensure, Context, Result};
+       7             : use cargo_metadata::MetadataCommand;
+       8             : use dylint_internal::{
+       9             :     driver as dylint_driver, env, parse_path_filename, rustup::SanitizeEnvironment, CommandExt,
+      10             : };
+      11             : use once_cell::sync::Lazy;
+      12             : use std::{
+      13             :     collections::BTreeMap,
+      14             :     env::{consts, current_dir},
+      15             :     ffi::OsStr,
+      16             :     fs::{metadata, OpenOptions},
+      17             :     path::{Path, PathBuf, MAIN_SEPARATOR},
+      18             : };
+      19             : 
+      20             : type Object = serde_json::Map<String, serde_json::Value>;
+      21             : 
+      22             : // smoelius: See note in dylint/src/metadata/mod.rs.
+      23             : #[cfg(feature = "__cargo_lib")]
+      24             : pub(crate) use cargo::{core, sources, util};
+      25             : 
+      26             : pub mod driver_builder;
+      27             : 
+      28             : mod error;
+      29             : use error::warn;
+      30             : #[doc(hidden)]
+      31             : pub use error::warn as __warn;
+      32             : pub use error::{ColorizedError, ColorizedResult};
+      33             : 
+      34             : mod name_toolchain_map;
+      35             : pub use name_toolchain_map::{Lazy as NameToolchainMap, ToolchainMap};
+      36             : use name_toolchain_map::{LazyToolchainMap, MaybeLibrary};
+      37             : 
+      38             : #[cfg(__library_packages)]
+      39             : pub(crate) mod library_packages;
+      40             : 
+      41             : pub mod opts;
+      42             : 
+      43             : #[cfg(feature = "package_options")]
+      44             : mod package_options;
+      45             : 
+      46           0 : static REQUIRED_FORM: Lazy<String> = Lazy::new(|| {
+      47           0 :     format!(
+      48           0 :         r#""{}" LIBRARY_NAME "@" TOOLCHAIN "{}""#,
+      49           0 :         consts::DLL_PREFIX,
+      50           0 :         consts::DLL_SUFFIX
+      51           0 :     )
+      52           0 : });
+      53             : 
+      54             : #[cfg_attr(dylint_lib = "general", allow(non_local_effect_before_error_return))]
+      55             : #[cfg_attr(dylint_lib = "overscoped_allow", allow(overscoped_allow))]
+      56          39 : pub fn run(opts: &opts::Dylint) -> Result<()> {
+      57          39 :     let opts = {
+      58          39 :         let opts_orig = opts;
+      59          39 : 
+      60          39 :         let mut opts = opts.clone();
+      61             : 
+      62           4 :         if matches!(
+      63          39 :             opts.operation,
+      64             :             opts::Operation::Check(_) | opts::Operation::List(_)
+      65             :         ) {
+      66          35 :             let lib_sel = opts.library_selection_mut();
+      67             : 
+      68          35 :             let path_refers_to_libraries =
+      69          35 :                 lib_sel
+      70          35 :                     .paths
+      71          35 :                     .iter()
+      72          35 :                     .try_fold(false, |is_file, path| -> Result<_> {
+      73           3 :                         let metadata =
+      74           3 :                             metadata(path).with_context(|| "Could not read file metadata")?;
+      75           3 :                         Ok(is_file || metadata.is_file())
+      76          35 :                     })?;
+      77             : 
+      78          35 :             if path_refers_to_libraries {
+      79           1 :                 warn(
+      80           1 :                     opts_orig,
+      81           1 :                     "Referring to libraries with `--path` is deprecated. Use `--lib-path`.",
+      82           1 :                 );
+      83           1 :                 lib_sel.lib_paths.extend(lib_sel.paths.split_off(0));
+      84          34 :             };
+      85             : 
+      86             :             // smoelius: Use of `--git` or `--path` implies `--all`.
+      87          35 :             lib_sel.all |= lib_sel.git_or_path();
+      88           4 :         }
+      89             : 
+      90          39 :         opts
+      91          39 :     };
+      92          39 : 
+      93          39 :     if opts.library_selection().pattern.is_some() && !opts.git_or_path() {
+      94           0 :         bail!("`--pattern` can be used only with `--git` or `--path`");
+      95          39 :     }
+      96          39 : 
+      97          39 :     if opts.pipe_stderr.is_some() {
+      98           0 :         warn(&opts, "`--pipe-stderr` is experimental");
+      99          39 :     }
+     100             : 
+     101          39 :     if opts.pipe_stdout.is_some() {
+     102           0 :         warn(&opts, "`--pipe-stdout` is experimental");
+     103          39 :     }
+     104             : 
+     105          39 :     match &opts.operation {
+     106             :         opts::Operation::Check(_) | opts::Operation::List(_) => {
+     107          35 :             let name_toolchain_map = NameToolchainMap::new(&opts);
+     108          35 :             run_with_name_toolchain_map(&opts, &name_toolchain_map)
+     109             :         }
+     110             :         #[cfg(feature = "package_options")]
+     111           1 :         opts::Operation::New(new_opts) => package_options::new_package(&opts, new_opts),
+     112             :         #[cfg(feature = "package_options")]
+     113           3 :         opts::Operation::Upgrade(upgrade_opts) => {
+     114           3 :             package_options::upgrade_package(&opts, upgrade_opts)
+     115             :         }
+     116             :     }
+     117          39 : }
+     118             : 
+     119          37 : fn run_with_name_toolchain_map(
+     120          37 :     opts: &opts::Dylint,
+     121          37 :     name_toolchain_map: &NameToolchainMap,
+     122          37 : ) -> Result<()> {
+     123          37 :     let lib_sel = opts.library_selection();
+     124          37 : 
+     125          37 :     if lib_sel.libs.is_empty() && lib_sel.lib_paths.is_empty() && !lib_sel.all {
+     126           6 :         if matches!(opts.operation, opts::Operation::List(_)) {
+     127           4 :             warn_if_empty(opts, name_toolchain_map)?;
+     128           4 :             return list_libs(name_toolchain_map);
+     129           2 :         }
+     130           2 : 
+     131           2 :         warn(opts, "Nothing to do. Did you forget `--all`?");
+     132           2 :         return Ok(());
+     133          31 :     }
+     134             : 
+     135          31 :     let resolved = resolve(opts, name_toolchain_map)?;
+     136             : 
+     137          26 :     if resolved.is_empty() {
+     138           1 :         assert!(lib_sel.libs.is_empty());
+     139           1 :         assert!(lib_sel.lib_paths.is_empty());
+     140             : 
+     141           1 :         let name_toolchain_map_is_empty = warn_if_empty(opts, name_toolchain_map)?;
+     142             : 
+     143             :         // smoelius: If `name_toolchain_map` is NOT empty, then it had better be the case that
+     144             :         // `--all` was not passed.
+     145           1 :         assert!(name_toolchain_map_is_empty || !lib_sel.all);
+     146          25 :     }
+     147             : 
+     148          26 :     match &opts.operation {
+     149          21 :         opts::Operation::Check(check_opts) => check_or_fix(opts, check_opts, &resolved),
+     150           5 :         opts::Operation::List(_) => list_lints(opts, &resolved),
+     151             :         #[allow(unreachable_patterns)]
+     152           0 :         _ => unreachable!(),
+     153             :     }
+     154          37 : }
+     155             : 
+     156           5 : fn warn_if_empty(opts: &opts::Dylint, name_toolchain_map: &NameToolchainMap) -> Result<bool> {
+     157           5 :     let name_toolchain_map = name_toolchain_map.get_or_try_init()?;
+     158             : 
+     159           5 :     Ok(if name_toolchain_map.is_empty() {
+     160           2 :         warn(opts, "No libraries were found.");
+     161           2 :         true
+     162             :     } else {
+     163           3 :         false
+     164             :     })
+     165           5 : }
+     166             : 
+     167           4 : fn list_libs(name_toolchain_map: &NameToolchainMap) -> Result<()> {
+     168           4 :     let name_toolchain_map = name_toolchain_map.get_or_try_init()?;
+     169             : 
+     170           4 :     let name_width = name_toolchain_map
+     171           4 :         .keys()
+     172           4 :         .map(String::len)
+     173           4 :         .max()
+     174           4 :         .unwrap_or_default();
+     175           4 : 
+     176           4 :     let toolchain_width = name_toolchain_map
+     177           4 :         .values()
+     178           4 :         .flat_map(LazyToolchainMap::keys)
+     179           4 :         .map(String::len)
+     180           4 :         .max()
+     181           4 :         .unwrap_or_default();
+     182             : 
+     183           7 :     for (name, toolchain_map) in name_toolchain_map {
+     184           6 :         for (toolchain, maybe_libraries) in toolchain_map {
+     185           6 :             for maybe_library in maybe_libraries {
+     186           3 :                 let location = display_location(&maybe_library.path())?;
+     187           3 :                 println!("{name:<name_width$}  {toolchain:<toolchain_width$}  {location}",);
+     188             :             }
+     189             :         }
+     190             :     }
+     191             : 
+     192           4 :     Ok(())
+     193           4 : }
+     194             : 
+     195             : #[cfg_attr(
+     196             :     dylint_lib = "question_mark_in_expression",
+     197             :     allow(question_mark_in_expression)
+     198             : )]
+     199          31 : fn resolve(opts: &opts::Dylint, name_toolchain_map: &NameToolchainMap) -> Result<ToolchainMap> {
+     200          31 :     let lib_sel = opts.library_selection();
+     201          31 : 
+     202          31 :     let mut toolchain_map = ToolchainMap::new();
+     203          31 : 
+     204          31 :     if lib_sel.all {
+     205          19 :         let name_toolchain_map = name_toolchain_map.get_or_try_init()?;
+     206             : 
+     207          14 :         for other in name_toolchain_map.values() {
+     208          29 :             for (toolchain, maybe_libraries) in other {
+     209          15 :                 let paths = maybe_libraries
+     210          15 :                     .iter()
+     211          16 :                     .map(|maybe_library| maybe_library.build(opts))
+     212          15 :                     .collect::<Result<Vec<_>>>()?;
+     213          15 :                 toolchain_map
+     214          15 :                     .entry(toolchain.clone())
+     215          15 :                     .or_default()
+     216          15 :                     .extend(paths);
+     217             :             }
+     218             :         }
+     219          12 :     }
+     220             : 
+     221          39 :     for name in &lib_sel.libs {
+     222          13 :         ensure!(!lib_sel.all, "`--lib` cannot be used with `--all`");
+     223          13 :         let (toolchain, maybe_library) =
+     224          13 :             name_as_lib(name_toolchain_map, name, true)?.unwrap_or_else(|| unreachable!());
+     225          13 :         let path = maybe_library.build(opts)?;
+     226          13 :         toolchain_map.entry(toolchain).or_default().insert(path);
+     227             :     }
+     228             : 
+     229          27 :     for name in &lib_sel.lib_paths {
+     230           1 :         let (toolchain, path) = name_as_path(name, true)?.unwrap_or_else(|| unreachable!());
+     231           1 :         toolchain_map.entry(toolchain).or_default().insert(path);
+     232             :     }
+     233             : 
+     234          26 :     Ok(toolchain_map)
+     235          31 : }
+     236             : 
+     237          13 : pub fn name_as_lib(
+     238          13 :     name_toolchain_map: &NameToolchainMap,
+     239          13 :     name: &str,
+     240          13 :     as_lib_only: bool,
+     241          13 : ) -> Result<Option<(String, MaybeLibrary)>> {
+     242          13 :     if !is_valid_lib_name(name) {
+     243           0 :         ensure!(!as_lib_only, "`{}` is not a valid library name", name);
+     244           0 :         return Ok(None);
+     245          13 :     }
+     246             : 
+     247          13 :     let name_toolchain_map = name_toolchain_map.get_or_try_init()?;
+     248             : 
+     249          13 :     if let Some(toolchain_map) = name_toolchain_map.get(name) {
+     250          13 :         let mut toolchain_maybe_libraries = flatten_toolchain_map(toolchain_map);
+     251          13 : 
+     252          13 :         return match toolchain_maybe_libraries.len() {
+     253           0 :             0 => Ok(None),
+     254          13 :             1 => Ok(Some(toolchain_maybe_libraries.remove(0))),
+     255           0 :             _ => Err(anyhow!(
+     256           0 :                 "Found multiple libraries matching `{}`: {:?}",
+     257           0 :                 name,
+     258           0 :                 toolchain_maybe_libraries
+     259           0 :                     .iter()
+     260           0 :                     .map(|(_, path)| path)
+     261           0 :                     .collect::<Vec<_>>()
+     262           0 :             )),
+     263             :         };
+     264           0 :     }
+     265           0 : 
+     266           0 :     ensure!(!as_lib_only, "Could not find `--lib {}`", name);
+     267             : 
+     268           0 :     Ok(None)
+     269          13 : }
+     270             : 
+     271          13 : fn is_valid_lib_name(name: &str) -> bool {
+     272          13 :     Path::new(name).file_name() == Some(OsStr::new(name))
+     273          13 : }
+     274             : 
+     275          13 : fn flatten_toolchain_map<I, T>(toolchain_map: &BTreeMap<String, I>) -> Vec<(String, T)>
+     276          13 : where
+     277          13 :     for<'a> &'a I: IntoIterator<Item = &'a T>,
+     278          13 :     T: Clone,
+     279          13 : {
+     280          13 :     toolchain_map
+     281          13 :         .iter()
+     282          13 :         .flat_map(|(toolchain, values)| {
+     283          13 :             values
+     284          13 :                 .into_iter()
+     285          13 :                 .map(|value| (toolchain.clone(), value.clone()))
+     286          13 :                 .collect::<Vec<_>>()
+     287          13 :         })
+     288          13 :         .collect()
+     289          13 : }
+     290             : 
+     291           1 : fn name_as_path(name: &str, as_path_only: bool) -> Result<Option<(String, PathBuf)>> {
+     292           1 :     if let Ok(path) = PathBuf::from(name).canonicalize() {
+     293           1 :         if let Some((_, toolchain)) = parse_path_filename(&path) {
+     294           1 :             return Ok(Some((toolchain, path)));
+     295           0 :         }
+     296           0 : 
+     297           0 :         ensure!(
+     298           0 :             !as_path_only,
+     299           0 :             "`--lib-path {}` was used, but the filename does not have the required form: {}",
+     300           0 :             name,
+     301           0 :             *REQUIRED_FORM
+     302             :         );
+     303             : 
+     304             :         // smoelius: If `name` contains a path separator, then it was clearly meant to be a
+     305             :         // path.
+     306           0 :         ensure!(
+     307           0 :             !name.contains(MAIN_SEPARATOR),
+     308           0 :             "`{}` is a valid path, but the filename does not have the required form: {}",
+     309           0 :             name,
+     310           0 :             *REQUIRED_FORM
+     311             :         );
+     312             : 
+     313           0 :         ensure!(
+     314           0 :             !as_path_only,
+     315           0 :             "`--lib-path {}` was used, but it is invalid",
+     316             :             name
+     317             :         );
+     318           0 :     }
+     319             : 
+     320           0 :     ensure!(!as_path_only, "Could not find `--path {}`", name);
+     321             : 
+     322           0 :     Ok(None)
+     323           1 : }
+     324             : 
+     325           5 : fn list_lints(opts: &opts::Dylint, resolved: &ToolchainMap) -> Result<()> {
+     326          11 :     for (toolchain, paths) in resolved {
+     327          13 :         for path in paths {
+     328           7 :             let driver = driver_builder::get(opts, toolchain)?;
+     329           7 :             let dylint_libs = serde_json::to_string(&[path])?;
+     330           7 :             let (name, _) =
+     331           7 :                 parse_path_filename(path).ok_or_else(|| anyhow!("Could not parse path"))?;
+     332             : 
+     333           7 :             print!("{name}");
+     334           7 :             if resolved.keys().len() >= 2 {
+     335           2 :                 print!("@{toolchain}");
+     336           5 :             }
+     337           7 :             if paths.len() >= 2 {
+     338           2 :                 let location = display_location(path)?;
+     339           2 :                 print!(" ({location})");
+     340           5 :             }
+     341           7 :             println!();
+     342             : 
+     343             :             // smoelius: `-W help` is the normal way to list lints, so we can be sure it
+     344             :             // gets the lints loaded. However, we don't actually use it to list the lints.
+     345           7 :             let mut command = dylint_driver(toolchain, &driver)?;
+     346           7 :             command
+     347           7 :                 .envs([
+     348           7 :                     (env::DYLINT_LIBS, dylint_libs.as_str()),
+     349           7 :                     (env::DYLINT_LIST, "1"),
+     350           7 :                 ])
+     351           7 :                 .args(["rustc", "-W", "help"])
+     352           7 :                 .success()?;
+     353             : 
+     354           7 :             println!();
+     355             :         }
+     356             :     }
+     357             : 
+     358           5 :     Ok(())
+     359           5 : }
+     360             : 
+     361           5 : fn display_location(path: &Path) -> Result<String> {
+     362           5 :     let current_dir = current_dir().with_context(|| "Could not get current directory")?;
+     363           5 :     let Ok(path_buf) = path.canonicalize() else {
+     364           1 :         return Ok("<unbuilt>".to_owned());
+     365             :     };
+     366           4 :     let parent = path_buf
+     367           4 :         .parent()
+     368           4 :         .ok_or_else(|| anyhow!("Could not get parent directory"))?;
+     369           4 :     Ok(parent
+     370           4 :         .strip_prefix(&current_dir)
+     371           4 :         .unwrap_or(parent)
+     372           4 :         .to_string_lossy()
+     373           4 :         .to_string())
+     374           5 : }
+     375             : 
+     376          21 : fn check_or_fix(
+     377          21 :     opts: &opts::Dylint,
+     378          21 :     check_opts: &opts::Check,
+     379          21 :     resolved: &ToolchainMap,
+     380          21 : ) -> Result<()> {
+     381          21 :     let clippy_disable_docs_links = clippy_disable_docs_links()?;
+     382             : 
+     383          21 :     let mut failures = Vec::new();
+     384             : 
+     385          39 :     for (toolchain, paths) in resolved {
+     386          21 :         let target_dir = target_dir(opts, toolchain)?;
+     387          21 :         let target_dir_str = target_dir.to_string_lossy();
+     388          21 :         let driver = driver_builder::get(opts, toolchain)?;
+     389          21 :         let dylint_libs = serde_json::to_string(&paths)?;
+     390             :         #[cfg(not(__library_packages))]
+     391             :         let dylint_metadata = None;
+     392             :         #[cfg(__library_packages)]
+     393          21 :         let dylint_metadata = library_packages::dylint_metadata(opts)?;
+     394          21 :         let dylint_metadata_str = dylint_metadata
+     395          21 :             .map(|object: &Object| serde_json::Value::from(object.clone()))
+     396          21 :             .unwrap_or_default()
+     397          21 :             .to_string();
+     398          21 :         let description = format!("with toolchain `{toolchain}`");
+     399          21 :         let mut command = if check_opts.fix {
+     400           1 :             dylint_internal::cargo::fix(&description)
+     401             :         } else {
+     402          20 :             dylint_internal::cargo::check(&description)
+     403             :         }
+     404          21 :         .build();
+     405          21 :         let mut args = vec!["--target-dir", &target_dir_str];
+     406          21 :         if let Some(path) = &check_opts.lib_sel.manifest_path {
+     407           3 :             args.extend(["--manifest-path", path]);
+     408          18 :         }
+     409          23 :         for spec in &check_opts.packages {
+     410           2 :             args.extend(["-p", spec]);
+     411           2 :         }
+     412          21 :         if check_opts.workspace {
+     413           0 :             args.extend(["--workspace"]);
+     414          21 :         }
+     415          21 :         args.extend(check_opts.args.iter().map(String::as_str));
+     416          21 : 
+     417          21 :         // smoelius: Set CLIPPY_DISABLE_DOCS_LINKS to prevent lints from accidentally linking to the
+     418          21 :         // Clippy repository. But set it to the JSON-encoded original value so that the Clippy
+     419          21 :         // library can unset the variable.
+     420          21 :         // smoelius: This doesn't work if another library is loaded alongside Clippy.
+     421          21 :         // smoelius: This was fixed in `clippy_utils`:
+     422          21 :         // https://github.com/rust-lang/rust-clippy/commit/1a206fc4abae0b57a3f393481367cf3efca23586
+     423          21 :         // But I am going to continue to set CLIPPY_DISABLE_DOCS_LINKS because it doesn't seem to
+     424          21 :         // hurt and it provides a small amount of backward compatibility.
+     425          21 :         command
+     426          21 :             .sanitize_environment()
+     427          21 :             .envs([
+     428          21 :                 (
+     429          21 :                     env::CLIPPY_DISABLE_DOCS_LINKS,
+     430          21 :                     clippy_disable_docs_links.as_str(),
+     431          21 :                 ),
+     432          21 :                 (env::DYLINT_LIBS, &dylint_libs),
+     433          21 :                 (env::DYLINT_METADATA, &dylint_metadata_str),
+     434          21 :                 (
+     435          21 :                     env::DYLINT_NO_DEPS,
+     436          21 :                     if check_opts.no_deps { "1" } else { "0" },
+     437             :                 ),
+     438          21 :                 (env::RUSTC_WORKSPACE_WRAPPER, &*driver.to_string_lossy()),
+     439          21 :                 (env::RUSTUP_TOOLCHAIN, toolchain),
+     440          21 :             ])
+     441          21 :             .args(args);
+     442             : 
+     443          21 :         if let Some(stderr_path) = &opts.pipe_stderr {
+     444           0 :             let file = OpenOptions::new()
+     445           0 :                 .append(true)
+     446           0 :                 .create(true)
+     447           0 :                 .open(stderr_path)
+     448           0 :                 .with_context(|| format!("Failed to open `{stderr_path}` for stderr usage"))?;
+     449           0 :             command.stderr(file);
+     450          21 :         }
+     451             : 
+     452          21 :         if let Some(stdout_path) = &opts.pipe_stdout {
+     453           0 :             let file = OpenOptions::new()
+     454           0 :                 .append(true)
+     455           0 :                 .create(true)
+     456           0 :                 .open(stdout_path)
+     457           0 :                 .with_context(|| format!("Failed to open `{stdout_path}` for stdout usage"))?;
+     458           0 :             command.stdout(file);
+     459          21 :         }
+     460             : 
+     461          21 :         let result = command.success();
+     462          21 :         if result.is_err() {
+     463           3 :             if !check_opts.keep_going {
+     464           3 :                 return result
+     465           3 :                     .with_context(|| format!("Compilation failed with toolchain `{toolchain}`"));
+     466           0 :             };
+     467           0 :             failures.push(toolchain);
+     468          18 :         }
+     469             :     }
+     470             : 
+     471          18 :     if failures.is_empty() {
+     472          18 :         Ok(())
+     473             :     } else {
+     474           0 :         Err(anyhow!(
+     475           0 :             "Compilation failed with the following toolchains: {:?}",
+     476           0 :             failures
+     477           0 :         ))
+     478             :     }
+     479          21 : }
+     480             : 
+     481          21 : fn target_dir(opts: &opts::Dylint, toolchain: &str) -> Result<PathBuf> {
+     482          21 :     let mut command = MetadataCommand::new();
+     483          21 :     if let Some(path) = &opts.library_selection().manifest_path {
+     484           3 :         command.manifest_path(path);
+     485          18 :     }
+     486          21 :     let metadata = command.no_deps().exec()?;
+     487          21 :     Ok(metadata
+     488          21 :         .target_directory
+     489          21 :         .join("dylint/target")
+     490          21 :         .join(toolchain)
+     491          21 :         .into())
+     492          21 : }
+     493             : 
+     494          21 : fn clippy_disable_docs_links() -> Result<String> {
+     495          21 :     let val = env::var(env::CLIPPY_DISABLE_DOCS_LINKS).ok();
+     496          21 :     serde_json::to_string(&val).map_err(Into::into)
+     497          21 : }
+     498             : 
+     499             : #[allow(clippy::unwrap_used)]
+     500             : #[cfg(test)]
+     501             : mod test {
+     502             :     use super::*;
+     503             :     use dylint_internal::examples;
+     504             :     use std::{
+     505             :         env::{join_paths, set_var},
+     506             :         sync::Mutex,
+     507             :     };
+     508             : 
+     509             :     // smoelius: With the upgrade to nightly-2023-03-10, I started running into this:
+     510             :     // https://github.com/rust-lang/rustup/issues/988
+     511             :     // The easiest solution is to just not run the tests concurrently.
+     512             :     static MUTEX: Mutex<()> = Mutex::new(());
+     513             : 
+     514           1 :     static OPTS: Lazy<opts::Dylint> = Lazy::new(|| opts::Dylint {
+     515           1 :         operation: opts::Operation::Check(opts::Check {
+     516           1 :             lib_sel: opts::LibrarySelection {
+     517           1 :                 no_metadata: true,
+     518           1 :                 ..Default::default()
+     519           1 :             },
+     520           1 :             ..Default::default()
+     521           1 :         }),
+     522           1 :         ..Default::default()
+     523           1 :     });
+     524             : 
+     525           2 :     fn name_toolchain_map() -> NameToolchainMap<'static> {
+     526           2 :         examples::build().unwrap();
+     527           2 :         let metadata = dylint_internal::cargo::current_metadata().unwrap();
+     528           2 :         // smoelius: As of version 0.1.14, `cargo-llvm-cov` no longer sets `CARGO_TARGET_DIR`.
+     529           2 :         // So `dylint_library_path` no longer requires a `cfg!(coverage)` special case.
+     530           2 :         let dylint_library_path = join_paths([
+     531           2 :             metadata.target_directory.join("examples/debug"),
+     532           2 :             metadata.target_directory.join("straggler/debug"),
+     533           2 :         ])
+     534           2 :         .unwrap();
+     535           2 : 
+     536           2 :         #[rustfmt::skip]
+     537           2 :         // smoelius: Following the upgrade nightly-2023-08-24, I started seeing the following error:
+     538           2 :         //
+     539           2 :         //   error: internal compiler error: encountered incremental compilation error with shallow_lint_levels_on(dylint_internal[...]::cargo::{use#15})
+     540           2 :         //     |
+     541           2 :         //     = help: This is a known issue with the compiler. Run `cargo clean -p dylint_internal` or `cargo clean` to allow your project to compile
+     542           2 :         //     = note: Please follow the instructions below to create a bug report with the provided information
+     543           2 :         //     = note: See <https://github.com/rust-lang/rust/issues/84970> for more information
+     544           2 :         set_var(env::CARGO_INCREMENTAL, "0");
+     545           2 :         set_var(env::DYLINT_LIBRARY_PATH, dylint_library_path);
+     546           2 : 
+     547           2 :         NameToolchainMap::new(&OPTS)
+     548           2 :     }
+     549             : 
+     550             :     #[cfg_attr(dylint_lib = "general", allow(non_thread_safe_call_in_test))]
+     551             :     #[test]
+     552           1 :     fn multiple_libraries_multiple_toolchains() {
+     553           1 :         let _lock = MUTEX.lock().unwrap();
+     554           1 : 
+     555           1 :         let name_toolchain_map = name_toolchain_map();
+     556           1 : 
+     557           1 :         let inited = name_toolchain_map.get_or_try_init().unwrap();
+     558           1 : 
+     559           1 :         let question_mark_in_expression = inited.get("question_mark_in_expression").unwrap();
+     560           1 :         let straggler = inited.get("straggler").unwrap();
+     561           1 : 
+     562           1 :         assert_ne!(
+     563           1 :             question_mark_in_expression.keys().collect::<Vec<_>>(),
+     564           1 :             straggler.keys().collect::<Vec<_>>()
+     565           1 :         );
+     566             : 
+     567           1 :         let opts = opts::Dylint {
+     568           1 :             operation: opts::Operation::Check(opts::Check {
+     569           1 :                 lib_sel: opts::LibrarySelection {
+     570           1 :                     libs: vec![
+     571           1 :                         "question_mark_in_expression".to_owned(),
+     572           1 :                         "straggler".to_owned(),
+     573           1 :                     ],
+     574           1 :                     ..Default::default()
+     575           1 :                 },
+     576           1 :                 ..Default::default()
+     577           1 :             }),
+     578           1 :             ..Default::default()
+     579           1 :         };
+     580           1 : 
+     581           1 :         run_with_name_toolchain_map(&opts, &name_toolchain_map).unwrap();
+     582           1 :     }
+     583             : 
+     584             :     // smoelius: Check that loading multiple libraries with the same Rust toolchain works. At one
+     585             :     // point, I was getting this error from `libloading`:
+     586             :     //
+     587             :     //   cannot allocate memory in static TLS block
+     588             :     //
+     589             :     // The culprit turned out to be the `rand` crate, which uses a lot of thread local storage.
+     590             :     // `rand` is used by `tempfile`, which is used by various Rust compiler crates. Essentially,
+     591             :     // each library had its own copy of the Rust compiler, and therefore its own copy of the `rand`
+     592             :     // crate, and this was eating up all the thread local storage.
+     593             :     //
+     594             :     // The solution was to add `extern crate rustc_driver` to each library. This causes the library
+     595             :     // to link against `librust_driver.so`, which dylint-driver also links against. So, essentially,
+     596             :     // each library now uses dylint-driver's copy of the `rand` crate.
+     597             :     //
+     598             :     // This thread was very helpful in diagnosing the problem:
+     599             :     //
+     600             :     //   https://bugzilla.redhat.com/show_bug.cgi?id=1722181
+     601             :     //
+     602             :     #[cfg_attr(dylint_lib = "general", allow(non_thread_safe_call_in_test))]
+     603             :     #[test]
+     604           1 :     fn multiple_libraries_one_toolchain() {
+     605           1 :         let _lock = MUTEX.lock().unwrap();
+     606           1 : 
+     607           1 :         let name_toolchain_map = name_toolchain_map();
+     608           1 : 
+     609           1 :         let inited = name_toolchain_map.get_or_try_init().unwrap();
+     610           1 : 
+     611           1 :         let clippy = inited.get("clippy").unwrap();
+     612           1 :         let question_mark_in_expression = inited.get("question_mark_in_expression").unwrap();
+     613           1 : 
+     614           1 :         assert_eq!(
+     615           1 :             clippy.keys().collect::<Vec<_>>(),
+     616           1 :             question_mark_in_expression.keys().collect::<Vec<_>>()
+     617           1 :         );
+     618             : 
+     619           1 :         let opts = opts::Dylint {
+     620           1 :             operation: opts::Operation::Check(opts::Check {
+     621           1 :                 lib_sel: opts::LibrarySelection {
+     622           1 :                     libs: vec![
+     623           1 :                         "clippy".to_owned(),
+     624           1 :                         "question_mark_in_expression".to_owned(),
+     625           1 :                     ],
+     626           1 :                     ..Default::default()
+     627           1 :                 },
+     628           1 :                 ..Default::default()
+     629           1 :             }),
+     630           1 :             ..Default::default()
+     631           1 :         };
+     632           1 : 
+     633           1 :         run_with_name_toolchain_map(&opts, &name_toolchain_map).unwrap();
+     634           1 :     }
+     635             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/detailed_toml_dependency.rs.func-sort-c.html b/coverage/dylint/src/library_packages/cargo_cli/detailed_toml_dependency.rs.func-sort-c.html new file mode 100644 index 000000000..2e2233a91 --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/detailed_toml_dependency.rs.func-sort-c.html @@ -0,0 +1,172 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/detailed_toml_dependency.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli - detailed_toml_dependency.rs (source / functions)HitTotalCoverage
Test:unnamedLines:44100.0 %
Date:2024-04-23 03:30:56Functions:72528.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::expecting0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_bool::<toml::de::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_borrowed_bytes::<serde_json::error::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_borrowed_str::<serde_json::error::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_bytes::<serde_json::error::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_char::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_f32::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_f64::<toml::de::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i16::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i32::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i64::<toml::de::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i8::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u16::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u32::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u64::<serde_json::error::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u8::<serde_json::error::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_unit::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__Visitor<alloc::string::String> as serde::de::Visitor>::expecting0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__Field as serde::de::Deserialize>::deserialize::<toml::value::Value>2
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_str::<toml::de::Error>2
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__Visitor<alloc::string::String> as serde::de::Visitor>::visit_map::<&mut toml::value::MapDeserializer>2
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__Visitor<alloc::string::String> as serde::de::Visitor>::visit_map::<serde::__private::de::FlatMapAccess<serde_json::error::Error>>30
<dylint::library_packages::impl_::DetailedTomlDependency>::unused_keys32
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__Field as serde::de::Deserialize>::deserialize::<serde::__private::de::content::ContentRefDeserializer<serde_json::error::Error>>33
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_str::<serde_json::error::Error>33
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/detailed_toml_dependency.rs.func.html b/coverage/dylint/src/library_packages/cargo_cli/detailed_toml_dependency.rs.func.html new file mode 100644 index 000000000..a0409f8bf --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/detailed_toml_dependency.rs.func.html @@ -0,0 +1,172 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/detailed_toml_dependency.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli - detailed_toml_dependency.rs (source / functions)HitTotalCoverage
Test:unnamedLines:44100.0 %
Date:2024-04-23 03:30:56Functions:72528.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__Field as serde::de::Deserialize>::deserialize::<serde::__private::de::content::ContentRefDeserializer<serde_json::error::Error>>33
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__Field as serde::de::Deserialize>::deserialize::<toml::value::Value>2
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::expecting0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_bool::<toml::de::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_borrowed_bytes::<serde_json::error::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_borrowed_str::<serde_json::error::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_bytes::<serde_json::error::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_char::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_f32::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_f64::<toml::de::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i16::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i32::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i64::<toml::de::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i8::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_str::<serde_json::error::Error>33
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_str::<toml::de::Error>2
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u16::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u32::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u64::<serde_json::error::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u8::<serde_json::error::Error>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_unit::<_>0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__Visitor<alloc::string::String> as serde::de::Visitor>::expecting0
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__Visitor<alloc::string::String> as serde::de::Visitor>::visit_map::<&mut toml::value::MapDeserializer>2
<<dylint::library_packages::impl_::DetailedTomlDependency<_> as serde::de::Deserialize>::deserialize::__Visitor<alloc::string::String> as serde::de::Visitor>::visit_map::<serde::__private::de::FlatMapAccess<serde_json::error::Error>>30
<dylint::library_packages::impl_::DetailedTomlDependency>::unused_keys32
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/detailed_toml_dependency.rs.gcov.html b/coverage/dylint/src/library_packages/cargo_cli/detailed_toml_dependency.rs.gcov.html new file mode 100644 index 000000000..ca888431a --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/detailed_toml_dependency.rs.gcov.html @@ -0,0 +1,127 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/detailed_toml_dependency.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli - detailed_toml_dependency.rs (source / functions)HitTotalCoverage
Test:unnamedLines:44100.0 %
Date:2024-04-23 03:30:56Functions:72528.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use serde::{Deserialize, Serialize};
+       2             : use std::collections::BTreeMap;
+       3             : 
+       4             : // smoelius: `DetailedTomlDependency::unused_keys` does not appear in the original.
+       5             : impl DetailedTomlDependency {
+       6          32 :     pub fn unused_keys(&self) -> Vec<String> {
+       7          32 :         self.other.keys().cloned().collect()
+       8          32 :     }
+       9             : }
+      10             : 
+      11             : // smoelius: `DetailedTomlDependency` was copied from:
+      12             : // https://github.com/rust-lang/cargo/blob/e476251168fab96ae3c7544ee1a9f3ae3b7f885f/src/cargo/util/toml/mod.rs#L250-L287
+      13             : 
+      14         101 : #[derive(Deserialize, Serialize, Clone, Debug)]
+      15             : #[serde(rename_all = "kebab-case")]
+      16             : pub struct DetailedTomlDependency<P: Clone = String> {
+      17             :     version: Option<String>,
+      18             :     registry: Option<String>,
+      19             :     /// The URL of the `registry` field.
+      20             :     /// This is an internal implementation detail. When Cargo creates a
+      21             :     /// package, it replaces `registry` with `registry-index` so that the
+      22             :     /// manifest contains the correct URL. All users won't have the same
+      23             :     /// registry names configured, so Cargo can't rely on just the name for
+      24             :     /// crates published by other users.
+      25             :     registry_index: Option<String>,
+      26             :     // `path` is relative to the file it appears in. If that's a `Cargo.toml`, it'll be relative to
+      27             :     // that TOML file, and if it's a `.cargo/config` file, it'll be relative to that file.
+      28             :     path: Option<P>,
+      29             :     git: Option<String>,
+      30             :     branch: Option<String>,
+      31             :     tag: Option<String>,
+      32             :     rev: Option<String>,
+      33             :     features: Option<Vec<String>>,
+      34             :     optional: Option<bool>,
+      35             :     default_features: Option<bool>,
+      36             :     #[serde(rename = "default_features")]
+      37             :     default_features2: Option<bool>,
+      38             :     package: Option<String>,
+      39             :     public: Option<bool>,
+      40             : 
+      41             :     /// One or more of `bin`, `cdylib`, `staticlib`, `bin:<name>`.
+      42             :     artifact: Option<StringOrVec>,
+      43             :     /// If set, the artifact should also be a dependency
+      44             :     lib: Option<bool>,
+      45             :     /// A platform name, like `x86_64-apple-darwin`
+      46             :     target: Option<String>,
+      47             :     /// This is here to provide a way to see the "unused manifest keys" when deserializing
+      48             :     #[serde(skip_serializing)]
+      49             :     #[serde(flatten)]
+      50             :     other: BTreeMap<String, toml::Value>,
+      51             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/index-sort-f.html b/coverage/dylint/src/library_packages/cargo_cli/index-sort-f.html new file mode 100644 index 000000000..a66529d29 --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/index-sort-f.html @@ -0,0 +1,113 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cliHitTotalCoverage
Test:unnamedLines:22726187.0 %
Date:2024-04-23 03:30:56Functions:297339.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
string_or_vec.rs +
0.0%
+
0.0 %0 / 100.0 %0 / 6
detailed_toml_dependency.rs +
100.0%
+
100.0 %4 / 428.0 %7 / 25
mod.rs +
90.3%90.3%
+
90.3 %223 / 24752.4 %22 / 42
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/index-sort-l.html b/coverage/dylint/src/library_packages/cargo_cli/index-sort-l.html new file mode 100644 index 000000000..c2bb15daa --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/index-sort-l.html @@ -0,0 +1,113 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cliHitTotalCoverage
Test:unnamedLines:22726187.0 %
Date:2024-04-23 03:30:56Functions:297339.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
string_or_vec.rs +
0.0%
+
0.0 %0 / 100.0 %0 / 6
mod.rs +
90.3%90.3%
+
90.3 %223 / 24752.4 %22 / 42
detailed_toml_dependency.rs +
100.0%
+
100.0 %4 / 428.0 %7 / 25
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/index.html b/coverage/dylint/src/library_packages/cargo_cli/index.html new file mode 100644 index 000000000..b3bd85829 --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/index.html @@ -0,0 +1,113 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cliHitTotalCoverage
Test:unnamedLines:22726187.0 %
Date:2024-04-23 03:30:56Functions:297339.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
detailed_toml_dependency.rs +
100.0%
+
100.0 %4 / 428.0 %7 / 25
mod.rs +
90.3%90.3%
+
90.3 %223 / 24752.4 %22 / 42
string_or_vec.rs +
0.0%
+
0.0 %0 / 100.0 %0 / 6
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/mod.rs.func-sort-c.html b/coverage/dylint/src/library_packages/cargo_cli/mod.rs.func-sort-c.html new file mode 100644 index 000000000..31f04ac8d --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/mod.rs.func-sort-c.html @@ -0,0 +1,240 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/mod.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli - mod.rs (source / functions)HitTotalCoverage
Test:unnamedLines:22324790.3 %
Date:2024-04-23 03:30:56Functions:224252.4 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint::library_packages::impl_::create_dummy_dependency::{closure#0}0
dylint::library_packages::impl_::create_dummy_package::{closure#0}0
dylint::library_packages::impl_::create_dummy_package::{closure#1}0
dylint::library_packages::impl_::create_dummy_package::{closure#2}0
dylint::library_packages::impl_::create_dummy_package::{closure#3}0
dylint::library_packages::impl_::dummy_dependency_free_suffix0
dylint::library_packages::impl_::dummy_dependency_free_suffix::{closure#0}0
dylint::library_packages::impl_::find_accessed_subdir::{closure#1}::{closure#0}0
dylint::library_packages::impl_::find_accessed_subdir::{closure#1}::{closure#1}0
dylint::library_packages::impl_::find_accessed_subdir::{closure#3}0
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::find_accessed_subdir::{closure#2}>::{closure#0}0
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::find_accessed_subdir::{closure#2}>::{closure#1}0
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::find_accessed_subdir::{closure#2}>::{closure#2}0
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::inject_dummy_dependencies::{closure#0}>::{closure#0}0
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::inject_dummy_dependencies::{closure#0}>::{closure#1}0
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::inject_dummy_dependencies::{closure#0}>::{closure#2}0
dylint::library_packages::impl_::git_dependency_root::{closure#0}0
dylint::library_packages::impl_::git_dependency_root::{closure#1}0
dylint::library_packages::impl_::git_dependency_root::{closure#2}0
dylint::library_packages::impl_::git_dependency_root::{closure#3}0
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::find_accessed_subdir::{closure#2}>2
dylint::library_packages::impl_::find_accessed_subdir::{closure#2}3
dylint::library_packages::impl_::find_accessed_subdir::{closure#0}7
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::inject_dummy_dependencies::{closure#0}>8
dylint::library_packages::impl_::inject_dummy_dependencies8
dylint::library_packages::impl_::cargo_fetch9
dylint::library_packages::impl_::cargo_metadata9
dylint::library_packages::impl_::create_dummy_dependency9
dylint::library_packages::impl_::create_dummy_package9
dylint::library_packages::impl_::find_accessed_subdir9
dylint::library_packages::impl_::git_dependency_root9
dylint::library_packages::impl_::git_source_id9
dylint::library_packages::impl_::ident9
dylint::library_packages::impl_::ident::{closure#0}9
dylint::library_packages::impl_::manifest_contents9
dylint::library_packages::impl_::find_accessed_subdir::{closure#1}14
<dylint::library_packages::impl_::NamedTempDir as core::ops::drop::Drop>::drop15
dylint::library_packages::impl_::inject_dummy_dependencies::{closure#0}15
<dylint::library_packages::impl_::PackageId>::name20
<dylint::library_packages::impl_::Config>::default25
<dylint::library_packages::impl_::PackageId>::new27
dylint::library_packages::impl_::dependency_source_id_and_root31
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/mod.rs.func.html b/coverage/dylint/src/library_packages/cargo_cli/mod.rs.func.html new file mode 100644 index 000000000..3b09bda69 --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/mod.rs.func.html @@ -0,0 +1,240 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/mod.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli - mod.rs (source / functions)HitTotalCoverage
Test:unnamedLines:22324790.3 %
Date:2024-04-23 03:30:56Functions:224252.4 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::library_packages::impl_::Config>::default25
<dylint::library_packages::impl_::NamedTempDir as core::ops::drop::Drop>::drop15
<dylint::library_packages::impl_::PackageId>::name20
<dylint::library_packages::impl_::PackageId>::new27
dylint::library_packages::impl_::cargo_fetch9
dylint::library_packages::impl_::cargo_metadata9
dylint::library_packages::impl_::create_dummy_dependency9
dylint::library_packages::impl_::create_dummy_dependency::{closure#0}0
dylint::library_packages::impl_::create_dummy_package9
dylint::library_packages::impl_::create_dummy_package::{closure#0}0
dylint::library_packages::impl_::create_dummy_package::{closure#1}0
dylint::library_packages::impl_::create_dummy_package::{closure#2}0
dylint::library_packages::impl_::create_dummy_package::{closure#3}0
dylint::library_packages::impl_::dependency_source_id_and_root31
dylint::library_packages::impl_::dummy_dependency_free_suffix0
dylint::library_packages::impl_::dummy_dependency_free_suffix::{closure#0}0
dylint::library_packages::impl_::find_accessed_subdir9
dylint::library_packages::impl_::find_accessed_subdir::{closure#0}7
dylint::library_packages::impl_::find_accessed_subdir::{closure#1}14
dylint::library_packages::impl_::find_accessed_subdir::{closure#1}::{closure#0}0
dylint::library_packages::impl_::find_accessed_subdir::{closure#1}::{closure#1}0
dylint::library_packages::impl_::find_accessed_subdir::{closure#2}3
dylint::library_packages::impl_::find_accessed_subdir::{closure#3}0
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::find_accessed_subdir::{closure#2}>2
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::find_accessed_subdir::{closure#2}>::{closure#0}0
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::find_accessed_subdir::{closure#2}>::{closure#1}0
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::find_accessed_subdir::{closure#2}>::{closure#2}0
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::inject_dummy_dependencies::{closure#0}>8
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::inject_dummy_dependencies::{closure#0}>::{closure#0}0
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::inject_dummy_dependencies::{closure#0}>::{closure#1}0
dylint::library_packages::impl_::for_each_subdir::<dylint::library_packages::impl_::inject_dummy_dependencies::{closure#0}>::{closure#2}0
dylint::library_packages::impl_::git_dependency_root9
dylint::library_packages::impl_::git_dependency_root::{closure#0}0
dylint::library_packages::impl_::git_dependency_root::{closure#1}0
dylint::library_packages::impl_::git_dependency_root::{closure#2}0
dylint::library_packages::impl_::git_dependency_root::{closure#3}0
dylint::library_packages::impl_::git_source_id9
dylint::library_packages::impl_::ident9
dylint::library_packages::impl_::ident::{closure#0}9
dylint::library_packages::impl_::inject_dummy_dependencies8
dylint::library_packages::impl_::inject_dummy_dependencies::{closure#0}15
dylint::library_packages::impl_::manifest_contents9
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/mod.rs.gcov.html b/coverage/dylint/src/library_packages/cargo_cli/mod.rs.gcov.html new file mode 100644 index 000000000..e07226c63 --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/mod.rs.gcov.html @@ -0,0 +1,459 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/mod.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli - mod.rs (source / functions)HitTotalCoverage
Test:unnamedLines:22324790.3 %
Date:2024-04-23 03:30:56Functions:224252.4 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : //! This module borrows an idea from [Marker]: to use `cargo fetch` to download a package into
+       2             : //! Cargo's cache. More specifically, this module creates a "dummy" project with a specified package
+       3             : //! as a dependency, and then calls `cargo fetch` to download the project's dependencies into
+       4             : //! Cargo's cache.
+       5             : //!
+       6             : //! There is a complication, however. Dylint does not require a workspace metadata entry to specify
+       7             : //! a lint library's package name. But the above idea, as applied in Marker, requires the package
+       8             : //! name.
+       9             : //!
+      10             : //! To work around this problem, this module creates a "dummy" dependency with a random name and
+      11             : //! "injects" it into each subdirectory of the relevant checkouts directory. If Cargo finds the
+      12             : //! dummy dependency in one of those subdirectories, then that subdirectory must have been updated
+      13             : //! by `cargo fetch`. On the other hand, if Cargo finds the dummy dependency in a completely new
+      14             : //! subdirectory, then that subdirectory must have been created by `cargo fetch`.
+      15             : //!
+      16             : //! [Marker]: https://github.com/rust-marker/marker
+      17             : 
+      18             : use crate::opts;
+      19             : use anyhow::{anyhow, bail, ensure, Context, Result};
+      20             : use cargo_metadata::{Metadata, MetadataCommand};
+      21             : use dylint_internal::{packaging::isolate, CommandExt};
+      22             : use home::cargo_home;
+      23             : use semver::Version;
+      24             : use std::{
+      25             :     borrow::Cow,
+      26             :     ffi::{OsStr, OsString},
+      27             :     fs::{create_dir_all, read_dir, remove_dir_all, write},
+      28             :     path::{Path, PathBuf},
+      29             :     process::{Output, Stdio},
+      30             : };
+      31             : use tempfile::{tempdir, Builder, TempDir};
+      32             : use url::Url;
+      33             : 
+      34             : mod string_or_vec;
+      35             : use string_or_vec::StringOrVec;
+      36             : 
+      37             : mod util;
+      38             : use util::{short_hash, CanonicalUrl};
+      39             : 
+      40             : struct NamedTempDir(PathBuf);
+      41             : 
+      42             : impl Drop for NamedTempDir {
+      43          15 :     fn drop(&mut self) {
+      44          15 :         remove_dir_all(&self.0).unwrap_or_default();
+      45          15 :     }
+      46             : }
+      47             : 
+      48             : // smoelius: Use `include!` so that `DetailedTomlDependency`'s fields are visible without having to
+      49             : // make them all `pub`.
+      50             : include!("detailed_toml_dependency.rs");
+      51             : 
+      52             : pub struct Config;
+      53             : 
+      54             : #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
+      55             : pub struct PackageId {
+      56             :     name: String,
+      57             :     version: Version,
+      58             :     source_id: String,
+      59             : }
+      60             : 
+      61             : pub type SourceId = String;
+      62             : 
+      63             : impl Config {
+      64             :     #[allow(clippy::unnecessary_wraps)]
+      65          25 :     pub const fn default() -> Result<Self> {
+      66          25 :         Ok(Self)
+      67          25 :     }
+      68             : }
+      69             : 
+      70             : impl PackageId {
+      71             :     #[allow(clippy::unnecessary_wraps)]
+      72          27 :     pub const fn new(name: String, version: Version, source_id: SourceId) -> Result<Self> {
+      73          27 :         Ok(Self {
+      74          27 :             name,
+      75          27 :             version,
+      76          27 :             source_id,
+      77          27 :         })
+      78          27 :     }
+      79             : 
+      80          20 :     pub fn name(&self) -> &str {
+      81          20 :         &self.name
+      82          20 :     }
+      83             : }
+      84             : 
+      85          31 : pub fn dependency_source_id_and_root(
+      86          31 :     _opts: &opts::Dylint,
+      87          31 :     metadata: &Metadata,
+      88          31 :     _config: &Config,
+      89          31 :     details: &DetailedTomlDependency,
+      90          31 : ) -> Result<(SourceId, PathBuf)> {
+      91          31 :     if let Some(url) = &details.git {
+      92           9 :         ensure!(
+      93           9 :             details.path.is_none(),
+      94           0 :             "A dependency cannot have both git and path entries"
+      95             :         );
+      96           9 :         let source_id = git_source_id(url, details)?;
+      97           9 :         let root = git_dependency_root(url, details)?;
+      98           9 :         Ok((source_id, root))
+      99          22 :     } else if let Some(path) = &details.path {
+     100          22 :         let source_id = String::new();
+     101          22 :         let root = metadata
+     102          22 :             .workspace_root
+     103          22 :             .join(path)
+     104          22 :             .as_std_path()
+     105          22 :             .to_path_buf();
+     106          22 :         Ok((source_id, root))
+     107             :     } else {
+     108           0 :         bail!("Only git and path entries are supported")
+     109             :     }
+     110          31 : }
+     111             : 
+     112           9 : fn git_source_id(url: &str, details: &DetailedTomlDependency) -> Result<String> {
+     113             :     #[derive(Serialize)]
+     114             :     struct GitReference<'a> {
+     115             :         url: &'a str,
+     116             :         branch: Option<&'a str>,
+     117             :         tag: Option<&'a str>,
+     118             :         rev: Option<&'a str>,
+     119             :     }
+     120           9 :     let json = serde_json::to_string(&GitReference {
+     121           9 :         url,
+     122           9 :         branch: details.branch.as_deref(),
+     123           9 :         tag: details.tag.as_deref(),
+     124           9 :         rev: details.rev.as_deref(),
+     125           9 :     })?;
+     126           9 :     Ok(json)
+     127           9 : }
+     128             : 
+     129           9 : fn git_dependency_root(url: &str, details: &DetailedTomlDependency) -> Result<PathBuf> {
+     130           9 :     let dependency = create_dummy_dependency()?;
+     131           9 :     let filename = dependency
+     132           9 :         .path()
+     133           9 :         .file_name()
+     134           9 :         .ok_or_else(|| anyhow!("Could not get file name"))?;
+     135           9 :     let dep_name = filename.to_string_lossy();
+     136             : 
+     137           9 :     let package = create_dummy_package(&dep_name, details)?;
+     138             : 
+     139           9 :     let cargo_home = cargo_home().with_context(|| "Could not determine `CARGO_HOME`")?;
+     140           9 :     let ident = ident(url)?;
+     141           9 :     let checkout_path = cargo_home.join("git/checkouts").join(ident);
+     142             : 
+     143             :     // smoelius: `checkout_path` might not exist, e.g., if the url has never been cloned.
+     144           9 :     let injected_dependencies = if checkout_path
+     145           9 :         .try_exists()
+     146           9 :         .with_context(|| format!("Could not determine whether {checkout_path:?} exists"))?
+     147             :     {
+     148           8 :         inject_dummy_dependencies(dependency.path(), &dep_name, &checkout_path)?
+     149             :     } else {
+     150           1 :         BTreeMap::new()
+     151             :     };
+     152             : 
+     153           9 :     let output = cargo_fetch(package.path())?;
+     154             : 
+     155             :     // smoelius: `cargo metadata` will fail if `cargo fetch` had to create a new checkouts
+     156             :     // subdirectory.
+     157           9 :     let metadata = cargo_metadata(package.path()).ok();
+     158             : 
+     159           9 :     let path = match (
+     160           9 :         find_accessed_subdir(
+     161           9 :             &dep_name,
+     162           9 :             &checkout_path,
+     163           9 :             &injected_dependencies,
+     164           9 :             metadata.as_ref(),
+     165           9 :         ),
+     166           9 :         output.status.success(),
+     167           9 :     ) {
+     168           9 :         (Ok(path), _) => Ok(path),
+     169           0 :         (Err(err), true) => Err(err),
+     170           0 :         (Err(err), false) => Err(err).with_context(|| {
+     171           0 :             format!(
+     172           0 :                 "fetching packages failed\nstdout: {:?}\nstderr: {:?}",
+     173           0 :                 String::from_utf8(output.stdout).unwrap_or_default(),
+     174           0 :                 dummy_dependency_free_suffix(
+     175           0 :                     &dep_name,
+     176           0 :                     &String::from_utf8(output.stderr).unwrap_or_default()
+     177           0 :                 )
+     178           0 :             )
+     179           0 :         }),
+     180           0 :     }?;
+     181             : 
+     182           9 :     Ok(path.to_path_buf())
+     183           9 : }
+     184             : 
+     185             : /// Creates a dummy dependency in a temporary directory, and returns the temporary directory if
+     186             : /// everything was successful.
+     187           9 : fn create_dummy_dependency() -> Result<TempDir> {
+     188           9 :     let tempdir = Builder::new()
+     189           9 :         .prefix("tmp")
+     190           9 :         .tempdir()
+     191           9 :         .with_context(|| "Could not create temporary directory")?;
+     192             : 
+     193           9 :     dylint_internal::cargo::init("dummy dependency")
+     194           9 :         .quiet(true)
+     195           9 :         .stable(true)
+     196           9 :         .build()
+     197           9 :         .current_dir(&tempdir)
+     198           9 :         .args(["--lib", "--vcs=none"])
+     199           9 :         .success()?;
+     200             : 
+     201           9 :     isolate(tempdir.path())?;
+     202             : 
+     203           9 :     Ok(tempdir)
+     204           9 : }
+     205             : 
+     206             : /// Creates a dummy package in a temporary directory, and returns the temporary directory if
+     207             : /// everything was successful.
+     208           9 : fn create_dummy_package(dep_name: &str, details: &DetailedTomlDependency) -> Result<TempDir> {
+     209           9 :     let tempdir = tempdir().with_context(|| "Could not create temporary directory")?;
+     210             : 
+     211           9 :     let manifest_contents = manifest_contents(dep_name, details)?;
+     212           9 :     let manifest_path = tempdir.path().join("Cargo.toml");
+     213           9 :     write(&manifest_path, manifest_contents)
+     214           9 :         .with_context(|| format!("Could not write to {manifest_path:?}"))?;
+     215             : 
+     216           9 :     let src_path = tempdir.path().join("src");
+     217           9 : 
+     218           9 :     create_dir_all(&src_path)
+     219           9 :         .with_context(|| format!("`create_dir_all` failed for `{src_path:?}`"))?;
+     220             : 
+     221           9 :     let main_rs_path = src_path.join("main.rs");
+     222           9 :     write(&main_rs_path, "fn main() {}")
+     223           9 :         .with_context(|| format!("Could not write to {main_rs_path:?}"))?;
+     224             : 
+     225           9 :     Ok(tempdir)
+     226           9 : }
+     227             : 
+     228           9 : fn manifest_contents(dep_name: &str, details: &DetailedTomlDependency) -> Result<String> {
+     229           9 :     let details = toml::to_string(details)?;
+     230             : 
+     231           9 :     Ok(format!(
+     232           9 :         r#"
+     233           9 : [package]
+     234           9 : name = "dummy-package"
+     235           9 : version = "0.1.0"
+     236           9 : edition = "2021"
+     237           9 : publish = false
+     238           9 : 
+     239           9 : [dependencies.{dep_name}]
+     240           9 : {details}
+     241           9 : "#
+     242           9 :     ))
+     243           9 : }
+     244             : 
+     245           8 : fn inject_dummy_dependencies(
+     246           8 :     dep_path: &Path,
+     247           8 :     dep_name: &str,
+     248           8 :     checkout_path: &Path,
+     249           8 : ) -> Result<BTreeMap<OsString, NamedTempDir>> {
+     250           8 :     let mut injected_dependencies = BTreeMap::new();
+     251           8 :     #[cfg_attr(dylint_lib = "general", allow(non_local_effect_before_error_return))]
+     252          15 :     for_each_subdir(checkout_path, |subdir, path| {
+     253          15 :         injected_dependencies.insert(subdir.to_owned(), NamedTempDir(path.join(dep_name)));
+     254          15 :         fs_extra::dir::copy(dep_path, path, &fs_extra::dir::CopyOptions::default())?;
+     255          15 :         Ok(())
+     256          15 :     })?;
+     257           8 :     Ok(injected_dependencies)
+     258           8 : }
+     259             : 
+     260           9 : fn cargo_fetch(path: &Path) -> Result<Output> {
+     261           9 :     // smoelius: `cargo fetch` could fail, e.g., if a new checkouts subdirectory had to be created.
+     262           9 :     // But the command should still be executed.
+     263           9 :     // smoelius: Since stdout and stderr are captured, there is no need to use `.quiet(true)`.
+     264           9 :     // smoelius: We still want to hide the "Fetching ..." message, though.
+     265           9 :     dylint_internal::cargo::fetch("dummy package")
+     266           9 :         .quiet(dylint_internal::cargo::Quiet::MESSAGE)
+     267           9 :         .stable(true)
+     268           9 :         .build()
+     269           9 :         .args([
+     270           9 :             "--manifest-path",
+     271           9 :             &path.join("Cargo.toml").to_string_lossy(),
+     272           9 :         ])
+     273           9 :         .stdout(Stdio::piped())
+     274           9 :         .stderr(Stdio::piped())
+     275           9 :         .logged_output(false)
+     276           9 : }
+     277             : 
+     278           9 : fn cargo_metadata(path: &Path) -> Result<Metadata> {
+     279           9 :     MetadataCommand::new()
+     280           9 :         .current_dir(path)
+     281           9 :         .exec()
+     282           9 :         .map_err(Into::into)
+     283           9 : }
+     284             : 
+     285             : // smoelius: `ident` is based on the function of the same name at:
+     286             : // https://github.com/rust-lang/cargo/blob/1a498b6c1c119a79d677553862bffae96b97ad7f/src/cargo/sources/git/source.rs#L136-L147
+     287             : #[allow(clippy::manual_next_back)]
+     288             : #[cfg_attr(dylint_lib = "overscoped_allow", allow(overscoped_allow))]
+     289           9 : fn ident(url: &str) -> Result<String> {
+     290           9 :     let url = Url::parse(url)?;
+     291             : 
+     292           9 :     let canonical_url = CanonicalUrl::new(&url)?;
+     293             : 
+     294           9 :     let ident = canonical_url
+     295           9 :         .raw_canonicalized_url()
+     296           9 :         .path_segments()
+     297           9 :         .and_then(|s| s.rev().next())
+     298           9 :         .unwrap_or("");
+     299             : 
+     300           9 :     let ident = if ident.is_empty() { "_empty" } else { ident };
+     301             : 
+     302           9 :     Ok(format!("{}-{}", ident, short_hash(&canonical_url)))
+     303           9 : }
+     304             : 
+     305           9 : fn find_accessed_subdir<'a>(
+     306           9 :     dep_name: &str,
+     307           9 :     checkout_path: &Path,
+     308           9 :     injected_dependencies: &BTreeMap<OsString, NamedTempDir>,
+     309           9 :     metadata: Option<&'a Metadata>,
+     310           9 : ) -> Result<Cow<'a, Path>> {
+     311           9 :     let mut accessed = metadata
+     312           9 :         .map_or::<&[_], _>(&[], |metadata| &metadata.packages)
+     313           9 :         .iter()
+     314          14 :         .map(|package| {
+     315          14 :             if package.name == dep_name {
+     316           7 :                 let parent = package
+     317           7 :                     .manifest_path
+     318           7 :                     .parent()
+     319           7 :                     .ok_or_else(|| anyhow!("Could not get parent directory"))?;
+     320           7 :                 let grandparent = parent
+     321           7 :                     .parent()
+     322           7 :                     .ok_or_else(|| anyhow!("Could not get grandparent directory"))?;
+     323           7 :                 Ok(Some(Cow::Borrowed(grandparent.as_std_path())))
+     324             :             } else {
+     325           7 :                 Ok(None)
+     326             :             }
+     327          14 :         })
+     328           9 :         .filter_map(Result::transpose)
+     329           9 :         .collect::<Result<Vec<_>>>()?;
+     330             : 
+     331             :     // smoelius: If no subdirectories were accessed, then some checkouts subdirectory should have
+     332             :     // been created.
+     333           9 :     if accessed.is_empty() {
+     334           3 :         for_each_subdir(checkout_path, |subdir, path| {
+     335           3 :             if injected_dependencies.get(subdir).is_none() {
+     336           2 :                 accessed.push(Cow::Owned(path.to_path_buf()));
+     337           2 :             }
+     338           3 :             Ok(())
+     339           3 :         })?;
+     340           7 :     }
+     341             : 
+     342           9 :     ensure!(
+     343           9 :         accessed.len() <= 1,
+     344           0 :         "Multiple subdirectories were accessed: {:#?}",
+     345             :         accessed
+     346             :     );
+     347             : 
+     348           9 :     accessed
+     349           9 :         .into_iter()
+     350           9 :         .next()
+     351           9 :         .ok_or_else(|| anyhow!("Could not determined accessed subdirectory"))
+     352           9 : }
+     353             : 
+     354          10 : fn for_each_subdir(
+     355          10 :     checkout_path: &Path,
+     356          10 :     mut f: impl FnMut(&OsStr, &Path) -> Result<()>,
+     357          10 : ) -> Result<()> {
+     358          18 :     for entry in read_dir(checkout_path)
+     359          10 :         .with_context(|| format!("`read_dir` failed for {checkout_path:?}"))?
+     360             :     {
+     361          18 :         let entry = entry.with_context(|| format!("`read_dir` failed for {checkout_path:?}"))?;
+     362          18 :         let path = entry.path();
+     363          18 :         let file_name = path
+     364          18 :             .file_name()
+     365          18 :             .ok_or_else(|| anyhow!("Could not get file name"))?;
+     366          18 :         if !path.is_dir() {
+     367           0 :             continue;
+     368          18 :         }
+     369          18 :         f(file_name, &path)?;
+     370             :     }
+     371          10 :     Ok(())
+     372          10 : }
+     373             : 
+     374           0 : fn dummy_dependency_free_suffix(dep_name: &str, s: &str) -> String {
+     375           0 :     // smoelius: The `{..}` are a hack to prevent triggering `misleading_variable_name`.
+     376           0 :     let lines = { s.split_inclusive('\n') };
+     377           0 :     if let Some(i) = lines.clone().rev().position(|line| line.contains(dep_name)) {
+     378           0 :         let n = lines.clone().count();
+     379           0 :         lines.skip(n - i).collect()
+     380             :     } else {
+     381           0 :         s.to_owned()
+     382             :     }
+     383           0 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/string_or_vec.rs.func-sort-c.html b/coverage/dylint/src/library_packages/cargo_cli/string_or_vec.rs.func-sort-c.html new file mode 100644 index 000000000..d1a9135bf --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/string_or_vec.rs.func-sort-c.html @@ -0,0 +1,96 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/string_or_vec.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli - string_or_vec.rs (source / functions)HitTotalCoverage
Test:unnamedLines:0100.0 %
Date:2024-04-23 03:30:56Functions:060.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::library_packages::impl_::string_or_vec::StringOrVec as serde::de::Deserialize>::deserialize::<serde::__private::de::content::ContentRefDeserializer<serde_json::error::Error>>0
<dylint::library_packages::impl_::string_or_vec::StringOrVec as serde::de::Deserialize>::deserialize::<serde::__private::de::content::ContentRefDeserializer<serde_json::error::Error>>::{closure#0}0
<dylint::library_packages::impl_::string_or_vec::StringOrVec as serde::de::Deserialize>::deserialize::<serde::__private::de::content::ContentRefDeserializer<serde_json::error::Error>>::{closure#1}0
<dylint::library_packages::impl_::string_or_vec::StringOrVec as serde::de::Deserialize>::deserialize::<toml::value::Value>0
<dylint::library_packages::impl_::string_or_vec::StringOrVec as serde::de::Deserialize>::deserialize::<toml::value::Value>::{closure#0}0
<dylint::library_packages::impl_::string_or_vec::StringOrVec as serde::de::Deserialize>::deserialize::<toml::value::Value>::{closure#1}0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/string_or_vec.rs.func.html b/coverage/dylint/src/library_packages/cargo_cli/string_or_vec.rs.func.html new file mode 100644 index 000000000..54f5e391c --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/string_or_vec.rs.func.html @@ -0,0 +1,96 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/string_or_vec.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli - string_or_vec.rs (source / functions)HitTotalCoverage
Test:unnamedLines:0100.0 %
Date:2024-04-23 03:30:56Functions:060.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::library_packages::impl_::string_or_vec::StringOrVec as serde::de::Deserialize>::deserialize::<serde::__private::de::content::ContentRefDeserializer<serde_json::error::Error>>0
<dylint::library_packages::impl_::string_or_vec::StringOrVec as serde::de::Deserialize>::deserialize::<serde::__private::de::content::ContentRefDeserializer<serde_json::error::Error>>::{closure#0}0
<dylint::library_packages::impl_::string_or_vec::StringOrVec as serde::de::Deserialize>::deserialize::<serde::__private::de::content::ContentRefDeserializer<serde_json::error::Error>>::{closure#1}0
<dylint::library_packages::impl_::string_or_vec::StringOrVec as serde::de::Deserialize>::deserialize::<toml::value::Value>0
<dylint::library_packages::impl_::string_or_vec::StringOrVec as serde::de::Deserialize>::deserialize::<toml::value::Value>::{closure#0}0
<dylint::library_packages::impl_::string_or_vec::StringOrVec as serde::de::Deserialize>::deserialize::<toml::value::Value>::{closure#1}0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/string_or_vec.rs.gcov.html b/coverage/dylint/src/library_packages/cargo_cli/string_or_vec.rs.gcov.html new file mode 100644 index 000000000..491546a7c --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/string_or_vec.rs.gcov.html @@ -0,0 +1,106 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/string_or_vec.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli - string_or_vec.rs (source / functions)HitTotalCoverage
Test:unnamedLines:0100.0 %
Date:2024-04-23 03:30:56Functions:060.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : #![allow(clippy::doc_markdown, clippy::use_self)]
+       2             : #![cfg_attr(
+       3             :     dylint_lib = "inconsistent_qualification",
+       4             :     allow(inconsistent_qualification)
+       5             : )]
+       6             : #![cfg_attr(dylint_lib = "overscoped_allow", allow(overscoped_allow))]
+       7             : 
+       8             : use serde::{de, Serialize};
+       9             : use serde_untagged::UntaggedEnumVisitor;
+      10             : 
+      11             : // smoelius: `StringOrVec` was copied from:
+      12             : // https://github.com/rust-lang/cargo/blob/e476251168fab96ae3c7544ee1a9f3ae3b7f885f/src/cargo/util/toml/mod.rs#L871-L887
+      13             : 
+      14             : /// A StringOrVec can be parsed from either a TOML string or array,
+      15             : /// but is always stored as a vector.
+      16             : #[derive(Clone, Debug, Serialize, Eq, PartialEq, PartialOrd, Ord)]
+      17             : pub struct StringOrVec(Vec<String>);
+      18             : 
+      19             : impl<'de> de::Deserialize<'de> for StringOrVec {
+      20           0 :     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+      21           0 :     where
+      22           0 :         D: de::Deserializer<'de>,
+      23           0 :     {
+      24           0 :         UntaggedEnumVisitor::new()
+      25           0 :             .expecting("string or list of strings")
+      26           0 :             .string(|value| Ok(StringOrVec(vec![value.to_owned()])))
+      27           0 :             .seq(|value| value.deserialize().map(StringOrVec))
+      28           0 :             .deserialize(deserializer)
+      29           0 :     }
+      30             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/util/canonical_url.rs.func-sort-c.html b/coverage/dylint/src/library_packages/cargo_cli/util/canonical_url.rs.func-sort-c.html new file mode 100644 index 000000000..f2630ed12 --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/util/canonical_url.rs.func-sort-c.html @@ -0,0 +1,84 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/util/canonical_url.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli/util - canonical_url.rs (source / functions)HitTotalCoverage
Test:unnamedLines:293974.4 %
Date:2024-04-23 03:30:56Functions:33100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::library_packages::impl_::util::canonical_url::CanonicalUrl as core::hash::Hash>::hash::<core::hash::sip::SipHasher>9
<dylint::library_packages::impl_::util::canonical_url::CanonicalUrl>::new9
<dylint::library_packages::impl_::util::canonical_url::CanonicalUrl>::raw_canonicalized_url9
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/util/canonical_url.rs.func.html b/coverage/dylint/src/library_packages/cargo_cli/util/canonical_url.rs.func.html new file mode 100644 index 000000000..580fed5c5 --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/util/canonical_url.rs.func.html @@ -0,0 +1,84 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/util/canonical_url.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli/util - canonical_url.rs (source / functions)HitTotalCoverage
Test:unnamedLines:293974.4 %
Date:2024-04-23 03:30:56Functions:33100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::library_packages::impl_::util::canonical_url::CanonicalUrl as core::hash::Hash>::hash::<core::hash::sip::SipHasher>9
<dylint::library_packages::impl_::util::canonical_url::CanonicalUrl>::new9
<dylint::library_packages::impl_::util::canonical_url::CanonicalUrl>::raw_canonicalized_url9
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/util/canonical_url.rs.gcov.html b/coverage/dylint/src/library_packages/cargo_cli/util/canonical_url.rs.gcov.html new file mode 100644 index 000000000..b69a20f73 --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/util/canonical_url.rs.gcov.html @@ -0,0 +1,168 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/util/canonical_url.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli/util - canonical_url.rs (source / functions)HitTotalCoverage
Test:unnamedLines:293974.4 %
Date:2024-04-23 03:30:56Functions:33100.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : // smoelius: This file is a slight modification of:
+       2             : // https://github.com/rust-lang/cargo/blob/16ad1f2945dff5c7f3234257d5ab477ea86b7338/src/cargo/util/canonical_url.rs
+       3             : 
+       4             : #![allow(
+       5             :     clippy::case_sensitive_file_extension_comparisons,
+       6             :     clippy::missing_const_for_fn,
+       7             :     clippy::use_self,
+       8             :     clippy::unwrap_used
+       9             : )]
+      10             : #![cfg_attr(dylint_lib = "collapsible_unwrap", allow(collapsible_unwrap))]
+      11             : #![cfg_attr(
+      12             :     dylint_lib = "inconsistent_qualification",
+      13             :     allow(inconsistent_qualification)
+      14             : )]
+      15             : #![cfg_attr(dylint_lib = "overscoped_allow", allow(overscoped_allow))]
+      16             : 
+      17             : use anyhow::Result as CargoResult;
+      18             : 
+      19             : use std::hash::{self, Hash};
+      20             : use url::Url;
+      21             : 
+      22             : /// A newtype wrapper around `Url` which represents a "canonical" version of an
+      23             : /// original URL.
+      24             : ///
+      25             : /// A "canonical" url is only intended for internal comparison purposes in
+      26             : /// Cargo. It's to help paper over mistakes such as depending on
+      27             : /// `github.com/foo/bar` vs `github.com/foo/bar.git`. This is **only** for
+      28             : /// internal purposes within Cargo and provides no means to actually read the
+      29             : /// underlying string value of the `Url` it contains. This is intentional,
+      30             : /// because all fetching should still happen within the context of the original
+      31             : /// URL.
+      32             : #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
+      33             : pub struct CanonicalUrl(Url);
+      34             : 
+      35             : impl CanonicalUrl {
+      36           9 :     pub fn new(url: &Url) -> CargoResult<CanonicalUrl> {
+      37           9 :         let mut url = url.clone();
+      38           9 : 
+      39           9 :         // cannot-be-a-base-urls (e.g., `github.com:rust-lang/rustfmt.git`)
+      40           9 :         // are not supported.
+      41           9 :         if url.cannot_be_a_base() {
+      42           0 :             anyhow::bail!(
+      43           0 :                 "invalid url `{}`: cannot-be-a-base-URLs are not supported",
+      44           0 :                 url
+      45           0 :             )
+      46           9 :         }
+      47           9 : 
+      48           9 :         // Strip a trailing slash.
+      49           9 :         if url.path().ends_with('/') {
+      50           0 :             url.path_segments_mut().unwrap().pop_if_empty();
+      51           9 :         }
+      52             : 
+      53             :         // For GitHub URLs specifically, just lower-case everything. GitHub
+      54             :         // treats both the same, but they hash differently, and we're gonna be
+      55             :         // hashing them. This wants a more general solution, and also we're
+      56             :         // almost certainly not using the same case conversion rules that GitHub
+      57             :         // does. (See issue #84)
+      58           9 :         if url.host_str() == Some("github.com") {
+      59           9 :             url = format!("https{}", &url[url::Position::AfterScheme..])
+      60           9 :                 .parse()
+      61           9 :                 .unwrap();
+      62           9 :             let path = url.path().to_lowercase();
+      63           9 :             url.set_path(&path);
+      64           9 :         }
+      65             : 
+      66             :         // Repos can generally be accessed with or without `.git` extension.
+      67           9 :         let needs_chopping = url.path().ends_with(".git");
+      68           9 :         if needs_chopping {
+      69           0 :             let last = {
+      70           0 :                 let last = url.path_segments().unwrap().next_back().unwrap();
+      71           0 :                 last[..last.len() - 4].to_owned()
+      72           0 :             };
+      73           0 :             url.path_segments_mut().unwrap().pop().push(&last);
+      74           9 :         }
+      75             : 
+      76           9 :         Ok(CanonicalUrl(url))
+      77           9 :     }
+      78             : 
+      79             :     /// Returns the raw canonicalized URL, although beware that this should
+      80             :     /// never be used/displayed/etc, it should only be used for internal data
+      81             :     /// structures and hashes and such.
+      82           9 :     pub fn raw_canonicalized_url(&self) -> &Url {
+      83           9 :         &self.0
+      84           9 :     }
+      85             : }
+      86             : 
+      87             : // See comment in `source_id.rs` for why we explicitly use `as_str()` here.
+      88             : impl Hash for CanonicalUrl {
+      89           9 :     fn hash<S: hash::Hasher>(&self, into: &mut S) {
+      90           9 :         self.0.as_str().hash(into);
+      91           9 :     }
+      92             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/util/hex.rs.func-sort-c.html b/coverage/dylint/src/library_packages/cargo_cli/util/hex.rs.func-sort-c.html new file mode 100644 index 000000000..347d1db56 --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/util/hex.rs.func-sort-c.html @@ -0,0 +1,88 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/util/hex.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli/util - hex.rs (source / functions)HitTotalCoverage
Test:unnamedLines:112152.4 %
Date:2024-04-23 03:30:56Functions:3475.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint::library_packages::impl_::util::hex::hash_u64_file0
dylint::library_packages::impl_::util::hex::hash_u64::<&dylint::library_packages::impl_::util::canonical_url::CanonicalUrl>9
dylint::library_packages::impl_::util::hex::short_hash::<dylint::library_packages::impl_::util::canonical_url::CanonicalUrl>9
dylint::library_packages::impl_::util::hex::to_hex9
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/util/hex.rs.func.html b/coverage/dylint/src/library_packages/cargo_cli/util/hex.rs.func.html new file mode 100644 index 000000000..92b884b90 --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/util/hex.rs.func.html @@ -0,0 +1,88 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/util/hex.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli/util - hex.rs (source / functions)HitTotalCoverage
Test:unnamedLines:112152.4 %
Date:2024-04-23 03:30:56Functions:3475.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint::library_packages::impl_::util::hex::hash_u64::<&dylint::library_packages::impl_::util::canonical_url::CanonicalUrl>9
dylint::library_packages::impl_::util::hex::hash_u64_file0
dylint::library_packages::impl_::util::hex::short_hash::<dylint::library_packages::impl_::util::canonical_url::CanonicalUrl>9
dylint::library_packages::impl_::util::hex::to_hex9
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/util/hex.rs.gcov.html b/coverage/dylint/src/library_packages/cargo_cli/util/hex.rs.gcov.html new file mode 100644 index 000000000..ecd5b41c2 --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/util/hex.rs.gcov.html @@ -0,0 +1,116 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/util/hex.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli/util - hex.rs (source / functions)HitTotalCoverage
Test:unnamedLines:112152.4 %
Date:2024-04-23 03:30:56Functions:3475.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : // smoelius: This file is a slight modification of:
+       2             : // https://github.com/rust-lang/cargo/blob/aab416f6e68d555e8c9a0f02098a24946e0725fb/src/cargo/util/hex.rs
+       3             : 
+       4             : #![allow(deprecated)]
+       5             : #![allow(clippy::module_name_repetitions)]
+       6             : #![cfg_attr(dylint_lib = "overscoped_allow", allow(overscoped_allow))]
+       7             : #![cfg_attr(dylint_lib = "supplementary", allow(unnamed_constant))]
+       8             : 
+       9             : type StableHasher = std::hash::SipHasher;
+      10             : 
+      11             : use std::fs::File;
+      12             : use std::hash::{Hash, Hasher};
+      13             : use std::io::Read;
+      14             : 
+      15           9 : pub fn to_hex(num: u64) -> String {
+      16           9 :     hex::encode(num.to_le_bytes())
+      17           9 : }
+      18             : 
+      19           9 : pub fn hash_u64<H: Hash>(hashable: H) -> u64 {
+      20           9 :     let mut hasher = StableHasher::new();
+      21           9 :     hashable.hash(&mut hasher);
+      22           9 :     hasher.finish()
+      23           9 : }
+      24             : 
+      25           0 : pub fn hash_u64_file(mut file: &File) -> std::io::Result<u64> {
+      26           0 :     let mut hasher = StableHasher::new();
+      27           0 :     let mut buf = [0; 64 * 1024];
+      28             :     loop {
+      29           0 :         let n = file.read(&mut buf)?;
+      30           0 :         if n == 0 {
+      31           0 :             break;
+      32           0 :         }
+      33           0 :         hasher.write(&buf[..n]);
+      34             :     }
+      35           0 :     Ok(hasher.finish())
+      36           0 : }
+      37             : 
+      38           9 : pub fn short_hash<H: Hash>(hashable: &H) -> String {
+      39           9 :     to_hex(hash_u64(hashable))
+      40           9 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/util/index-sort-f.html b/coverage/dylint/src/library_packages/cargo_cli/util/index-sort-f.html new file mode 100644 index 000000000..080a8c323 --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/util/index-sort-f.html @@ -0,0 +1,103 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/util + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli/utilHitTotalCoverage
Test:unnamedLines:406066.7 %
Date:2024-04-23 03:30:56Functions:6785.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
hex.rs +
52.4%52.4%
+
52.4 %11 / 2175.0 %3 / 4
canonical_url.rs +
74.4%74.4%
+
74.4 %29 / 39100.0 %3 / 3
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/util/index-sort-l.html b/coverage/dylint/src/library_packages/cargo_cli/util/index-sort-l.html new file mode 100644 index 000000000..827111d04 --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/util/index-sort-l.html @@ -0,0 +1,103 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/util + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli/utilHitTotalCoverage
Test:unnamedLines:406066.7 %
Date:2024-04-23 03:30:56Functions:6785.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
hex.rs +
52.4%52.4%
+
52.4 %11 / 2175.0 %3 / 4
canonical_url.rs +
74.4%74.4%
+
74.4 %29 / 39100.0 %3 / 3
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/cargo_cli/util/index.html b/coverage/dylint/src/library_packages/cargo_cli/util/index.html new file mode 100644 index 000000000..f17d08485 --- /dev/null +++ b/coverage/dylint/src/library_packages/cargo_cli/util/index.html @@ -0,0 +1,103 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/cargo_cli/util + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages/cargo_cli/utilHitTotalCoverage
Test:unnamedLines:406066.7 %
Date:2024-04-23 03:30:56Functions:6785.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
canonical_url.rs +
74.4%74.4%
+
74.4 %29 / 39100.0 %3 / 3
hex.rs +
52.4%52.4%
+
52.4 %11 / 2175.0 %3 / 4
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/index-sort-f.html b/coverage/dylint/src/library_packages/index-sort-f.html new file mode 100644 index 000000000..477b55ddb --- /dev/null +++ b/coverage/dylint/src/library_packages/index-sort-f.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packagesHitTotalCoverage
Test:unnamedLines:21725385.8 %
Date:2024-04-23 03:30:56Functions:295453.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
mod.rs +
85.8%85.8%
+
85.8 %217 / 25353.7 %29 / 54
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/index-sort-l.html b/coverage/dylint/src/library_packages/index-sort-l.html new file mode 100644 index 000000000..456c438d9 --- /dev/null +++ b/coverage/dylint/src/library_packages/index-sort-l.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packagesHitTotalCoverage
Test:unnamedLines:21725385.8 %
Date:2024-04-23 03:30:56Functions:295453.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
mod.rs +
85.8%85.8%
+
85.8 %217 / 25353.7 %29 / 54
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/index.html b/coverage/dylint/src/library_packages/index.html new file mode 100644 index 000000000..4b27555d2 --- /dev/null +++ b/coverage/dylint/src/library_packages/index.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packagesHitTotalCoverage
Test:unnamedLines:21725385.8 %
Date:2024-04-23 03:30:56Functions:295453.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
mod.rs +
85.8%85.8%
+
85.8 %217 / 25353.7 %29 / 54
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/mod.rs.func-sort-c.html b/coverage/dylint/src/library_packages/mod.rs.func-sort-c.html new file mode 100644 index 000000000..51c7c4ec6 --- /dev/null +++ b/coverage/dylint/src/library_packages/mod.rs.func-sort-c.html @@ -0,0 +1,288 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/mod.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages - mod.rs (source / functions)HitTotalCoverage
Test:unnamedLines:21725385.8 %
Date:2024-04-23 03:30:56Functions:295453.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::expecting0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_bool::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_borrowed_bytes::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_borrowed_str::<serde_json::error::Error>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_bytes::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_char::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_f32::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_f64::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i16::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i32::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i64::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i8::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u16::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u32::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u64::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u8::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_unit::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__Visitor as serde::de::Visitor>::expecting0
<dylint::library_packages::Package as core::cmp::Ord>::cmp0
<dylint::library_packages::Package as core::cmp::PartialEq>::eq0
<dylint::library_packages::Package as core::cmp::PartialOrd>::partial_cmp0
dylint::library_packages::build_library::{closure#0}0
dylint::library_packages::from_opts::{closure#0}0
dylint::library_packages::from_opts::{closure#1}0
dylint::library_packages::package_library_name::{closure#1}0
dylint::library_packages::detailed_toml_dependency::{closure#0}1
dylint::library_packages::from_opts2
dylint::library_packages::to_map_entry::{closure#0}2
dylint::library_packages::library_packages::{closure#1}5
dylint::library_packages::to_map_entry10
dylint::library_packages::build_library20
<dylint::library_packages::Package>::path21
dylint::library_packages::library_packages_from_dylint_metadata23
dylint::library_packages::library_packages_from_dylint_metadata::{closure#0}23
dylint::library_packages::library_packages25
dylint::library_packages::library_package::{closure#1}27
dylint::library_packages::package_id27
dylint::library_packages::package_library_name27
dylint::library_packages::package_library_name::{closure#0}27
dylint::library_packages::package_library_name::{closure#0}::{closure#0}27
dylint::library_packages::package_with_root27
dylint::library_packages::library_package::{closure#0}29
dylint::library_packages::library_package::{closure#0}::{closure#0}29
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__Visitor as serde::de::Visitor>::visit_map::<&mut serde_json::value::de::MapDeserializer>30
dylint::library_packages::detailed_toml_dependency32
dylint::library_packages::from_workspace_metadata32
dylint::library_packages::library_package32
dylint::library_packages::library_packages::{closure#0}32
dylint::library_packages::cargo_metadata::{closure#0}33
<dylint::library_packages::Package>::target_directory41
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__Field as serde::de::Deserialize>::deserialize::<serde_json::value::de::MapKeyDeserializer>43
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_str::<serde_json::error::Error>43
dylint::library_packages::dylint_metadata48
dylint::library_packages::cargo_metadata82
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/mod.rs.func.html b/coverage/dylint/src/library_packages/mod.rs.func.html new file mode 100644 index 000000000..ace6a97cc --- /dev/null +++ b/coverage/dylint/src/library_packages/mod.rs.func.html @@ -0,0 +1,288 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/mod.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages - mod.rs (source / functions)HitTotalCoverage
Test:unnamedLines:21725385.8 %
Date:2024-04-23 03:30:56Functions:295453.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__Field as serde::de::Deserialize>::deserialize::<serde_json::value::de::MapKeyDeserializer>43
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::expecting0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_bool::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_borrowed_bytes::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_borrowed_str::<serde_json::error::Error>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_bytes::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_char::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_f32::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_f64::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i16::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i32::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i64::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_i8::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_str::<serde_json::error::Error>43
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u16::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u32::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u64::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_u8::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__FieldVisitor as serde::de::Visitor>::visit_unit::<_>0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__Visitor as serde::de::Visitor>::expecting0
<<dylint::library_packages::Library as serde::de::Deserialize>::deserialize::__Visitor as serde::de::Visitor>::visit_map::<&mut serde_json::value::de::MapDeserializer>30
<dylint::library_packages::Package as core::cmp::Ord>::cmp0
<dylint::library_packages::Package as core::cmp::PartialEq>::eq0
<dylint::library_packages::Package as core::cmp::PartialOrd>::partial_cmp0
<dylint::library_packages::Package>::path21
<dylint::library_packages::Package>::target_directory41
dylint::library_packages::build_library20
dylint::library_packages::build_library::{closure#0}0
dylint::library_packages::cargo_metadata82
dylint::library_packages::cargo_metadata::{closure#0}33
dylint::library_packages::detailed_toml_dependency32
dylint::library_packages::detailed_toml_dependency::{closure#0}1
dylint::library_packages::dylint_metadata48
dylint::library_packages::from_opts2
dylint::library_packages::from_opts::{closure#0}0
dylint::library_packages::from_opts::{closure#1}0
dylint::library_packages::from_workspace_metadata32
dylint::library_packages::library_package32
dylint::library_packages::library_package::{closure#0}29
dylint::library_packages::library_package::{closure#0}::{closure#0}29
dylint::library_packages::library_package::{closure#1}27
dylint::library_packages::library_packages25
dylint::library_packages::library_packages::{closure#0}32
dylint::library_packages::library_packages::{closure#1}5
dylint::library_packages::library_packages_from_dylint_metadata23
dylint::library_packages::library_packages_from_dylint_metadata::{closure#0}23
dylint::library_packages::package_id27
dylint::library_packages::package_library_name27
dylint::library_packages::package_library_name::{closure#0}27
dylint::library_packages::package_library_name::{closure#0}::{closure#0}27
dylint::library_packages::package_library_name::{closure#1}0
dylint::library_packages::package_with_root27
dylint::library_packages::to_map_entry10
dylint::library_packages::to_map_entry::{closure#0}2
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/library_packages/mod.rs.gcov.html b/coverage/dylint/src/library_packages/mod.rs.gcov.html new file mode 100644 index 000000000..ca572ef64 --- /dev/null +++ b/coverage/dylint/src/library_packages/mod.rs.gcov.html @@ -0,0 +1,499 @@ + + + + + + + LCOV - unnamed - dylint/src/library_packages/mod.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/library_packages - mod.rs (source / functions)HitTotalCoverage
Test:unnamedLines:21725385.8 %
Date:2024-04-23 03:30:56Functions:295453.7 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use crate::{error::warn, opts};
+       2             : use anyhow::{anyhow, bail, ensure, Context, Result};
+       3             : use cargo_metadata::{Error, Metadata, MetadataCommand, Package as MetadataPackage};
+       4             : use dylint_internal::{env, library_filename, rustup::SanitizeEnvironment, CommandExt};
+       5             : use glob::glob;
+       6             : use if_chain::if_chain;
+       7             : use once_cell::sync::OnceCell;
+       8             : use serde::{de::IntoDeserializer, Deserialize};
+       9             : use std::path::{Path, PathBuf};
+      10             : 
+      11             : // smoelius: If both `__cargo_cli` and `__cargo_lib` are enabled, assume the user built
+      12             : // `cargo-dylint` with `--features=cargo-lib` and forgot `--no-default-features`.
+      13             : #[cfg(all(feature = "__cargo_cli", not(feature = "__cargo_lib")))]
+      14             : #[path = "cargo_cli/mod.rs"]
+      15             : mod impl_;
+      16             : 
+      17             : #[cfg(feature = "__cargo_lib")]
+      18             : #[path = "cargo_lib/mod.rs"]
+      19             : mod impl_;
+      20             : 
+      21             : use impl_::{dependency_source_id_and_root, Config, DetailedTomlDependency, PackageId, SourceId};
+      22             : 
+      23             : type Object = serde_json::Map<String, serde_json::Value>;
+      24             : 
+      25             : #[derive(Clone, Debug)]
+      26             : pub struct Package {
+      27             :     metadata: &'static Metadata,
+      28             :     pub root: PathBuf,
+      29             :     pub id: PackageId,
+      30             :     pub lib_name: String,
+      31             :     pub toolchain: String,
+      32             : }
+      33             : 
+      34             : impl Eq for Package {}
+      35             : 
+      36             : impl PartialEq for Package {
+      37           0 :     fn eq(&self, other: &Self) -> bool {
+      38           0 :         (&self.root, &self.id, &self.lib_name, &self.toolchain)
+      39           0 :             == (&other.root, &other.id, &other.lib_name, &other.toolchain)
+      40           0 :     }
+      41             : }
+      42             : 
+      43             : impl Ord for Package {
+      44           0 :     fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+      45           0 :         (&self.root, &self.id, &self.lib_name, &self.toolchain).cmp(&(
+      46           0 :             &other.root,
+      47           0 :             &other.id,
+      48           0 :             &other.lib_name,
+      49           0 :             &other.toolchain,
+      50           0 :         ))
+      51           0 :     }
+      52             : }
+      53             : 
+      54             : impl PartialOrd for Package {
+      55           0 :     fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+      56           0 :         Some(self.cmp(other))
+      57           0 :     }
+      58             : }
+      59             : 
+      60             : impl Package {
+      61          41 :     pub fn target_directory(&self) -> PathBuf {
+      62          41 :         self.metadata
+      63          41 :             .target_directory
+      64          41 :             .join("dylint/libraries")
+      65          41 :             .join(&self.toolchain)
+      66          41 :             .into_std_path_buf()
+      67          41 :     }
+      68             : 
+      69          21 :     pub fn path(&self) -> PathBuf {
+      70          21 :         self.target_directory()
+      71          21 :             .join("release")
+      72          21 :             .join(library_filename(&self.lib_name, &self.toolchain))
+      73          21 :     }
+      74             : }
+      75             : 
+      76          83 : #[derive(Debug, Deserialize)]
+      77             : struct Library {
+      78             :     pattern: Option<String>,
+      79             :     #[serde(flatten)]
+      80             :     details: DetailedTomlDependency,
+      81             : }
+      82             : 
+      83           2 : pub fn from_opts(opts: &opts::Dylint) -> Result<Vec<Package>> {
+      84           2 :     let lib_sel = opts.library_selection();
+      85             : 
+      86           2 :     let maybe_metadata = cargo_metadata(opts)?;
+      87             : 
+      88           2 :     let metadata = maybe_metadata.ok_or_else(|| anyhow!("Could not read cargo metadata"))?;
+      89             : 
+      90           2 :     ensure!(
+      91           2 :         lib_sel.paths.len() <= 1,
+      92           0 :         "At most one library package can be named with `--path`"
+      93             :     );
+      94             : 
+      95           2 :     let path = if let Some(path) = lib_sel.paths.first() {
+      96           2 :         let canonical_path = dunce::canonicalize(path)
+      97           2 :             .with_context(|| format!("Could not canonicalize {path:?}"))?;
+      98           2 :         Some(canonical_path.to_string_lossy().to_string())
+      99             :     } else {
+     100           0 :         None
+     101             :     };
+     102             : 
+     103           2 :     let toml: toml::map::Map<_, _> = vec![
+     104           2 :         to_map_entry("path", path.as_ref()),
+     105           2 :         to_map_entry("git", lib_sel.git.as_ref()),
+     106           2 :         to_map_entry("branch", lib_sel.branch.as_ref()),
+     107           2 :         to_map_entry("tag", lib_sel.tag.as_ref()),
+     108           2 :         to_map_entry("rev", lib_sel.rev.as_ref()),
+     109           2 :     ]
+     110           2 :     .into_iter()
+     111           2 :     .flatten()
+     112           2 :     .collect();
+     113             : 
+     114           2 :     let details = DetailedTomlDependency::deserialize(toml.into_deserializer())?;
+     115             : 
+     116           2 :     let library = Library {
+     117           2 :         details,
+     118           2 :         pattern: lib_sel.pattern.clone(),
+     119           2 :     };
+     120           2 : 
+     121           2 :     library_packages(opts, metadata, &[library])
+     122           2 : }
+     123             : 
+     124          10 : fn to_map_entry(key: &str, value: Option<&String>) -> Option<(String, toml::Value)> {
+     125          10 :     value
+     126          10 :         .cloned()
+     127          10 :         .map(|s| (String::from(key), toml::Value::from(s)))
+     128          10 : }
+     129             : 
+     130          32 : pub fn from_workspace_metadata(opts: &opts::Dylint) -> Result<Vec<Package>> {
+     131             :     if_chain! {
+     132          32 :         if let Some(metadata) = cargo_metadata(opts)?;
+     133          27 :         if let Some(object) = dylint_metadata(opts)?;
+     134             :         then {
+     135          23 :             library_packages_from_dylint_metadata(opts, metadata, object)
+     136             :         } else {
+     137           5 :             Ok(vec![])
+     138             :         }
+     139             :     }
+     140          32 : }
+     141             : 
+     142             : #[allow(clippy::module_name_repetitions)]
+     143          48 : pub fn dylint_metadata(opts: &opts::Dylint) -> Result<Option<&'static Object>> {
+     144             :     if_chain! {
+     145          48 :         if let Some(metadata) = cargo_metadata(opts)?;
+     146          45 :         if let serde_json::Value::Object(object) = &metadata.workspace_metadata;
+     147          40 :         if let Some(value) = object.get("dylint");
+     148             :         then {
+     149          40 :             if let serde_json::Value::Object(subobject) = value {
+     150          40 :                 Ok(Some(subobject))
+     151             :             } else {
+     152           0 :                 bail!("`dylint` value must be a map")
+     153             :             }
+     154             :         } else {
+     155           8 :             Ok(None)
+     156             :         }
+     157             :     }
+     158          48 : }
+     159             : 
+     160             : static CARGO_METADATA: OnceCell<Option<Metadata>> = OnceCell::new();
+     161             : 
+     162          82 : fn cargo_metadata(opts: &opts::Dylint) -> Result<Option<&'static Metadata>> {
+     163          82 :     CARGO_METADATA
+     164          82 :         .get_or_try_init(|| {
+     165          33 :             let lib_sel = opts.library_selection();
+     166          33 : 
+     167          33 :             if lib_sel.no_metadata {
+     168           4 :                 return Ok(None);
+     169          29 :             }
+     170          29 : 
+     171          29 :             let mut command = MetadataCommand::new();
+     172             : 
+     173          29 :             if let Some(path) = &lib_sel.manifest_path {
+     174           5 :                 command.manifest_path(path);
+     175          24 :             }
+     176             : 
+     177          29 :             match command.exec() {
+     178          29 :                 Ok(metadata) => Ok(Some(metadata)),
+     179           0 :                 Err(err) => {
+     180           0 :                     if lib_sel.manifest_path.is_none() {
+     181           0 :                         if_chain! {
+     182           0 :                             if let Error::CargoMetadata { stderr } = err;
+     183           0 :                             if let Some(line) = stderr.lines().next();
+     184           0 :                             if !line.starts_with("error: could not find `Cargo.toml`");
+     185             :                             then {
+     186           0 :                                 warn(opts, line.strip_prefix("error: ").unwrap_or(line));
+     187             :                             }
+     188             :                         }
+     189           0 :                         Ok(None)
+     190             :                     } else {
+     191           0 :                         Err(err.into())
+     192             :                     }
+     193             :                 }
+     194             :             }
+     195          82 :         })
+     196          82 :         .map(Option::as_ref)
+     197          82 : }
+     198             : 
+     199          23 : fn library_packages_from_dylint_metadata(
+     200          23 :     opts: &opts::Dylint,
+     201          23 :     metadata: &'static Metadata,
+     202          23 :     object: &Object,
+     203          23 : ) -> Result<Vec<Package>> {
+     204          23 :     let libraries = object
+     205          23 :         .iter()
+     206          23 :         .map(|(key, value)| {
+     207          23 :             if key == "libraries" {
+     208          23 :                 let libraries = serde_json::from_value::<Vec<Library>>(value.clone())?;
+     209          23 :                 library_packages(opts, metadata, &libraries)
+     210             :             } else {
+     211           0 :                 bail!("Unknown key `{}`", key)
+     212             :             }
+     213          23 :         })
+     214          23 :         .collect::<Result<Vec<_>>>()?;
+     215          18 :     Ok(libraries.into_iter().flatten().collect())
+     216          23 : }
+     217             : 
+     218          25 : fn library_packages(
+     219          25 :     opts: &opts::Dylint,
+     220          25 :     metadata: &'static Metadata,
+     221          25 :     libraries: &[Library],
+     222          25 : ) -> Result<Vec<Package>> {
+     223          25 :     let config = Config::default()?;
+     224             : 
+     225          25 :     let packages = libraries
+     226          25 :         .iter()
+     227          32 :         .map(|library| library_package(opts, metadata, &config, library))
+     228          25 :         .collect::<Result<Vec<_>>>()
+     229          25 :         .with_context(|| "Could not build metadata entries")?;
+     230             : 
+     231          20 :     Ok(packages.into_iter().flatten().collect())
+     232          25 : }
+     233             : 
+     234          32 : fn library_package(
+     235          32 :     opts: &opts::Dylint,
+     236          32 :     metadata: &'static Metadata,
+     237          32 :     config: &Config,
+     238          32 :     library: &Library,
+     239          32 : ) -> Result<Vec<Package>> {
+     240          32 :     let details = detailed_toml_dependency(library)?;
+     241             : 
+     242             :     // smoelius: The dependency root cannot be canonicalized here. It could contain a `glob` pattern
+     243             :     // (e.g., `*`), because Dylint allows `path` entries to contain `glob` patterns.
+     244          31 :     let (source_id, dependency_root) =
+     245          31 :         dependency_source_id_and_root(opts, metadata, config, details)?;
+     246             : 
+     247          31 :     let pattern = if let Some(pattern) = &library.pattern {
+     248           9 :         dependency_root.join(pattern)
+     249             :     } else {
+     250             :         #[allow(clippy::redundant_clone)]
+     251          22 :         dependency_root.clone()
+     252             :     };
+     253             : 
+     254          31 :     let entries = glob(&pattern.to_string_lossy())?;
+     255             : 
+     256          31 :     let paths = entries
+     257          31 :         .map(|entry| {
+     258          29 :             entry.map_err(Into::into).and_then(|path| {
+     259          29 :                 // smoelius: Because `dependency_root` might not be absolute, `path` might not be
+     260          29 :                 // absolute. So `path` must be normalized.
+     261          29 :                 let path_buf = cargo_util::paths::normalize_path(&path);
+     262          29 :                 if let Some(pattern) = &library.pattern {
+     263             :                     // smoelius: Use `cargo_util::paths::normalize_path` instead of `canonicalize`
+     264             :                     // so as not to "taint" the path with a path prefix on Windows.
+     265             :                     //
+     266             :                     // This problem keeps coming up. For example, it recently came up in:
+     267             :                     // https://github.com/trailofbits/dylint/pull/944
+     268           8 :                     let dependency_root = cargo_util::paths::normalize_path(&dependency_root);
+     269           8 :                     ensure!(
+     270           8 :                         path_buf.starts_with(&dependency_root),
+     271           2 :                         "Pattern `{pattern}` could refer to `{}`, which is outside of `{}`",
+     272           2 :                         path_buf.to_string_lossy(),
+     273           2 :                         dependency_root.to_string_lossy()
+     274             :                     );
+     275          21 :                 }
+     276          27 :                 Ok(path_buf)
+     277          29 :             })
+     278          31 :         })
+     279          31 :         .collect::<std::result::Result<Vec<_>, _>>()?;
+     280             : 
+     281          29 :     ensure!(
+     282          29 :         !paths.is_empty(),
+     283           2 :         "No paths matched `{}`",
+     284           2 :         pattern.to_string_lossy()
+     285             :     );
+     286             : 
+     287             :     // smoelius: Collecting the package ids before building reveals missing/unparsable `Cargo.toml`
+     288             :     // files sooner.
+     289             : 
+     290             :     // smoelius: Why are we doing this complicated dance at all? Because we want to leverage Cargo's
+     291             :     // download cache. But we also want to support git repositories with libraries that use
+     292             :     // different compiler versions. And we have to work around the fact that "all projects within a
+     293             :     // workspace are intended to be built with the same version of the compiler"
+     294             :     // (https://github.com/rust-lang/rustup/issues/1399#issuecomment-383376082).
+     295             : 
+     296             :     // smoelius: Experiments suggest that a considerable amount of Dylint's start up time is spent
+     297             :     // in the following "loop," and a considerable (though not necessarily dominant) fraction of
+     298             :     // that is spent in `active_toolchain`.
+     299          27 :     let packages = paths
+     300          27 :         .into_iter()
+     301          27 :         .map(|path| {
+     302          27 :             if path.is_dir() {
+     303             :                 // smoelius: Ignore subdirectories that do not contain packages.
+     304          27 :                 let Ok(package) = package_with_root(&path) else {
+     305           0 :                     return Ok(None);
+     306             :                 };
+     307             :                 // smoelius: When `__cargo_cli` is enabled, `source_id`'s type is `String`.
+     308             :                 #[allow(clippy::clone_on_copy)]
+     309          27 :                 let package_id = package_id(&package, source_id.clone())?;
+     310          27 :                 let lib_name = package_library_name(&package)?;
+     311          27 :                 let toolchain = dylint_internal::rustup::active_toolchain(&path)?;
+     312          27 :                 Ok(Some(Package {
+     313          27 :                     metadata,
+     314          27 :                     root: path,
+     315          27 :                     id: package_id,
+     316          27 :                     lib_name,
+     317          27 :                     toolchain,
+     318          27 :                 }))
+     319             :             } else {
+     320           0 :                 Ok(None)
+     321             :             }
+     322          27 :         })
+     323          27 :         .collect::<Result<Vec<_>>>()?;
+     324             : 
+     325          27 :     Ok(packages.into_iter().flatten().collect())
+     326          32 : }
+     327             : 
+     328          32 : fn detailed_toml_dependency(library: &Library) -> Result<&DetailedTomlDependency> {
+     329          32 :     let mut unused_keys = library.details.unused_keys();
+     330          32 :     #[allow(clippy::format_collect)]
+     331          32 :     if !unused_keys.is_empty() {
+     332           1 :         unused_keys.sort_unstable();
+     333           1 :         bail!(
+     334           1 :             "Unknown library keys:{}",
+     335           1 :             unused_keys
+     336           1 :                 .iter()
+     337           1 :                 .map(|name| format!("\n    {name}"))
+     338           1 :                 .collect::<String>()
+     339           1 :         );
+     340          31 :     }
+     341          31 : 
+     342          31 :     Ok(&library.details)
+     343          32 : }
+     344             : 
+     345          27 : fn package_with_root(package_root: &Path) -> Result<MetadataPackage> {
+     346             :     // smoelius: For the long term, we should investigate having a "cache" that maps paths to
+     347             :     // `cargo_metadata::Metadata`.
+     348          27 :     let metadata = MetadataCommand::new()
+     349          27 :         .current_dir(package_root)
+     350          27 :         .no_deps()
+     351          27 :         .exec()?;
+     352             : 
+     353          27 :     dylint_internal::cargo::package_with_root(&metadata, package_root)
+     354          27 : }
+     355             : 
+     356          27 : fn package_id(package: &MetadataPackage, source_id: SourceId) -> Result<PackageId> {
+     357          27 :     PackageId::new(package.name.clone(), package.version.clone(), source_id)
+     358          27 : }
+     359             : 
+     360          27 : pub fn package_library_name(package: &MetadataPackage) -> Result<String> {
+     361          27 :     package
+     362          27 :         .targets
+     363          27 :         .iter()
+     364          27 :         .find_map(|target| {
+     365          27 :             if target.kind.iter().any(|kind| kind == "cdylib") {
+     366          27 :                 Some(target.name.clone())
+     367             :             } else {
+     368           0 :                 None
+     369             :             }
+     370          27 :         })
+     371          27 :         .ok_or_else(|| {
+     372           0 :             anyhow!(
+     373           0 :                 "Could not find `cdylib` target for package `{}`",
+     374           0 :                 package.id
+     375           0 :             )
+     376          27 :         })
+     377          27 : }
+     378             : 
+     379          20 : pub fn build_library(opts: &opts::Dylint, package: &Package) -> Result<PathBuf> {
+     380          20 :     let target_dir = package.target_directory();
+     381          20 : 
+     382          20 :     let path = package.path();
+     383          20 : 
+     384          20 :     if !opts.library_selection().no_build {
+     385             :         // smoelius: Clear `RUSTFLAGS` so that changes to it do not cause workspace metadata entries
+     386             :         // to be rebuilt.
+     387          20 :         dylint_internal::cargo::build(&format!("workspace metadata entry `{}`", package.id.name()))
+     388          20 :             .quiet(opts.quiet)
+     389          20 :             .build()
+     390          20 :             .sanitize_environment()
+     391          20 :             .env_remove(env::RUSTFLAGS)
+     392          20 :             .current_dir(&package.root)
+     393          20 :             .args(["--release", "--target-dir", &target_dir.to_string_lossy()])
+     394          20 :             .success()?;
+     395             : 
+     396          20 :         let exists = path
+     397          20 :             .try_exists()
+     398          20 :             .with_context(|| format!("Could not determine whether {path:?} exists"))?;
+     399             : 
+     400          20 :         ensure!(exists, "Could not find {path:?} despite successful build");
+     401           0 :     }
+     402             : 
+     403          20 :     Ok(path)
+     404          20 : }
+     405             : 
+     406             : // smoelius: `pkg_dir` and `target_short_hash` are based on functions with the same names in
+     407             : // https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/context/compilation_files.rs
+     408             : 
+     409             : #[cfg(any())]
+     410             : mod disabled {
+     411             :     fn pkg_dir(package_root: &Path, pkg_id: PackageId) -> String {
+     412             :         let name = pkg_id.name();
+     413             :         format!("{}-{}", name, target_short_hash(package_root, pkg_id))
+     414             :     }
+     415             : 
+     416             :     const METADATA_VERSION: u8 = 2;
+     417             : 
+     418             :     fn target_short_hash(package_root: &Path, pkg_id: PackageId) -> String {
+     419             :         // smoelius: For now, the package root is the workspace root.
+     420             :         let hashable = pkg_id.stable_hash(package_root);
+     421             :         cargo::util::short_hash(&(METADATA_VERSION, hashable))
+     422             :     }
+     423             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/name_toolchain_map/index-sort-f.html b/coverage/dylint/src/name_toolchain_map/index-sort-f.html new file mode 100644 index 000000000..668dfab7e --- /dev/null +++ b/coverage/dylint/src/name_toolchain_map/index-sort-f.html @@ -0,0 +1,103 @@ + + + + + + + LCOV - unnamed - dylint/src/name_toolchain_map + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/name_toolchain_mapHitTotalCoverage
Test:unnamedLines:939894.9 %
Date:2024-04-23 03:30:56Functions:131586.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
mod.rs +
93.1%93.1%
+
93.1 %67 / 7277.8 %7 / 9
maybe_library.rs +
100.0%
+
100.0 %26 / 26100.0 %6 / 6
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/name_toolchain_map/index-sort-l.html b/coverage/dylint/src/name_toolchain_map/index-sort-l.html new file mode 100644 index 000000000..bcf433870 --- /dev/null +++ b/coverage/dylint/src/name_toolchain_map/index-sort-l.html @@ -0,0 +1,103 @@ + + + + + + + LCOV - unnamed - dylint/src/name_toolchain_map + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/name_toolchain_mapHitTotalCoverage
Test:unnamedLines:939894.9 %
Date:2024-04-23 03:30:56Functions:131586.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
mod.rs +
93.1%93.1%
+
93.1 %67 / 7277.8 %7 / 9
maybe_library.rs +
100.0%
+
100.0 %26 / 26100.0 %6 / 6
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/name_toolchain_map/index.html b/coverage/dylint/src/name_toolchain_map/index.html new file mode 100644 index 000000000..d0b62ad18 --- /dev/null +++ b/coverage/dylint/src/name_toolchain_map/index.html @@ -0,0 +1,103 @@ + + + + + + + LCOV - unnamed - dylint/src/name_toolchain_map + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/name_toolchain_mapHitTotalCoverage
Test:unnamedLines:939894.9 %
Date:2024-04-23 03:30:56Functions:131586.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
maybe_library.rs +
100.0%
+
100.0 %26 / 26100.0 %6 / 6
mod.rs +
93.1%93.1%
+
93.1 %67 / 7277.8 %7 / 9
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/name_toolchain_map/maybe_library.rs.func-sort-c.html b/coverage/dylint/src/name_toolchain_map/maybe_library.rs.func-sort-c.html new file mode 100644 index 000000000..5faf47b05 --- /dev/null +++ b/coverage/dylint/src/name_toolchain_map/maybe_library.rs.func-sort-c.html @@ -0,0 +1,96 @@ + + + + + + + LCOV - unnamed - dylint/src/name_toolchain_map/maybe_library.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/name_toolchain_map - maybe_library.rs (source / functions)HitTotalCoverage
Test:unnamedLines:2626100.0 %
Date:2024-04-23 03:30:56Functions:66100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::name_toolchain_map::maybe_library::Inner>::path3
<dylint::name_toolchain_map::maybe_library::MaybeLibrary>::path3
<dylint::name_toolchain_map::maybe_library::MaybeLibrary as core::convert::From<dylint::library_packages::Package>>::from23
<dylint::name_toolchain_map::maybe_library::Inner>::build29
<dylint::name_toolchain_map::maybe_library::MaybeLibrary>::build29
<dylint::name_toolchain_map::maybe_library::MaybeLibrary as core::convert::From<std::path::PathBuf>>::from71
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/name_toolchain_map/maybe_library.rs.func.html b/coverage/dylint/src/name_toolchain_map/maybe_library.rs.func.html new file mode 100644 index 000000000..750c2d285 --- /dev/null +++ b/coverage/dylint/src/name_toolchain_map/maybe_library.rs.func.html @@ -0,0 +1,96 @@ + + + + + + + LCOV - unnamed - dylint/src/name_toolchain_map/maybe_library.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/name_toolchain_map - maybe_library.rs (source / functions)HitTotalCoverage
Test:unnamedLines:2626100.0 %
Date:2024-04-23 03:30:56Functions:66100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::name_toolchain_map::maybe_library::Inner>::build29
<dylint::name_toolchain_map::maybe_library::Inner>::path3
<dylint::name_toolchain_map::maybe_library::MaybeLibrary as core::convert::From<dylint::library_packages::Package>>::from23
<dylint::name_toolchain_map::maybe_library::MaybeLibrary as core::convert::From<std::path::PathBuf>>::from71
<dylint::name_toolchain_map::maybe_library::MaybeLibrary>::build29
<dylint::name_toolchain_map::maybe_library::MaybeLibrary>::path3
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/name_toolchain_map/maybe_library.rs.gcov.html b/coverage/dylint/src/name_toolchain_map/maybe_library.rs.gcov.html new file mode 100644 index 000000000..b96deaf3b --- /dev/null +++ b/coverage/dylint/src/name_toolchain_map/maybe_library.rs.gcov.html @@ -0,0 +1,139 @@ + + + + + + + LCOV - unnamed - dylint/src/name_toolchain_map/maybe_library.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/name_toolchain_map - maybe_library.rs (source / functions)HitTotalCoverage
Test:unnamedLines:2626100.0 %
Date:2024-04-23 03:30:56Functions:66100.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use anyhow::Result;
+       2             : use std::path::PathBuf;
+       3             : 
+       4             : #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
+       5             : pub struct MaybeLibrary {
+       6             :     inner: Inner,
+       7             : }
+       8             : 
+       9             : impl MaybeLibrary {
+      10           3 :     pub fn path(&self) -> PathBuf {
+      11           3 :         self.inner.path()
+      12           3 :     }
+      13             : 
+      14          29 :     pub fn build(&self, opts: &crate::opts::Dylint) -> Result<PathBuf> {
+      15          29 :         self.inner.build(opts)
+      16          29 :     }
+      17             : }
+      18             : 
+      19             : impl From<PathBuf> for MaybeLibrary {
+      20          71 :     fn from(path: PathBuf) -> Self {
+      21          71 :         Self {
+      22          71 :             inner: Inner::Path(path),
+      23          71 :         }
+      24          71 :     }
+      25             : }
+      26             : 
+      27             : #[cfg(__library_packages)]
+      28             : impl From<crate::library_packages::Package> for MaybeLibrary {
+      29          23 :     fn from(package: crate::library_packages::Package) -> Self {
+      30          23 :         Self {
+      31          23 :             inner: Inner::Package(package),
+      32          23 :         }
+      33          23 :     }
+      34             : }
+      35             : 
+      36             : #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
+      37             : pub enum Inner {
+      38             :     Path(PathBuf),
+      39             : 
+      40             :     #[cfg(__library_packages)]
+      41             :     Package(crate::library_packages::Package),
+      42             : }
+      43             : 
+      44             : impl Inner {
+      45           3 :     pub fn path(&self) -> PathBuf {
+      46           3 :         match self {
+      47           2 :             Self::Path(path) => path.clone(),
+      48             : 
+      49             :             #[cfg(__library_packages)]
+      50           1 :             Self::Package(package) => package.path(),
+      51             :         }
+      52           3 :     }
+      53             : 
+      54             :     #[cfg_attr(not(__library_packages), allow(unused_variables))]
+      55          29 :     fn build(&self, opts: &crate::opts::Dylint) -> Result<PathBuf> {
+      56          29 :         match self {
+      57           9 :             Self::Path(path) => Ok(path.clone()),
+      58             : 
+      59             :             #[cfg(__library_packages)]
+      60          20 :             Self::Package(package) => crate::library_packages::build_library(opts, package),
+      61             :         }
+      62          29 :     }
+      63             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/name_toolchain_map/mod.rs.func-sort-c.html b/coverage/dylint/src/name_toolchain_map/mod.rs.func-sort-c.html new file mode 100644 index 000000000..e33508eaa --- /dev/null +++ b/coverage/dylint/src/name_toolchain_map/mod.rs.func-sort-c.html @@ -0,0 +1,108 @@ + + + + + + + LCOV - unnamed - dylint/src/name_toolchain_map/mod.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/name_toolchain_map - mod.rs (source / functions)HitTotalCoverage
Test:unnamedLines:677293.1 %
Date:2024-04-23 03:30:56Functions:7977.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint::name_toolchain_map::dylint_libraries_in::{closure#0}0
dylint::name_toolchain_map::dylint_libraries_in::{closure#1}::{closure#0}0
dylint::name_toolchain_map::dylint_libraries_in10
dylint::name_toolchain_map::dylint_library_paths27
<dylint::name_toolchain_map::Lazy>::get_or_try_init::{closure#0}34
<dylint::name_toolchain_map::Lazy>::new37
<dylint::name_toolchain_map::Lazy>::get_or_try_init43
dylint::name_toolchain_map::dylint_libraries_in::{closure#1}::{closure#1}71
dylint::name_toolchain_map::dylint_libraries_in::{closure#1}219
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/name_toolchain_map/mod.rs.func.html b/coverage/dylint/src/name_toolchain_map/mod.rs.func.html new file mode 100644 index 000000000..a9b0bcef3 --- /dev/null +++ b/coverage/dylint/src/name_toolchain_map/mod.rs.func.html @@ -0,0 +1,108 @@ + + + + + + + LCOV - unnamed - dylint/src/name_toolchain_map/mod.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/name_toolchain_map - mod.rs (source / functions)HitTotalCoverage
Test:unnamedLines:677293.1 %
Date:2024-04-23 03:30:56Functions:7977.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::name_toolchain_map::Lazy>::get_or_try_init43
<dylint::name_toolchain_map::Lazy>::get_or_try_init::{closure#0}34
<dylint::name_toolchain_map::Lazy>::new37
dylint::name_toolchain_map::dylint_libraries_in10
dylint::name_toolchain_map::dylint_libraries_in::{closure#0}0
dylint::name_toolchain_map::dylint_libraries_in::{closure#1}219
dylint::name_toolchain_map::dylint_libraries_in::{closure#1}::{closure#0}0
dylint::name_toolchain_map::dylint_libraries_in::{closure#1}::{closure#1}71
dylint::name_toolchain_map::dylint_library_paths27
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/name_toolchain_map/mod.rs.gcov.html b/coverage/dylint/src/name_toolchain_map/mod.rs.gcov.html new file mode 100644 index 000000000..c0f3be3c8 --- /dev/null +++ b/coverage/dylint/src/name_toolchain_map/mod.rs.gcov.html @@ -0,0 +1,204 @@ + + + + + + + LCOV - unnamed - dylint/src/name_toolchain_map/mod.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/name_toolchain_map - mod.rs (source / functions)HitTotalCoverage
Test:unnamedLines:677293.1 %
Date:2024-04-23 03:30:56Functions:7977.8 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use anyhow::{ensure, Context, Result};
+       2             : use dylint_internal::{env, parse_path_filename};
+       3             : use once_cell::sync::OnceCell;
+       4             : use std::{
+       5             :     collections::{BTreeMap, BTreeSet},
+       6             :     env::split_paths,
+       7             :     fs::read_dir,
+       8             :     path::{Path, PathBuf},
+       9             : };
+      10             : 
+      11             : mod maybe_library;
+      12             : pub use maybe_library::MaybeLibrary;
+      13             : 
+      14             : pub type ToolchainMap = BTreeMap<String, BTreeSet<PathBuf>>;
+      15             : 
+      16             : #[allow(clippy::redundant_pub_crate)]
+      17             : pub(crate) type NameToolchainMap = BTreeMap<String, LazyToolchainMap>;
+      18             : 
+      19             : #[allow(clippy::redundant_pub_crate)]
+      20             : pub(crate) type LazyToolchainMap = BTreeMap<String, BTreeSet<MaybeLibrary>>;
+      21             : 
+      22             : #[cfg_attr(not(__library_packages), allow(dead_code))]
+      23             : struct Inner<'opts> {
+      24             :     opts: &'opts crate::opts::Dylint,
+      25             :     name_toolchain_map: OnceCell<NameToolchainMap>,
+      26             : }
+      27             : 
+      28             : pub struct Lazy<'opts> {
+      29             :     inner: Inner<'opts>,
+      30             : }
+      31             : 
+      32             : impl<'opts> Lazy<'opts> {
+      33             :     #[must_use]
+      34          37 :     pub const fn new(opts: &'opts crate::opts::Dylint) -> Self {
+      35          37 :         Self {
+      36          37 :             inner: Inner {
+      37          37 :                 opts,
+      38          37 :                 name_toolchain_map: OnceCell::new(),
+      39          37 :             },
+      40          37 :         }
+      41          37 :     }
+      42             : 
+      43          43 :     pub fn get_or_try_init(&self) -> Result<&NameToolchainMap> {
+      44          43 :         self.inner
+      45          43 :             .name_toolchain_map
+      46          43 :             .get_or_try_init(|| -> Result<_> {
+      47          34 :                 let mut name_toolchain_map = NameToolchainMap::new();
+      48             : 
+      49             :                 #[cfg(__library_packages)]
+      50             :                 {
+      51          34 :                     let library_packages = if self.inner.opts.git_or_path() {
+      52           2 :                         crate::library_packages::from_opts(self.inner.opts)?
+      53             :                     } else {
+      54          32 :                         crate::library_packages::from_workspace_metadata(self.inner.opts)?
+      55             :                     };
+      56             : 
+      57          52 :                     for package in library_packages {
+      58          23 :                         name_toolchain_map
+      59          23 :                             .entry(package.lib_name.clone())
+      60          23 :                             .or_default()
+      61          23 :                             .entry(package.toolchain.clone())
+      62          23 :                             .or_default()
+      63          23 :                             .insert(MaybeLibrary::from(package));
+      64          23 :                     }
+      65             :                 }
+      66             : 
+      67             :                 // smoelius: If `--git` or `--path` was passed, then do not look for libraries by
+      68             :                 // other means.
+      69          29 :                 if !self.inner.opts.git_or_path() {
+      70          27 :                     let dylint_library_paths = dylint_library_paths()?;
+      71             : 
+      72          37 :                     for path in dylint_library_paths {
+      73          71 :                         for entry in dylint_libraries_in(&path)? {
+      74          71 :                             let (name, toolchain, path) = entry?;
+      75          71 :                             name_toolchain_map
+      76          71 :                                 .entry(name)
+      77          71 :                                 .or_default()
+      78          71 :                                 .entry(toolchain)
+      79          71 :                                 .or_default()
+      80          71 :                                 .insert(MaybeLibrary::from(path));
+      81             :                         }
+      82             :                     }
+      83           2 :                 }
+      84             : 
+      85          29 :                 Ok(name_toolchain_map)
+      86          43 :             })
+      87          43 :     }
+      88             : }
+      89             : 
+      90          27 : fn dylint_library_paths() -> Result<Vec<PathBuf>> {
+      91          27 :     let mut paths = Vec::new();
+      92             : 
+      93          27 :     if let Ok(val) = env::var(env::DYLINT_LIBRARY_PATH) {
+      94          10 :         for path in split_paths(&val) {
+      95          10 :             ensure!(
+      96          10 :                 path.is_absolute(),
+      97           0 :                 "DYLINT_LIBRARY_PATH contains `{}`, which is not absolute",
+      98           0 :                 path.to_string_lossy()
+      99             :             );
+     100          10 :             ensure!(
+     101          10 :                 path.is_dir(),
+     102           0 :                 "DYLINT_LIBRARY_PATH contains `{}`, which is not a directory",
+     103           0 :                 path.to_string_lossy()
+     104             :             );
+     105          10 :             paths.push(path);
+     106             :         }
+     107          20 :     }
+     108             : 
+     109          27 :     Ok(paths)
+     110          27 : }
+     111             : 
+     112          10 : fn dylint_libraries_in(
+     113          10 :     path: &Path,
+     114          10 : ) -> Result<impl Iterator<Item = Result<(String, String, PathBuf)>>> {
+     115          10 :     let iter = read_dir(path)
+     116          10 :         .with_context(|| format!("`read_dir` failed for `{}`", path.to_string_lossy()))?;
+     117          10 :     let path_buf = path.to_path_buf();
+     118          10 :     Ok(iter
+     119         219 :         .map(move |entry| -> Result<Option<(String, String, PathBuf)>> {
+     120         219 :             let entry = entry.with_context(|| {
+     121           0 :                 format!("`read_dir` failed for `{}`", path_buf.to_string_lossy())
+     122         219 :             })?;
+     123         219 :             let path = entry.path();
+     124         219 : 
+     125         219 :             Ok(parse_path_filename(&path).map(|(lib_name, toolchain)| (lib_name, toolchain, path)))
+     126         219 :         })
+     127          10 :         .filter_map(Result::transpose))
+     128          10 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/opts.rs.func-sort-c.html b/coverage/dylint/src/opts.rs.func-sort-c.html new file mode 100644 index 000000000..369cfd646 --- /dev/null +++ b/coverage/dylint/src/opts.rs.func-sort-c.html @@ -0,0 +1,100 @@ + + + + + + + LCOV - unnamed - dylint/src/opts.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src - opts.rs (source / functions)HitTotalCoverage
Test:unnamedLines:353989.7 %
Date:2024-04-23 03:30:56Functions:77100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::opts::Dylint>::library_selection_mut35
<dylint::opts::Operation>::library_selection_mut35
<dylint::opts::Operation as core::default::Default>::default46
<dylint::opts::Dylint>::git_or_path63
<dylint::opts::LibrarySelection>::git_or_path98
<dylint::opts::Dylint>::library_selection246
<dylint::opts::Operation>::library_selection246
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/opts.rs.func.html b/coverage/dylint/src/opts.rs.func.html new file mode 100644 index 000000000..165d5453f --- /dev/null +++ b/coverage/dylint/src/opts.rs.func.html @@ -0,0 +1,100 @@ + + + + + + + LCOV - unnamed - dylint/src/opts.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src - opts.rs (source / functions)HitTotalCoverage
Test:unnamedLines:353989.7 %
Date:2024-04-23 03:30:56Functions:77100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::opts::Dylint>::git_or_path63
<dylint::opts::Dylint>::library_selection246
<dylint::opts::Dylint>::library_selection_mut35
<dylint::opts::LibrarySelection>::git_or_path98
<dylint::opts::Operation as core::default::Default>::default46
<dylint::opts::Operation>::library_selection246
<dylint::opts::Operation>::library_selection_mut35
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/opts.rs.gcov.html b/coverage/dylint/src/opts.rs.gcov.html new file mode 100644 index 000000000..c8e2c9ad3 --- /dev/null +++ b/coverage/dylint/src/opts.rs.gcov.html @@ -0,0 +1,254 @@ + + + + + + + LCOV - unnamed - dylint/src/opts.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src - opts.rs (source / functions)HitTotalCoverage
Test:unnamedLines:353989.7 %
Date:2024-04-23 03:30:56Functions:77100.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : //! Warning: Addition of public fields to the structs in this module is considered a non-breaking
+       2             : //! change.
+       3             : //!
+       4             : //! For this reason, we recommend using [struct update syntax] when initializing instances of the
+       5             : //! structs in this module.
+       6             : //!
+       7             : //! Example:
+       8             : //!
+       9             : //! ```
+      10             : //! # use crate::dylint::opts::Dylint;
+      11             : //! let opts = Dylint {
+      12             : //!     quiet: true,
+      13             : //!     ..Default::default()
+      14             : //! };
+      15             : //! ```
+      16             : //!
+      17             : //! [struct update syntax]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax
+      18             : 
+      19             : #[cfg(feature = "package_options")]
+      20             : use once_cell::sync::Lazy;
+      21             : 
+      22             : #[allow(clippy::struct_excessive_bools)]
+      23             : #[derive(Clone, Debug, Default)]
+      24             : pub struct Dylint {
+      25             :     pub pipe_stderr: Option<String>,
+      26             : 
+      27             :     pub pipe_stdout: Option<String>,
+      28             : 
+      29             :     pub quiet: bool,
+      30             : 
+      31             :     pub operation: Operation,
+      32             : }
+      33             : 
+      34             : #[derive(Clone, Debug, Default)]
+      35             : pub struct LibrarySelection {
+      36             :     pub all: bool,
+      37             : 
+      38             :     pub branch: Option<String>,
+      39             : 
+      40             :     pub git: Option<String>,
+      41             : 
+      42             :     pub lib_paths: Vec<String>,
+      43             : 
+      44             :     pub libs: Vec<String>,
+      45             : 
+      46             :     pub manifest_path: Option<String>,
+      47             : 
+      48             :     pub no_build: bool,
+      49             : 
+      50             :     pub no_metadata: bool,
+      51             : 
+      52             :     pub paths: Vec<String>,
+      53             : 
+      54             :     pub pattern: Option<String>,
+      55             : 
+      56             :     pub rev: Option<String>,
+      57             : 
+      58             :     pub tag: Option<String>,
+      59             : }
+      60             : 
+      61             : #[derive(Clone, Debug)]
+      62             : #[non_exhaustive]
+      63             : pub enum Operation {
+      64             :     Check(Check),
+      65             :     List(List),
+      66             :     #[cfg(feature = "package_options")]
+      67             :     New(New),
+      68             :     #[cfg(feature = "package_options")]
+      69             :     Upgrade(Upgrade),
+      70             : }
+      71             : 
+      72             : #[allow(clippy::struct_excessive_bools)]
+      73             : #[derive(Clone, Debug, Default)]
+      74             : pub struct Check {
+      75             :     pub lib_sel: LibrarySelection,
+      76             : 
+      77             :     pub fix: bool,
+      78             : 
+      79             :     pub keep_going: bool,
+      80             : 
+      81             :     pub no_deps: bool,
+      82             : 
+      83             :     pub packages: Vec<String>,
+      84             : 
+      85             :     pub workspace: bool,
+      86             : 
+      87             :     pub args: Vec<String>,
+      88             : }
+      89             : 
+      90             : #[derive(Clone, Debug, Default)]
+      91             : pub struct List {
+      92             :     pub lib_sel: LibrarySelection,
+      93             : }
+      94             : 
+      95             : #[cfg(feature = "package_options")]
+      96             : #[derive(Clone, Debug, Default)]
+      97             : pub struct New {
+      98             :     pub isolate: bool,
+      99             : 
+     100             :     pub path: String,
+     101             : }
+     102             : 
+     103             : #[cfg(feature = "package_options")]
+     104             : #[derive(Clone, Debug, Default)]
+     105             : pub struct Upgrade {
+     106             :     pub allow_downgrade: bool,
+     107             : 
+     108             :     pub rust_version: Option<String>,
+     109             : 
+     110             :     pub path: String,
+     111             : }
+     112             : 
+     113             : impl Dylint {
+     114             :     #[must_use]
+     115         246 :     pub fn library_selection(&self) -> &LibrarySelection {
+     116         246 :         self.operation.library_selection()
+     117         246 :     }
+     118             : 
+     119          35 :     pub fn library_selection_mut(&mut self) -> &mut LibrarySelection {
+     120          35 :         self.operation.library_selection_mut()
+     121          35 :     }
+     122             : 
+     123          63 :     pub(crate) fn git_or_path(&self) -> bool {
+     124          63 :         self.library_selection().git_or_path()
+     125          63 :     }
+     126             : }
+     127             : 
+     128             : impl LibrarySelection {
+     129          98 :     pub(crate) fn git_or_path(&self) -> bool {
+     130          98 :         self.git.is_some() || !self.paths.is_empty()
+     131          98 :     }
+     132             : }
+     133             : 
+     134             : #[cfg(feature = "package_options")]
+     135             : static LIBRARY_SELECTION: Lazy<LibrarySelection> = Lazy::new(LibrarySelection::default);
+     136             : 
+     137             : impl Operation {
+     138         246 :     fn library_selection(&self) -> &LibrarySelection {
+     139         246 :         match self {
+     140         193 :             Self::Check(check) => &check.lib_sel,
+     141          49 :             Self::List(list) => &list.lib_sel,
+     142             :             #[cfg(feature = "package_options")]
+     143             :             Self::New(_) | Self::Upgrade(_) => {
+     144           4 :                 if cfg!(debug_assertions) {
+     145           4 :                     eprintln!(
+     146           4 :                         "[{}:{}] {}",
+     147           4 :                         file!(),
+     148           4 :                         line!(),
+     149           4 :                         "`library_selection` called on an `Operation` with no `LibrarySelection` \
+     150           4 :                          field"
+     151           4 :                     );
+     152           4 :                 }
+     153           4 :                 &LIBRARY_SELECTION
+     154             :             }
+     155             :         }
+     156         246 :     }
+     157             : 
+     158             :     #[allow(clippy::panic)]
+     159          35 :     fn library_selection_mut(&mut self) -> &mut LibrarySelection {
+     160          35 :         match self {
+     161          26 :             Self::Check(check) => &mut check.lib_sel,
+     162           9 :             Self::List(list) => &mut list.lib_sel,
+     163             :             #[cfg(feature = "package_options")]
+     164             :             Self::New(_) | Self::Upgrade(_) => {
+     165           0 :                 panic!(
+     166           0 :                     "`library_selection_mut` called on an `Operation` with no `LibrarySelection` \
+     167           0 :                      field"
+     168           0 :                 )
+     169             :             }
+     170             :         }
+     171          35 :     }
+     172             : }
+     173             : 
+     174             : impl Default for Operation {
+     175          46 :     fn default() -> Self {
+     176          46 :         Self::Check(Check::default())
+     177          46 :     }
+     178             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/package_options/backup.rs.func-sort-c.html b/coverage/dylint/src/package_options/backup.rs.func-sort-c.html new file mode 100644 index 000000000..1db1dfcef --- /dev/null +++ b/coverage/dylint/src/package_options/backup.rs.func-sort-c.html @@ -0,0 +1,92 @@ + + + + + + + LCOV - unnamed - dylint/src/package_options/backup.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/package_options - backup.rs (source / functions)HitTotalCoverage
Test:unnamedLines:252696.2 %
Date:2024-04-23 03:30:56Functions:4580.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::package_options::backup::Backup>::new::<_>0
<dylint::package_options::backup::Backup as core::ops::drop::Drop>::drop4
<dylint::package_options::backup::Backup>::disable4
<dylint::package_options::backup::Backup>::new::<std::path::PathBuf>4
dylint::package_options::backup::sibling_tempfile4
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/package_options/backup.rs.func.html b/coverage/dylint/src/package_options/backup.rs.func.html new file mode 100644 index 000000000..dd0cab4f4 --- /dev/null +++ b/coverage/dylint/src/package_options/backup.rs.func.html @@ -0,0 +1,92 @@ + + + + + + + LCOV - unnamed - dylint/src/package_options/backup.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/package_options - backup.rs (source / functions)HitTotalCoverage
Test:unnamedLines:252696.2 %
Date:2024-04-23 03:30:56Functions:4580.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::package_options::backup::Backup as core::ops::drop::Drop>::drop4
<dylint::package_options::backup::Backup>::disable4
<dylint::package_options::backup::Backup>::new::<_>0
<dylint::package_options::backup::Backup>::new::<std::path::PathBuf>4
dylint::package_options::backup::sibling_tempfile4
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/package_options/backup.rs.gcov.html b/coverage/dylint/src/package_options/backup.rs.gcov.html new file mode 100644 index 000000000..a1f6b7f85 --- /dev/null +++ b/coverage/dylint/src/package_options/backup.rs.gcov.html @@ -0,0 +1,122 @@ + + + + + + + LCOV - unnamed - dylint/src/package_options/backup.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/package_options - backup.rs (source / functions)HitTotalCoverage
Test:unnamedLines:252696.2 %
Date:2024-04-23 03:30:56Functions:4580.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use std::{
+       2             :     fs::{copy, rename},
+       3             :     io::Result,
+       4             :     path::{Path, PathBuf},
+       5             : };
+       6             : use tempfile::NamedTempFile;
+       7             : 
+       8             : pub struct Backup {
+       9             :     path: PathBuf,
+      10             :     tempfile: Option<NamedTempFile>,
+      11             : }
+      12             : 
+      13             : impl Backup {
+      14           4 :     pub fn new<P>(path: P) -> Result<Self>
+      15           4 :     where
+      16           4 :         P: AsRef<Path>,
+      17           4 :     {
+      18           4 :         let tempfile = sibling_tempfile(path.as_ref())?;
+      19           4 :         copy(&path, &tempfile)?;
+      20           4 :         Ok(Self {
+      21           4 :             path: path.as_ref().to_path_buf(),
+      22           4 :             tempfile: Some(tempfile),
+      23           4 :         })
+      24           4 :     }
+      25             : 
+      26           4 :     pub fn disable(&mut self) -> Result<()> {
+      27           4 :         self.tempfile.take().map_or(Ok(()), NamedTempFile::close)
+      28           4 :     }
+      29             : }
+      30             : 
+      31             : impl Drop for Backup {
+      32           4 :     fn drop(&mut self) {
+      33           4 :         if let Some(tempfile) = self.tempfile.take() {
+      34           0 :             rename(&tempfile, &self.path).unwrap_or_default();
+      35           4 :         }
+      36           4 :     }
+      37             : }
+      38             : 
+      39             : #[allow(clippy::expect_used)]
+      40           4 : fn sibling_tempfile(path: &Path) -> Result<NamedTempFile> {
+      41           4 :     let canonical_path = path.canonicalize()?;
+      42           4 :     let parent = canonical_path
+      43           4 :         .parent()
+      44           4 :         .expect("should not fail for a canonical path");
+      45           4 :     NamedTempFile::new_in(parent)
+      46           4 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/package_options/index-sort-f.html b/coverage/dylint/src/package_options/index-sort-f.html new file mode 100644 index 000000000..ce814d133 --- /dev/null +++ b/coverage/dylint/src/package_options/index-sort-f.html @@ -0,0 +1,113 @@ + + + + + + + LCOV - unnamed - dylint/src/package_options + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/package_optionsHitTotalCoverage
Test:unnamedLines:24026092.3 %
Date:2024-04-23 03:30:56Functions:203754.1 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
mod.rs +
86.6%86.6%
+
86.6 %103 / 11942.1 %8 / 19
revs.rs +
97.4%97.4%
+
97.4 %112 / 11561.5 %8 / 13
backup.rs +
96.2%96.2%
+
96.2 %25 / 2680.0 %4 / 5
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/package_options/index-sort-l.html b/coverage/dylint/src/package_options/index-sort-l.html new file mode 100644 index 000000000..df115e9dc --- /dev/null +++ b/coverage/dylint/src/package_options/index-sort-l.html @@ -0,0 +1,113 @@ + + + + + + + LCOV - unnamed - dylint/src/package_options + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/package_optionsHitTotalCoverage
Test:unnamedLines:24026092.3 %
Date:2024-04-23 03:30:56Functions:203754.1 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
mod.rs +
86.6%86.6%
+
86.6 %103 / 11942.1 %8 / 19
backup.rs +
96.2%96.2%
+
96.2 %25 / 2680.0 %4 / 5
revs.rs +
97.4%97.4%
+
97.4 %112 / 11561.5 %8 / 13
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/package_options/index.html b/coverage/dylint/src/package_options/index.html new file mode 100644 index 000000000..993901539 --- /dev/null +++ b/coverage/dylint/src/package_options/index.html @@ -0,0 +1,113 @@ + + + + + + + LCOV - unnamed - dylint/src/package_options + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/package_optionsHitTotalCoverage
Test:unnamedLines:24026092.3 %
Date:2024-04-23 03:30:56Functions:203754.1 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
backup.rs +
96.2%96.2%
+
96.2 %25 / 2680.0 %4 / 5
mod.rs +
86.6%86.6%
+
86.6 %103 / 11942.1 %8 / 19
revs.rs +
97.4%97.4%
+
97.4 %112 / 11561.5 %8 / 13
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/package_options/mod.rs.func-sort-c.html b/coverage/dylint/src/package_options/mod.rs.func-sort-c.html new file mode 100644 index 000000000..a7f35e4a3 --- /dev/null +++ b/coverage/dylint/src/package_options/mod.rs.func-sort-c.html @@ -0,0 +1,148 @@ + + + + + + + LCOV - unnamed - dylint/src/package_options/mod.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/package_options - mod.rs (source / functions)HitTotalCoverage
Test:unnamedLines:10311986.6 %
Date:2024-04-23 03:30:56Functions:81942.1 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint::package_options::fill_in::{closure#0}0
dylint::package_options::fill_in::{closure#1}0
dylint::package_options::fill_in::{closure#2}0
dylint::package_options::new_package::{closure#1}0
dylint::package_options::new_package::{closure#2}0
dylint::package_options::upgrade_package::{closure#1}0
dylint::package_options::upgrade_package::{closure#2}0
dylint::package_options::upgrade_package::{closure#3}0
dylint::package_options::upgrade_package::{closure#4}0
dylint::package_options::upgrade_package::{closure#5}0
dylint::package_options::upgrade_package::{closure#6}0
dylint::package_options::fill_in1
dylint::package_options::new_package1
dylint::package_options::new_package::{closure#0}1
dylint::package_options::upgrade_package3
dylint::package_options::parse_as_nightly4
dylint::package_options::parse_date4
dylint::package_options::upgrade_package::{closure#0}14
dylint::package_options::upgrade_package::{closure#0}::{closure#0}14
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/package_options/mod.rs.func.html b/coverage/dylint/src/package_options/mod.rs.func.html new file mode 100644 index 000000000..25c10b03c --- /dev/null +++ b/coverage/dylint/src/package_options/mod.rs.func.html @@ -0,0 +1,148 @@ + + + + + + + LCOV - unnamed - dylint/src/package_options/mod.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/package_options - mod.rs (source / functions)HitTotalCoverage
Test:unnamedLines:10311986.6 %
Date:2024-04-23 03:30:56Functions:81942.1 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint::package_options::fill_in1
dylint::package_options::fill_in::{closure#0}0
dylint::package_options::fill_in::{closure#1}0
dylint::package_options::fill_in::{closure#2}0
dylint::package_options::new_package1
dylint::package_options::new_package::{closure#0}1
dylint::package_options::new_package::{closure#1}0
dylint::package_options::new_package::{closure#2}0
dylint::package_options::parse_as_nightly4
dylint::package_options::parse_date4
dylint::package_options::upgrade_package3
dylint::package_options::upgrade_package::{closure#0}14
dylint::package_options::upgrade_package::{closure#0}::{closure#0}14
dylint::package_options::upgrade_package::{closure#1}0
dylint::package_options::upgrade_package::{closure#2}0
dylint::package_options::upgrade_package::{closure#3}0
dylint::package_options::upgrade_package::{closure#4}0
dylint::package_options::upgrade_package::{closure#5}0
dylint::package_options::upgrade_package::{closure#6}0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/package_options/mod.rs.gcov.html b/coverage/dylint/src/package_options/mod.rs.gcov.html new file mode 100644 index 000000000..e48d84cd0 --- /dev/null +++ b/coverage/dylint/src/package_options/mod.rs.gcov.html @@ -0,0 +1,252 @@ + + + + + + + LCOV - unnamed - dylint/src/package_options/mod.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/package_options - mod.rs (source / functions)HitTotalCoverage
Test:unnamedLines:10311986.6 %
Date:2024-04-23 03:30:56Functions:81942.1 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use crate::opts;
+       2             : use anyhow::{anyhow, bail, Context, Result};
+       3             : use dylint_internal::{
+       4             :     clippy_utils::{
+       5             :         clippy_utils_version_from_rust_version, set_clippy_utils_dependency_revision,
+       6             :         set_toolchain_channel, toolchain_channel,
+       7             :     },
+       8             :     find_and_replace,
+       9             :     packaging::new_template,
+      10             : };
+      11             : use heck::{ToKebabCase, ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase};
+      12             : use if_chain::if_chain;
+      13             : use std::{
+      14             :     fs::{copy, create_dir_all},
+      15             :     path::Path,
+      16             : };
+      17             : use tempfile::tempdir;
+      18             : use walkdir::WalkDir;
+      19             : 
+      20             : mod backup;
+      21             : use backup::Backup;
+      22             : 
+      23             : mod revs;
+      24             : use revs::Revs;
+      25             : 
+      26           1 : pub fn new_package(_opts: &opts::Dylint, new_opts: &opts::New) -> Result<()> {
+      27           1 :     let path = Path::new(&new_opts.path);
+      28             : 
+      29           1 :     let name = path
+      30           1 :         .file_name()
+      31           1 :         .map(|s| s.to_string_lossy().to_string())
+      32           1 :         .ok_or_else(|| anyhow!("Could not determine library name from {:?}", path))?;
+      33             : 
+      34           1 :     let tempdir = tempdir().with_context(|| "`tempdir` failed")?;
+      35             : 
+      36           1 :     new_template(tempdir.path())?;
+      37             : 
+      38             :     // smoelius: Isolation is now the default.
+      39           1 :     if !new_opts.isolate {
+      40           0 :         find_and_replace(
+      41           0 :             &tempdir.path().join("Cargo.toml"),
+      42           0 :             r"\r?\n\[workspace\]\r?\n",
+      43           0 :             "",
+      44           0 :         )?;
+      45           1 :     }
+      46             : 
+      47             :     // smoelius: So is allowing unused extern crates.
+      48           1 :     find_and_replace(
+      49           1 :         &tempdir.path().join("src/lib.rs"),
+      50           1 :         r"(?m)^.. (#!\[warn\(unused_extern_crates\)\])$",
+      51           1 :         "${1}",
+      52           1 :     )?;
+      53             : 
+      54           1 :     fill_in(&name, tempdir.path(), path)?;
+      55             : 
+      56           1 :     Ok(())
+      57           1 : }
+      58             : 
+      59           1 : fn fill_in(name: &str, from: &Path, to: &Path) -> Result<()> {
+      60           1 :     let lower_snake_case = name.to_snake_case();
+      61           1 :     let upper_snake_case = name.to_shouty_snake_case();
+      62           1 :     let kebab_case = name.to_kebab_case();
+      63           1 :     let camel_case = name.to_upper_camel_case();
+      64             : 
+      65          12 :     for entry in WalkDir::new(from) {
+      66          12 :         let entry = entry?;
+      67          12 :         let abs_path = entry.path();
+      68          12 :         let rel_path = abs_path.strip_prefix(from)?;
+      69             : 
+      70          12 :         if !abs_path.is_file() {
+      71           4 :             continue;
+      72           8 :         }
+      73           8 : 
+      74           8 :         find_and_replace(&from.join(rel_path), r"\bfill_me_in\b", &lower_snake_case)?;
+      75           8 :         find_and_replace(&from.join(rel_path), r"\bFILL_ME_IN\b", &upper_snake_case)?;
+      76           8 :         find_and_replace(&from.join(rel_path), r"\bfill-me-in\b", &kebab_case)?;
+      77           8 :         find_and_replace(&from.join(rel_path), r"\bFillMeIn\b", &camel_case)?;
+      78             : 
+      79           8 :         let from_path = from.join(rel_path);
+      80           8 :         let to_path = to.join(rel_path);
+      81           8 :         let parent = to_path
+      82           8 :             .parent()
+      83           8 :             .ok_or_else(|| anyhow!("Could not get parent directory"))?;
+      84           8 :         create_dir_all(parent).with_context(|| {
+      85           0 :             format!("`create_dir_all` failed for `{}`", parent.to_string_lossy())
+      86           8 :         })?;
+      87           8 :         copy(&from_path, &to_path).with_context(|| {
+      88           0 :             format!(
+      89           0 :                 "Could not copy `{}` to `{}`",
+      90           0 :                 from_path.to_string_lossy(),
+      91           0 :                 to_path.to_string_lossy()
+      92           0 :             )
+      93           8 :         })?;
+      94             :     }
+      95             : 
+      96           1 :     Ok(())
+      97           1 : }
+      98             : 
+      99           3 : pub fn upgrade_package(opts: &opts::Dylint, upgrade_opts: &opts::Upgrade) -> Result<()> {
+     100           3 :     let path = Path::new(&upgrade_opts.path);
+     101             : 
+     102           3 :     let rev = {
+     103           3 :         let revs = Revs::new(opts.quiet)?;
+     104           3 :         let mut iter = revs.iter()?;
+     105           3 :         match &upgrade_opts.rust_version {
+     106           2 :             Some(rust_version) => {
+     107           2 :                 let clippy_utils_version = clippy_utils_version_from_rust_version(rust_version)?;
+     108          14 :                 iter.find(|result| {
+     109          14 :                     result
+     110          14 :                         .as_ref()
+     111          14 :                         .map_or(true, |rev| rev.version == clippy_utils_version)
+     112          14 :                 })
+     113           2 :                 .unwrap_or_else(|| {
+     114           0 :                     Err(anyhow!(
+     115           0 :                         "Could not find `clippy_utils` version `{}`",
+     116           0 :                         clippy_utils_version
+     117           0 :                     ))
+     118           2 :                 })?
+     119             :             }
+     120           1 :             None => iter.next().unwrap_or_else(|| {
+     121           0 :                 Err(anyhow!("Could not determine latest `clippy_utils` version"))
+     122           1 :             })?,
+     123             :         }
+     124             :     };
+     125             : 
+     126           3 :     let old_channel = toolchain_channel(path)?;
+     127             : 
+     128           1 :     if_chain! {
+     129           3 :         if !upgrade_opts.allow_downgrade;
+     130           2 :         if let Some(new_nightly) = parse_as_nightly(&rev.channel);
+     131           2 :         if let Some(old_nightly) = parse_as_nightly(&old_channel);
+     132           2 :         if new_nightly < old_nightly;
+     133             :         then {
+     134           1 :             bail!(
+     135           1 :                 "Refusing to downgrade toolchain from `{}` to `{}`. \
+     136           1 :                 Use `--allow-downgrade` to override.",
+     137           1 :                 old_channel,
+     138           1 :                 rev.channel
+     139           1 :             );
+     140             :         }
+     141             :     };
+     142             : 
+     143           2 :     let rust_toolchain_path = path.join("rust-toolchain");
+     144           2 :     let cargo_toml_path = path.join("Cargo.toml");
+     145             : 
+     146           2 :     let mut rust_toolchain_backup =
+     147           2 :         Backup::new(rust_toolchain_path).with_context(|| "Could not backup `rust-toolchain`")?;
+     148           2 :     let mut cargo_toml_backup =
+     149           2 :         Backup::new(cargo_toml_path).with_context(|| "Could not backup `Cargo.toml`")?;
+     150             : 
+     151           2 :     set_toolchain_channel(path, &rev.channel)?;
+     152           2 :     set_clippy_utils_dependency_revision(path, &rev.rev)?;
+     153             : 
+     154           2 :     cargo_toml_backup
+     155           2 :         .disable()
+     156           2 :         .with_context(|| "Could not disable `rust-toolchain` backup")?;
+     157           2 :     rust_toolchain_backup
+     158           2 :         .disable()
+     159           2 :         .with_context(|| "Could not disable `Cargo.toml` backup")?;
+     160             : 
+     161           2 :     Ok(())
+     162           3 : }
+     163             : 
+     164           4 : fn parse_as_nightly(channel: &str) -> Option<[u32; 3]> {
+     165           4 :     channel.strip_prefix("nightly-").and_then(parse_date)
+     166           4 : }
+     167             : 
+     168           4 : fn parse_date(date_str: &str) -> Option<[u32; 3]> {
+     169           4 :     date_str
+     170           4 :         .split('-')
+     171           4 :         .map(str::parse::<u32>)
+     172           4 :         .map(Result::ok)
+     173           4 :         .collect::<Option<Vec<_>>>()
+     174           4 :         .map(<[u32; 3]>::try_from)
+     175           4 :         .and_then(Result::ok)
+     176           4 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/package_options/revs.rs.func-sort-c.html b/coverage/dylint/src/package_options/revs.rs.func-sort-c.html new file mode 100644 index 000000000..5801bb9e1 --- /dev/null +++ b/coverage/dylint/src/package_options/revs.rs.func-sort-c.html @@ -0,0 +1,124 @@ + + + + + + + LCOV - unnamed - dylint/src/package_options/revs.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/package_options - revs.rs (source / functions)HitTotalCoverage
Test:unnamedLines:11211597.4 %
Date:2024-04-23 03:30:56Functions:81361.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::package_options::revs::RevIter as core::iter::traits::iterator::Iterator>::next::{closure#0}::{closure#0}0
<dylint::package_options::revs::RevIter as core::iter::traits::iterator::Iterator>::next::{closure#0}::{closure#1}0
<dylint::package_options::revs::Revs>::iter::{closure#0}0
<dylint::package_options::revs::Revs>::iter::{closure#1}0
<dylint::package_options::revs::Revs>::new::{closure#0}0
dylint::package_options::revs::test::EXAMPLES::{closure#0}1
dylint::package_options::revs::test::examples1
<dylint::package_options::revs::Revs>::iter9
<dylint::package_options::revs::Revs>::new9
dylint::package_options::revs::test::examples::{closure#0}113
dylint::package_options::revs::test::examples::{closure#0}::{closure#0}113
<dylint::package_options::revs::RevIter as core::iter::traits::iterator::Iterator>::next128
<dylint::package_options::revs::RevIter as core::iter::traits::iterator::Iterator>::next::{closure#0}128
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/package_options/revs.rs.func.html b/coverage/dylint/src/package_options/revs.rs.func.html new file mode 100644 index 000000000..5b1ab1186 --- /dev/null +++ b/coverage/dylint/src/package_options/revs.rs.func.html @@ -0,0 +1,124 @@ + + + + + + + LCOV - unnamed - dylint/src/package_options/revs.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/package_options - revs.rs (source / functions)HitTotalCoverage
Test:unnamedLines:11211597.4 %
Date:2024-04-23 03:30:56Functions:81361.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint::package_options::revs::RevIter as core::iter::traits::iterator::Iterator>::next128
<dylint::package_options::revs::RevIter as core::iter::traits::iterator::Iterator>::next::{closure#0}128
<dylint::package_options::revs::RevIter as core::iter::traits::iterator::Iterator>::next::{closure#0}::{closure#0}0
<dylint::package_options::revs::RevIter as core::iter::traits::iterator::Iterator>::next::{closure#0}::{closure#1}0
<dylint::package_options::revs::Revs>::iter9
<dylint::package_options::revs::Revs>::iter::{closure#0}0
<dylint::package_options::revs::Revs>::iter::{closure#1}0
<dylint::package_options::revs::Revs>::new9
<dylint::package_options::revs::Revs>::new::{closure#0}0
dylint::package_options::revs::test::EXAMPLES::{closure#0}1
dylint::package_options::revs::test::examples1
dylint::package_options::revs::test::examples::{closure#0}113
dylint::package_options::revs::test::examples::{closure#0}::{closure#0}113
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/dylint/src/package_options/revs.rs.gcov.html b/coverage/dylint/src/package_options/revs.rs.gcov.html new file mode 100644 index 000000000..7ccc28b3f --- /dev/null +++ b/coverage/dylint/src/package_options/revs.rs.gcov.html @@ -0,0 +1,260 @@ + + + + + + + LCOV - unnamed - dylint/src/package_options/revs.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - dylint/src/package_options - revs.rs (source / functions)HitTotalCoverage
Test:unnamedLines:11211597.4 %
Date:2024-04-23 03:30:56Functions:81361.5 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use anyhow::{anyhow, Context, Result};
+       2             : use dylint_internal::{
+       3             :     clippy_utils::{clippy_utils_package_version, toolchain_channel},
+       4             :     clone,
+       5             :     git2::{Commit, ObjectType, Repository},
+       6             : };
+       7             : use if_chain::if_chain;
+       8             : use tempfile::{tempdir, TempDir};
+       9             : 
+      10             : const RUST_CLIPPY_URL: &str = "https://github.com/rust-lang/rust-clippy";
+      11             : 
+      12             : #[derive(Debug, Eq, PartialEq)]
+      13             : pub struct Rev {
+      14             :     pub version: String,
+      15             :     pub channel: String,
+      16             :     pub rev: String,
+      17             : }
+      18             : 
+      19             : pub struct Revs {
+      20             :     tempdir: TempDir,
+      21             :     repository: Repository,
+      22             : }
+      23             : 
+      24             : pub struct RevIter<'revs> {
+      25             :     revs: &'revs Revs,
+      26             :     commit: Commit<'revs>,
+      27             :     curr_rev: Option<Rev>,
+      28             : }
+      29             : 
+      30             : impl Revs {
+      31           9 :     pub fn new(quiet: bool) -> Result<Self> {
+      32           9 :         let tempdir = tempdir().with_context(|| "`tempdir` failed")?;
+      33             : 
+      34           9 :         let repository = clone(RUST_CLIPPY_URL, "master", tempdir.path(), quiet)?;
+      35             : 
+      36           9 :         Ok(Self {
+      37           9 :             tempdir,
+      38           9 :             repository,
+      39           9 :         })
+      40           9 :     }
+      41             : 
+      42             :     #[allow(clippy::iter_not_returning_iterator)]
+      43           9 :     pub fn iter(&self) -> Result<RevIter> {
+      44           9 :         let object = {
+      45           9 :             let head = self.repository.head()?;
+      46           9 :             let oid = head.target().ok_or_else(|| anyhow!("Could not get HEAD"))?;
+      47           9 :             self.repository.find_object(oid, Some(ObjectType::Commit))?
+      48             :         };
+      49           9 :         let commit = object
+      50           9 :             .as_commit()
+      51           9 :             .ok_or_else(|| anyhow!("Object is not a commit"))?;
+      52           9 :         let version = clippy_utils_package_version(self.tempdir.path())?;
+      53           9 :         let channel = toolchain_channel(self.tempdir.path())?;
+      54           9 :         let rev = commit.id().to_string();
+      55           9 :         Ok(RevIter {
+      56           9 :             revs: self,
+      57           9 :             commit: commit.clone(),
+      58           9 :             curr_rev: Some(Rev {
+      59           9 :                 version,
+      60           9 :                 channel,
+      61           9 :                 rev,
+      62           9 :             }),
+      63           9 :         })
+      64           9 :     }
+      65             : }
+      66             : 
+      67             : impl<'revs> Iterator for RevIter<'revs> {
+      68             :     type Item = Result<Rev>;
+      69             : 
+      70             :     // smoelius: I think it is okay to ignore the `non_local_effect_before_error_return` warning
+      71             :     // here. If `self.commit` were not updated, the same commits would be traversed the next time
+      72             :     // `next` was called.
+      73             :     #[cfg_attr(dylint_lib = "general", allow(non_local_effect_before_error_return))]
+      74             :     #[cfg_attr(dylint_lib = "overscoped_allow", allow(overscoped_allow))]
+      75         128 :     fn next(&mut self) -> Option<Self::Item> {
+      76         128 :         (|| -> Result<Option<Rev>> {
+      77         128 :             let mut prev_rev: Option<Rev> = None;
+      78             :             loop {
+      79       11804 :                 let curr_rev = if let Some(rev) = self.curr_rev.take() {
+      80         128 :                     rev
+      81             :                 } else {
+      82             :                     // smoelius: Note that this is not `git log`'s default behavior. Rather, this
+      83             :                     // behavior corresponds to:
+      84             :                     //   git log --first-parent
+      85       11676 :                     let commit = if let Some(commit) = self.commit.parents().next() {
+      86       11676 :                         self.commit = commit.clone();
+      87       11676 :                         commit
+      88             :                     } else {
+      89           0 :                         return Ok(None);
+      90             :                     };
+      91       11676 :                     self.revs
+      92       11676 :                         .repository
+      93       11676 :                         .checkout_tree(commit.as_object(), None)
+      94       11676 :                         .with_context(|| {
+      95           0 :                             format!("`checkout_tree` failed for `{:?}`", commit.as_object())
+      96       11676 :                         })?;
+      97       11676 :                     self.revs
+      98       11676 :                         .repository
+      99       11676 :                         .set_head_detached(commit.id())
+     100       11676 :                         .with_context(|| {
+     101           0 :                             format!("`set_head_detached` failed for `{}`", commit.id())
+     102       11676 :                         })?;
+     103       11676 :                     let version = clippy_utils_package_version(self.revs.tempdir.path())?;
+     104       11676 :                     let channel = toolchain_channel(self.revs.tempdir.path())?;
+     105       11676 :                     let rev = commit.id().to_string();
+     106       11676 :                     Rev {
+     107       11676 :                         version,
+     108       11676 :                         channel,
+     109       11676 :                         rev,
+     110       11676 :                     }
+     111             :                 };
+     112         128 :                 if_chain! {
+     113       11804 :                     if let Some(prev_rev) = prev_rev;
+     114       11676 :                     if prev_rev.version != curr_rev.version;
+     115             :                     then {
+     116         128 :                         self.curr_rev = Some(curr_rev);
+     117         128 :                         return Ok(Some(prev_rev));
+     118             :                     }
+     119             :                 }
+     120       11676 :                 prev_rev = Some(curr_rev);
+     121             :             }
+     122         128 :         })()
+     123         128 :         .transpose()
+     124         128 :     }
+     125             : }
+     126             : 
+     127             : #[allow(clippy::unwrap_used)]
+     128             : #[cfg(test)]
+     129             : mod test {
+     130             :     use super::*;
+     131             :     use once_cell::sync::Lazy;
+     132             : 
+     133           1 :     static EXAMPLES: Lazy<[Rev; 6]> = Lazy::new(|| {
+     134           1 :         [
+     135           1 :             Rev {
+     136           1 :                 version: "0.1.65".to_owned(),
+     137           1 :                 channel: "nightly-2022-08-11".to_owned(),
+     138           1 :                 rev: "2b2190cb5667cdd276a24ef8b9f3692209c54a89".to_owned(),
+     139           1 :             },
+     140           1 :             Rev {
+     141           1 :                 version: "0.1.64".to_owned(),
+     142           1 :                 channel: "nightly-2022-06-30".to_owned(),
+     143           1 :                 rev: "0cb0f7636851f9fcc57085cf80197a2ef6db098f".to_owned(),
+     144           1 :             },
+     145           1 :             // smoelius: 0.1.62 and 0.1.63 omitted (for no particular reason).
+     146           1 :             Rev {
+     147           1 :                 version: "0.1.61".to_owned(),
+     148           1 :                 channel: "nightly-2022-02-24".to_owned(),
+     149           1 :                 rev: "7b2896a8fc9f0b275692677ee6d2d66a7cbde16a".to_owned(),
+     150           1 :             },
+     151           1 :             Rev {
+     152           1 :                 version: "0.1.60".to_owned(),
+     153           1 :                 channel: "nightly-2022-01-13".to_owned(),
+     154           1 :                 rev: "97a5daa65908e59744e2bc625b14849352231c75".to_owned(),
+     155           1 :             },
+     156           1 :             Rev {
+     157           1 :                 version: "0.1.59".to_owned(),
+     158           1 :                 channel: "nightly-2021-12-02".to_owned(),
+     159           1 :                 rev: "392b0c5c25ddbd36e4dc480afcf70ed01dce352d".to_owned(),
+     160           1 :             },
+     161           1 :             Rev {
+     162           1 :                 version: "0.1.58".to_owned(),
+     163           1 :                 channel: "nightly-2021-10-21".to_owned(),
+     164           1 :                 rev: "91496c2ac6abf6454c413bb23e8becf6b6dc20ea".to_owned(),
+     165           1 :             },
+     166           1 :         ]
+     167           1 :     });
+     168             : 
+     169             :     #[test]
+     170           1 :     fn examples() {
+     171           6 :         for example in &*EXAMPLES {
+     172           6 :             let revs = Revs::new(false).unwrap();
+     173           6 :             let mut iter = revs.iter().unwrap();
+     174           6 :             let rev = iter
+     175         113 :                 .find(|rev| {
+     176         113 :                     rev.as_ref()
+     177         113 :                         .map_or(true, |rev| rev.version == example.version)
+     178         113 :                 })
+     179           6 :                 .unwrap()
+     180           6 :                 .unwrap();
+     181           6 :             assert_eq!(rev, *example);
+     182             :         }
+     183           1 :     }
+     184             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/emerald.png b/coverage/emerald.png new file mode 100644 index 000000000..38ad4f406 Binary files /dev/null and b/coverage/emerald.png differ diff --git a/coverage/gcov.css b/coverage/gcov.css new file mode 100644 index 000000000..bfd0a83e1 --- /dev/null +++ b/coverage/gcov.css @@ -0,0 +1,519 @@ +/* All views: initial background and text color */ +body +{ + color: #000000; + background-color: #FFFFFF; +} + +/* All views: standard link format*/ +a:link +{ + color: #284FA8; + text-decoration: underline; +} + +/* All views: standard link - visited format */ +a:visited +{ + color: #00CB40; + text-decoration: underline; +} + +/* All views: standard link - activated format */ +a:active +{ + color: #FF0040; + text-decoration: underline; +} + +/* All views: main title format */ +td.title +{ + text-align: center; + padding-bottom: 10px; + font-family: sans-serif; + font-size: 20pt; + font-style: italic; + font-weight: bold; +} + +/* All views: header item format */ +td.headerItem +{ + text-align: right; + padding-right: 6px; + font-family: sans-serif; + font-weight: bold; + vertical-align: top; + white-space: nowrap; +} + +/* All views: header item value format */ +td.headerValue +{ + text-align: left; + color: #284FA8; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; +} + +/* All views: header item coverage table heading */ +td.headerCovTableHead +{ + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + font-size: 80%; + white-space: nowrap; +} + +/* All views: header item coverage table entry */ +td.headerCovTableEntry +{ + text-align: right; + color: #284FA8; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #DAE7FE; +} + +/* All views: header item coverage table entry for high coverage rate */ +td.headerCovTableEntryHi +{ + text-align: right; + color: #000000; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #A7FC9D; +} + +/* All views: header item coverage table entry for medium coverage rate */ +td.headerCovTableEntryMed +{ + text-align: right; + color: #000000; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #FFEA20; +} + +/* All views: header item coverage table entry for ow coverage rate */ +td.headerCovTableEntryLo +{ + text-align: right; + color: #000000; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #FF0000; +} + +/* All views: header legend value for legend entry */ +td.headerValueLeg +{ + text-align: left; + color: #000000; + font-family: sans-serif; + font-size: 80%; + white-space: nowrap; + padding-top: 4px; +} + +/* All views: color of horizontal ruler */ +td.ruler +{ + background-color: #6688D4; +} + +/* All views: version string format */ +td.versionInfo +{ + text-align: center; + padding-top: 2px; + font-family: sans-serif; + font-style: italic; +} + +/* Directory view/File view (all)/Test case descriptions: + table headline format */ +td.tableHead +{ + text-align: center; + color: #FFFFFF; + background-color: #6688D4; + font-family: sans-serif; + font-size: 120%; + font-weight: bold; + white-space: nowrap; + padding-left: 4px; + padding-right: 4px; +} + +span.tableHeadSort +{ + padding-right: 4px; +} + +/* Directory view/File view (all): filename entry format */ +td.coverFile +{ + text-align: left; + padding-left: 10px; + padding-right: 20px; + color: #284FA8; + background-color: #DAE7FE; + font-family: monospace; +} + +/* Directory view/File view (all): bar-graph entry format*/ +td.coverBar +{ + padding-left: 10px; + padding-right: 10px; + background-color: #DAE7FE; +} + +/* Directory view/File view (all): bar-graph outline color */ +td.coverBarOutline +{ + background-color: #000000; +} + +/* Directory view/File view (all): percentage entry for files with + high coverage rate */ +td.coverPerHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #A7FC9D; + font-weight: bold; + font-family: sans-serif; +} + +/* Directory view/File view (all): line count entry for files with + high coverage rate */ +td.coverNumHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #A7FC9D; + white-space: nowrap; + font-family: sans-serif; +} + +/* Directory view/File view (all): percentage entry for files with + medium coverage rate */ +td.coverPerMed +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #FFEA20; + font-weight: bold; + font-family: sans-serif; +} + +/* Directory view/File view (all): line count entry for files with + medium coverage rate */ +td.coverNumMed +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #FFEA20; + white-space: nowrap; + font-family: sans-serif; +} + +/* Directory view/File view (all): percentage entry for files with + low coverage rate */ +td.coverPerLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #FF0000; + font-weight: bold; + font-family: sans-serif; +} + +/* Directory view/File view (all): line count entry for files with + low coverage rate */ +td.coverNumLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #FF0000; + white-space: nowrap; + font-family: sans-serif; +} + +/* File view (all): "show/hide details" link format */ +a.detail:link +{ + color: #B8D0FF; + font-size:80%; +} + +/* File view (all): "show/hide details" link - visited format */ +a.detail:visited +{ + color: #B8D0FF; + font-size:80%; +} + +/* File view (all): "show/hide details" link - activated format */ +a.detail:active +{ + color: #FFFFFF; + font-size:80%; +} + +/* File view (detail): test name entry */ +td.testName +{ + text-align: right; + padding-right: 10px; + background-color: #DAE7FE; + font-family: sans-serif; +} + +/* File view (detail): test percentage entry */ +td.testPer +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #DAE7FE; + font-family: sans-serif; +} + +/* File view (detail): test lines count entry */ +td.testNum +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #DAE7FE; + font-family: sans-serif; +} + +/* Test case descriptions: test name format*/ +dt +{ + font-family: sans-serif; + font-weight: bold; +} + +/* Test case descriptions: description table body */ +td.testDescription +{ + padding-top: 10px; + padding-left: 30px; + padding-bottom: 10px; + padding-right: 30px; + background-color: #DAE7FE; +} + +/* Source code view: function entry */ +td.coverFn +{ + text-align: left; + padding-left: 10px; + padding-right: 20px; + color: #284FA8; + background-color: #DAE7FE; + font-family: monospace; +} + +/* Source code view: function entry zero count*/ +td.coverFnLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #FF0000; + font-weight: bold; + font-family: sans-serif; +} + +/* Source code view: function entry nonzero count*/ +td.coverFnHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #DAE7FE; + font-weight: bold; + font-family: sans-serif; +} + +/* Source code view: source code format */ +pre.source +{ + font-family: monospace; + white-space: pre; + margin-top: 2px; +} + +/* Source code view: line number format */ +span.lineNum +{ + background-color: #EFE383; +} + +/* Source code view: format for lines which were executed */ +td.lineCov, +span.lineCov +{ + background-color: #CAD7FE; +} + +/* Source code view: format for Cov legend */ +span.coverLegendCov +{ + padding-left: 10px; + padding-right: 10px; + padding-bottom: 2px; + background-color: #CAD7FE; +} + +/* Source code view: format for lines which were not executed */ +td.lineNoCov, +span.lineNoCov +{ + background-color: #FF6230; +} + +/* Source code view: format for NoCov legend */ +span.coverLegendNoCov +{ + padding-left: 10px; + padding-right: 10px; + padding-bottom: 2px; + background-color: #FF6230; +} + +/* Source code view (function table): standard link - visited format */ +td.lineNoCov > a:visited, +td.lineCov > a:visited +{ + color: black; + text-decoration: underline; +} + +/* Source code view: format for lines which were executed only in a + previous version */ +span.lineDiffCov +{ + background-color: #B5F7AF; +} + +/* Source code view: format for branches which were executed + * and taken */ +span.branchCov +{ + background-color: #CAD7FE; +} + +/* Source code view: format for branches which were executed + * but not taken */ +span.branchNoCov +{ + background-color: #FF6230; +} + +/* Source code view: format for branches which were not executed */ +span.branchNoExec +{ + background-color: #FF6230; +} + +/* Source code view: format for the source code heading line */ +pre.sourceHeading +{ + white-space: pre; + font-family: monospace; + font-weight: bold; + margin: 0px; +} + +/* All views: header legend value for low rate */ +td.headerValueLegL +{ + font-family: sans-serif; + text-align: center; + white-space: nowrap; + padding-left: 4px; + padding-right: 2px; + background-color: #FF0000; + font-size: 80%; +} + +/* All views: header legend value for med rate */ +td.headerValueLegM +{ + font-family: sans-serif; + text-align: center; + white-space: nowrap; + padding-left: 2px; + padding-right: 2px; + background-color: #FFEA20; + font-size: 80%; +} + +/* All views: header legend value for hi rate */ +td.headerValueLegH +{ + font-family: sans-serif; + text-align: center; + white-space: nowrap; + padding-left: 2px; + padding-right: 4px; + background-color: #A7FC9D; + font-size: 80%; +} + +/* All views except source code view: legend format for low coverage */ +span.coverLegendCovLo +{ + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + background-color: #FF0000; +} + +/* All views except source code view: legend format for med coverage */ +span.coverLegendCovMed +{ + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + background-color: #FFEA20; +} + +/* All views except source code view: legend format for hi coverage */ +span.coverLegendCovHi +{ + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + background-color: #A7FC9D; +} diff --git a/coverage/glass.png b/coverage/glass.png new file mode 100644 index 000000000..e1abc0068 Binary files /dev/null and b/coverage/glass.png differ diff --git a/coverage/index-sort-f.html b/coverage/index-sort-f.html new file mode 100644 index 000000000..24cc4c4dc --- /dev/null +++ b/coverage/index-sort-f.html @@ -0,0 +1,203 @@ + + + + + + + LCOV - unnamed + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top levelHitTotalCoverage
Test:unnamedLines:2180320668.0 %
Date:2024-04-23 03:30:56Functions:23754743.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
utils/linting/src +
0.0%
+
0.0 %0 / 1180.0 %0 / 22
utils/testing/src +
0.0%
+
0.0 %0 / 2970.0 %0 / 45
driver/src +
23.7%23.7%
+
23.7 %69 / 29114.7 %5 / 34
dylint-link/src +
46.7%46.7%
+
46.7 %84 / 18020.8 %5 / 24
cargo-dylint/src +
92.0%92.0%
+
92.0 %150 / 16329.5 %13 / 44
dylint/src/library_packages/cargo_cli +
87.0%87.0%
+
87.0 %227 / 26139.7 %29 / 73
dylint/src/library_packages +
85.8%85.8%
+
85.8 %217 / 25353.7 %29 / 54
dylint/src/package_options +
92.3%92.3%
+
92.3 %240 / 26054.1 %20 / 37
internal/src +
88.0%88.0%
+
88.0 %492 / 55959.7 %74 / 124
dylint/src +
85.3%85.3%
+
85.3 %568 / 66663.2 %43 / 68
dylint/src/library_packages/cargo_cli/util +
66.7%66.7%
+
66.7 %40 / 6085.7 %6 / 7
dylint/src/name_toolchain_map +
94.9%94.9%
+
94.9 %93 / 9886.7 %13 / 15
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/index-sort-l.html b/coverage/index-sort-l.html new file mode 100644 index 000000000..16e38d6d9 --- /dev/null +++ b/coverage/index-sort-l.html @@ -0,0 +1,203 @@ + + + + + + + LCOV - unnamed + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top levelHitTotalCoverage
Test:unnamedLines:2180320668.0 %
Date:2024-04-23 03:30:56Functions:23754743.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
utils/linting/src +
0.0%
+
0.0 %0 / 1180.0 %0 / 22
utils/testing/src +
0.0%
+
0.0 %0 / 2970.0 %0 / 45
driver/src +
23.7%23.7%
+
23.7 %69 / 29114.7 %5 / 34
dylint-link/src +
46.7%46.7%
+
46.7 %84 / 18020.8 %5 / 24
dylint/src/library_packages/cargo_cli/util +
66.7%66.7%
+
66.7 %40 / 6085.7 %6 / 7
dylint/src +
85.3%85.3%
+
85.3 %568 / 66663.2 %43 / 68
dylint/src/library_packages +
85.8%85.8%
+
85.8 %217 / 25353.7 %29 / 54
dylint/src/library_packages/cargo_cli +
87.0%87.0%
+
87.0 %227 / 26139.7 %29 / 73
internal/src +
88.0%88.0%
+
88.0 %492 / 55959.7 %74 / 124
cargo-dylint/src +
92.0%92.0%
+
92.0 %150 / 16329.5 %13 / 44
dylint/src/package_options +
92.3%92.3%
+
92.3 %240 / 26054.1 %20 / 37
dylint/src/name_toolchain_map +
94.9%94.9%
+
94.9 %93 / 9886.7 %13 / 15
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/index.html b/coverage/index.html new file mode 100644 index 000000000..b487aa941 --- /dev/null +++ b/coverage/index.html @@ -0,0 +1,203 @@ + + + + + + + LCOV - unnamed + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top levelHitTotalCoverage
Test:unnamedLines:2180320668.0 %
Date:2024-04-23 03:30:56Functions:23754743.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
cargo-dylint/src +
92.0%92.0%
+
92.0 %150 / 16329.5 %13 / 44
driver/src +
23.7%23.7%
+
23.7 %69 / 29114.7 %5 / 34
dylint-link/src +
46.7%46.7%
+
46.7 %84 / 18020.8 %5 / 24
dylint/src +
85.3%85.3%
+
85.3 %568 / 66663.2 %43 / 68
dylint/src/library_packages +
85.8%85.8%
+
85.8 %217 / 25353.7 %29 / 54
dylint/src/library_packages/cargo_cli +
87.0%87.0%
+
87.0 %227 / 26139.7 %29 / 73
dylint/src/library_packages/cargo_cli/util +
66.7%66.7%
+
66.7 %40 / 6085.7 %6 / 7
dylint/src/name_toolchain_map +
94.9%94.9%
+
94.9 %93 / 9886.7 %13 / 15
dylint/src/package_options +
92.3%92.3%
+
92.3 %240 / 26054.1 %20 / 37
internal/src +
88.0%88.0%
+
88.0 %492 / 55959.7 %74 / 124
utils/linting/src +
0.0%
+
0.0 %0 / 1180.0 %0 / 22
utils/testing/src +
0.0%
+
0.0 %0 / 2970.0 %0 / 45
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/cargo.rs.func-sort-c.html b/coverage/internal/src/cargo.rs.func-sort-c.html new file mode 100644 index 000000000..acc0cbbcc --- /dev/null +++ b/coverage/internal/src/cargo.rs.func-sort-c.html @@ -0,0 +1,172 @@ + + + + + + + LCOV - unnamed - internal/src/cargo.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - cargo.rs (source / functions)HitTotalCoverage
Test:unnamedLines:10812387.8 %
Date:2024-04-23 03:30:56Functions:182572.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint_internal::cargo::Builder>::quiet::<_>0
<dylint_internal::cargo::_::InternalBitFlags as core::str::traits::FromStr>::from_str::{closure#0}0
dylint_internal::cargo::package::{closure#1}0
dylint_internal::cargo::package_with_root::{closure#0}::{closure#0}0
dylint_internal::cargo::package_with_root::{closure#1}0
dylint_internal::cargo::run0
dylint_internal::cargo::update0
dylint_internal::cargo::fix1
dylint_internal::cargo::test4
dylint_internal::cargo::STABLE_CARGO::{closure#0}6
<dylint_internal::cargo::Builder>::quiet::<dylint_internal::cargo::Quiet>9
dylint_internal::cargo::fetch9
dylint_internal::cargo::current_metadata12
<dylint_internal::cargo::Builder>::stable18
dylint_internal::cargo::init18
dylint_internal::cargo::check20
dylint_internal::cargo::package_with_root27
<dylint_internal::cargo::Builder>::quiet::<bool>34
<dylint_internal::cargo::Quiet as core::convert::From<bool>>::from34
dylint_internal::cargo::build53
dylint_internal::cargo::package60
<dylint_internal::cargo::Builder>::build105
<dylint_internal::cargo::Builder>::new105
dylint_internal::cargo::package::{closure#0}210
dylint_internal::cargo::package_with_root::{closure#0}251
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/cargo.rs.func.html b/coverage/internal/src/cargo.rs.func.html new file mode 100644 index 000000000..18d263ab5 --- /dev/null +++ b/coverage/internal/src/cargo.rs.func.html @@ -0,0 +1,172 @@ + + + + + + + LCOV - unnamed - internal/src/cargo.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - cargo.rs (source / functions)HitTotalCoverage
Test:unnamedLines:10812387.8 %
Date:2024-04-23 03:30:56Functions:182572.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint_internal::cargo::Builder>::build105
<dylint_internal::cargo::Builder>::new105
<dylint_internal::cargo::Builder>::quiet::<_>0
<dylint_internal::cargo::Builder>::quiet::<bool>34
<dylint_internal::cargo::Builder>::quiet::<dylint_internal::cargo::Quiet>9
<dylint_internal::cargo::Builder>::stable18
<dylint_internal::cargo::Quiet as core::convert::From<bool>>::from34
<dylint_internal::cargo::_::InternalBitFlags as core::str::traits::FromStr>::from_str::{closure#0}0
dylint_internal::cargo::STABLE_CARGO::{closure#0}6
dylint_internal::cargo::build53
dylint_internal::cargo::check20
dylint_internal::cargo::current_metadata12
dylint_internal::cargo::fetch9
dylint_internal::cargo::fix1
dylint_internal::cargo::init18
dylint_internal::cargo::package60
dylint_internal::cargo::package::{closure#0}210
dylint_internal::cargo::package::{closure#1}0
dylint_internal::cargo::package_with_root27
dylint_internal::cargo::package_with_root::{closure#0}251
dylint_internal::cargo::package_with_root::{closure#0}::{closure#0}0
dylint_internal::cargo::package_with_root::{closure#1}0
dylint_internal::cargo::run0
dylint_internal::cargo::test4
dylint_internal::cargo::update0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/cargo.rs.gcov.html b/coverage/internal/src/cargo.rs.gcov.html new file mode 100644 index 000000000..f6cc4cb48 --- /dev/null +++ b/coverage/internal/src/cargo.rs.gcov.html @@ -0,0 +1,285 @@ + + + + + + + LCOV - unnamed - internal/src/cargo.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - cargo.rs (source / functions)HitTotalCoverage
Test:unnamedLines:10812387.8 %
Date:2024-04-23 03:30:56Functions:182572.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use crate::CommandExt;
+       2             : use ansi_term::Style;
+       3             : use anyhow::{anyhow, ensure, Result};
+       4             : use bitflags::bitflags;
+       5             : use cargo_metadata::{Metadata, MetadataCommand, Package, PackageId};
+       6             : use is_terminal::IsTerminal;
+       7             : use once_cell::sync::Lazy;
+       8             : use std::{
+       9             :     io::Write,
+      10             :     path::{Path, PathBuf},
+      11             :     process::{Command, Stdio},
+      12             : };
+      13             : 
+      14             : #[allow(clippy::module_name_repetitions)]
+      15             : pub use home::cargo_home;
+      16             : 
+      17           6 : static STABLE_CARGO: Lazy<PathBuf> = Lazy::new(|| {
+      18           6 :     let mut command = Command::new("rustup");
+      19           6 :     command.args(["+stable", "which", "cargo"]);
+      20           6 :     let output = command.logged_output(true).unwrap();
+      21           6 :     assert!(output.status.success());
+      22           6 :     let stdout = String::from_utf8(output.stdout).unwrap();
+      23           6 :     PathBuf::from(stdout.trim_end())
+      24           6 : });
+      25             : 
+      26           0 : bitflags! {
+      27           0 :     pub struct Quiet: u8 {
+      28           0 :         const MESSAGE = 1 << 0;
+      29           0 :         const STDERR = 1 << 1;
+      30           0 :     }
+      31           0 : }
+      32             : 
+      33             : impl From<bool> for Quiet {
+      34          34 :     fn from(value: bool) -> Self {
+      35          34 :         if value {
+      36           9 :             Self::all()
+      37             :         } else {
+      38          25 :             Self::empty()
+      39             :         }
+      40          34 :     }
+      41             : }
+      42             : 
+      43             : /// A `cargo` command builder
+      44             : ///
+      45             : /// Note that [`std::process::Command`]is itself a builder. So technically that makes this a
+      46             : /// "builder builder".
+      47             : pub struct Builder {
+      48             :     subcommand: String,
+      49             :     verb: String,
+      50             :     description: String,
+      51             :     quiet: Quiet,
+      52             :     stable: bool,
+      53             : }
+      54             : 
+      55             : #[must_use]
+      56          53 : pub fn build(description: &str) -> Builder {
+      57          53 :     Builder::new("build", "Building", description)
+      58          53 : }
+      59             : 
+      60             : #[must_use]
+      61          20 : pub fn check(description: &str) -> Builder {
+      62          20 :     Builder::new("check", "Checking", description)
+      63          20 : }
+      64             : 
+      65             : #[must_use]
+      66           9 : pub fn fetch(description: &str) -> Builder {
+      67           9 :     Builder::new("fetch", "Fetching", description)
+      68           9 : }
+      69             : 
+      70             : #[must_use]
+      71           1 : pub fn fix(description: &str) -> Builder {
+      72           1 :     Builder::new("fix", "Fixing", description)
+      73           1 : }
+      74             : 
+      75             : #[must_use]
+      76          18 : pub fn init(description: &str) -> Builder {
+      77          18 :     Builder::new("init", "Initializing", description)
+      78          18 : }
+      79             : 
+      80             : #[must_use]
+      81           0 : pub fn run(description: &str) -> Builder {
+      82           0 :     Builder::new("run", "Running", description)
+      83           0 : }
+      84             : 
+      85             : #[must_use]
+      86           4 : pub fn test(description: &str) -> Builder {
+      87           4 :     Builder::new("test", "Testing", description)
+      88           4 : }
+      89             : 
+      90             : #[must_use]
+      91           0 : pub fn update(description: &str) -> Builder {
+      92           0 :     Builder::new("update", "Updating", description)
+      93           0 : }
+      94             : 
+      95             : impl Builder {
+      96         105 :     fn new(subcommand: &str, verb: &str, description: &str) -> Self {
+      97         105 :         Self {
+      98         105 :             subcommand: subcommand.to_owned(),
+      99         105 :             verb: verb.to_owned(),
+     100         105 :             description: description.to_owned(),
+     101         105 :             quiet: Quiet::empty(),
+     102         105 :             stable: false,
+     103         105 :         }
+     104         105 :     }
+     105             : 
+     106             :     /// Whether to allow the command to write to standard error.
+     107          43 :     pub fn quiet(&mut self, value: impl Into<Quiet>) -> &mut Self {
+     108          43 :         let value = value.into();
+     109          43 :         // smoelius: `cargo check` and `cargo fix` are never silenced.
+     110          43 :         if !value.is_empty() {
+     111          18 :             assert!(!matches!(self.subcommand.as_str(), "check" | "fix"));
+     112          25 :         }
+     113          43 :         self.quiet = value;
+     114          43 :         self
+     115          43 :     }
+     116             : 
+     117             :     /// Whether to use a cached path to stable `cargo`. Using the cached path avoids repeated calls
+     118             :     /// to `rustup`.
+     119          18 :     pub fn stable(&mut self, value: bool) -> &mut Self {
+     120          18 :         self.stable = value;
+     121          18 :         self
+     122          18 :     }
+     123             : 
+     124             :     /// Consumes the builder and returns a [`std::process::Command`].
+     125         105 :     pub fn build(&mut self) -> Command {
+     126         105 :         if !self.quiet.contains(Quiet::MESSAGE) {
+     127             :             // smoelius: Writing directly to `stderr` prevents capture by `libtest`.
+     128          87 :             let message = format!("{} {}", self.verb, self.description);
+     129          87 :             std::io::stderr()
+     130          87 :                 .write_fmt(format_args!(
+     131          87 :                     "{}\n",
+     132          87 :                     if std::io::stderr().is_terminal() {
+     133           0 :                         Style::new().bold()
+     134             :                     } else {
+     135          87 :                         Style::new()
+     136             :                     }
+     137          87 :                     .paint(message)
+     138          87 :                 ))
+     139          87 :                 .expect("Could not write to stderr");
+     140          18 :         }
+     141         105 :         let mut command = if self.stable {
+     142          18 :             Command::new(&*STABLE_CARGO)
+     143             :         } else {
+     144          87 :             Command::new("cargo")
+     145             :         };
+     146             :         #[cfg(windows)]
+     147             :         {
+     148             :             // smoelius: Work around: https://github.com/rust-lang/rustup/pull/2978
+     149             :             let cargo_home = cargo_home().unwrap();
+     150             :             let old_path = crate::env::var(crate::env::PATH).unwrap();
+     151             :             let new_path = std::env::join_paths(
+     152             :                 std::iter::once(Path::new(&cargo_home).join("bin"))
+     153             :                     .chain(std::env::split_paths(&old_path)),
+     154             :             )
+     155             :             .unwrap();
+     156             :             command.envs(vec![(crate::env::PATH, new_path)]);
+     157             :         }
+     158         105 :         command.args([&self.subcommand]);
+     159         105 :         if self.quiet.contains(Quiet::STDERR) {
+     160           9 :             command.stderr(Stdio::null());
+     161          96 :         }
+     162         105 :         command
+     163         105 :     }
+     164             : }
+     165             : 
+     166             : /// Get metadata based on the current directory.
+     167          12 : pub fn current_metadata() -> Result<Metadata> {
+     168          12 :     MetadataCommand::new().no_deps().exec().map_err(Into::into)
+     169          12 : }
+     170             : 
+     171          27 : pub fn package_with_root(metadata: &Metadata, package_root: &Path) -> Result<Package> {
+     172          27 :     let packages = metadata
+     173          27 :         .packages
+     174          27 :         .iter()
+     175         251 :         .map(|package| {
+     176         251 :             let path = package
+     177         251 :                 .manifest_path
+     178         251 :                 .parent()
+     179         251 :                 .ok_or_else(|| anyhow!("Could not get parent directory"))?;
+     180         251 :             Ok(if path == package_root {
+     181          27 :                 Some(package)
+     182             :             } else {
+     183         224 :                 None
+     184             :             })
+     185         251 :         })
+     186          27 :         .filter_map(Result::transpose)
+     187          27 :         .collect::<Result<Vec<_>>>()?;
+     188             : 
+     189          27 :     ensure!(
+     190          27 :         packages.len() <= 1,
+     191           0 :         "Found multiple packages in `{}`",
+     192           0 :         package_root.to_string_lossy()
+     193             :     );
+     194             : 
+     195          27 :     packages
+     196          27 :         .into_iter()
+     197          27 :         .next()
+     198          27 :         .cloned()
+     199          27 :         .ok_or_else(|| anyhow!("Found no packages in `{}`", package_root.to_string_lossy()))
+     200          27 : }
+     201             : 
+     202          60 : pub fn package(metadata: &Metadata, package_id: &PackageId) -> Result<Package> {
+     203          60 :     metadata
+     204          60 :         .packages
+     205          60 :         .iter()
+     206         210 :         .find(|package| package.id == *package_id)
+     207          60 :         .cloned()
+     208          60 :         .ok_or_else(|| anyhow!("Could not find package"))
+     209          60 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/clippy_utils.rs.func-sort-c.html b/coverage/internal/src/clippy_utils.rs.func-sort-c.html new file mode 100644 index 000000000..acdca589a --- /dev/null +++ b/coverage/internal/src/clippy_utils.rs.func-sort-c.html @@ -0,0 +1,164 @@ + + + + + + + LCOV - unnamed - internal/src/clippy_utils.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - clippy_utils.rs (source / functions)HitTotalCoverage
Test:unnamedLines:689174.7 %
Date:2024-04-23 03:30:56Functions:132356.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::clippy_utils::clippy_utils_package_version::{closure#0}0
dylint_internal::clippy_utils::clippy_utils_package_version::{closure#2}0
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision::{closure#0}0
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision::{closure#2}0
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision::{closure#3}0
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision::{closure#6}0
dylint_internal::clippy_utils::set_toolchain_channel::{closure#0}0
dylint_internal::clippy_utils::set_toolchain_channel::{closure#3}0
dylint_internal::clippy_utils::toolchain_channel::{closure#0}0
dylint_internal::clippy_utils::toolchain_channel::{closure#2}0
dylint_internal::clippy_utils::clippy_utils_version_from_rust_version2
dylint_internal::clippy_utils::clippy_utils_version_from_rust_version::{closure#0}2
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision4
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision::{closure#1}4
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision::{closure#4}4
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision::{closure#5}4
dylint_internal::clippy_utils::set_toolchain_channel5
dylint_internal::clippy_utils::set_toolchain_channel::{closure#1}5
dylint_internal::clippy_utils::set_toolchain_channel::{closure#2}5
dylint_internal::clippy_utils::clippy_utils_package_version11685
dylint_internal::clippy_utils::clippy_utils_package_version::{closure#1}11685
dylint_internal::clippy_utils::toolchain_channel11688
dylint_internal::clippy_utils::toolchain_channel::{closure#1}11688
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/clippy_utils.rs.func.html b/coverage/internal/src/clippy_utils.rs.func.html new file mode 100644 index 000000000..7fbfac6d3 --- /dev/null +++ b/coverage/internal/src/clippy_utils.rs.func.html @@ -0,0 +1,164 @@ + + + + + + + LCOV - unnamed - internal/src/clippy_utils.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - clippy_utils.rs (source / functions)HitTotalCoverage
Test:unnamedLines:689174.7 %
Date:2024-04-23 03:30:56Functions:132356.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::clippy_utils::clippy_utils_package_version11685
dylint_internal::clippy_utils::clippy_utils_package_version::{closure#0}0
dylint_internal::clippy_utils::clippy_utils_package_version::{closure#1}11685
dylint_internal::clippy_utils::clippy_utils_package_version::{closure#2}0
dylint_internal::clippy_utils::clippy_utils_version_from_rust_version2
dylint_internal::clippy_utils::clippy_utils_version_from_rust_version::{closure#0}2
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision4
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision::{closure#0}0
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision::{closure#1}4
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision::{closure#2}0
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision::{closure#3}0
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision::{closure#4}4
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision::{closure#5}4
dylint_internal::clippy_utils::set_clippy_utils_dependency_revision::{closure#6}0
dylint_internal::clippy_utils::set_toolchain_channel5
dylint_internal::clippy_utils::set_toolchain_channel::{closure#0}0
dylint_internal::clippy_utils::set_toolchain_channel::{closure#1}5
dylint_internal::clippy_utils::set_toolchain_channel::{closure#2}5
dylint_internal::clippy_utils::set_toolchain_channel::{closure#3}0
dylint_internal::clippy_utils::toolchain_channel11688
dylint_internal::clippy_utils::toolchain_channel::{closure#0}0
dylint_internal::clippy_utils::toolchain_channel::{closure#1}11688
dylint_internal::clippy_utils::toolchain_channel::{closure#2}0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/clippy_utils.rs.gcov.html b/coverage/internal/src/clippy_utils.rs.gcov.html new file mode 100644 index 000000000..cd4cf4a41 --- /dev/null +++ b/coverage/internal/src/clippy_utils.rs.gcov.html @@ -0,0 +1,182 @@ + + + + + + + LCOV - unnamed - internal/src/clippy_utils.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - clippy_utils.rs (source / functions)HitTotalCoverage
Test:unnamedLines:689174.7 %
Date:2024-04-23 03:30:56Functions:132356.5 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use anyhow::{anyhow, Context, Result};
+       2             : use semver::Version;
+       3             : use std::{
+       4             :     fs::{read_to_string, write},
+       5             :     path::Path,
+       6             : };
+       7             : use toml_edit::{DocumentMut, Item, Value};
+       8             : 
+       9             : #[allow(clippy::module_name_repetitions)]
+      10           2 : pub fn clippy_utils_version_from_rust_version(rust_version: &str) -> Result<String> {
+      11           2 :     Version::parse(rust_version.strip_prefix("rust-").unwrap_or(rust_version))
+      12           2 :         .map(|version| Version::new(0, version.major, version.minor).to_string())
+      13           2 :         .map_err(Into::into)
+      14           2 : }
+      15             : 
+      16             : #[allow(clippy::module_name_repetitions)]
+      17       11685 : pub fn clippy_utils_package_version(path: &Path) -> Result<String> {
+      18       11685 :     let cargo_toml = path.join("clippy_utils/Cargo.toml");
+      19       11685 :     let contents = read_to_string(&cargo_toml).with_context(|| {
+      20           0 :         format!(
+      21           0 :             "`read_to_string` failed for `{}`",
+      22           0 :             cargo_toml.to_string_lossy(),
+      23           0 :         )
+      24       11685 :     })?;
+      25       11685 :     let document = contents.parse::<DocumentMut>()?;
+      26       11685 :     document
+      27       11685 :         .as_table()
+      28       11685 :         .get("package")
+      29       11685 :         .and_then(Item::as_table)
+      30       11685 :         .and_then(|table| table.get("version"))
+      31       11685 :         .and_then(Item::as_str)
+      32       11685 :         .map(ToOwned::to_owned)
+      33       11685 :         .ok_or_else(|| anyhow!("Could not determine `clippy_utils` version"))
+      34       11685 : }
+      35             : 
+      36           4 : pub fn set_clippy_utils_dependency_revision(path: &Path, rev: &str) -> Result<()> {
+      37           4 :     let cargo_toml = path.join("Cargo.toml");
+      38           4 :     let contents = read_to_string(&cargo_toml).with_context(|| {
+      39           0 :         format!(
+      40           0 :             "`read_to_string` failed for `{}`",
+      41           0 :             cargo_toml.to_string_lossy(),
+      42           0 :         )
+      43           4 :     })?;
+      44           4 :     let mut document = contents.parse::<DocumentMut>()?;
+      45             :     // smoelius: First check `dependencies` for `clippy_utils`.
+      46           4 :     let mut clippy_utils = document
+      47           4 :         .as_table_mut()
+      48           4 :         .get_mut("dependencies")
+      49           4 :         .and_then(Item::as_table_mut)
+      50           4 :         .and_then(|table| table.get_mut("clippy_utils"));
+      51           4 :     // smoelius: It it's not found there, check `workspace.dependencies`.
+      52           4 :     if clippy_utils.is_none() {
+      53           0 :         clippy_utils = document
+      54           0 :             .as_table_mut()
+      55           0 :             .get_mut("workspace")
+      56           0 :             .and_then(Item::as_table_mut)
+      57           0 :             .and_then(|table| table.get_mut("dependencies"))
+      58           0 :             .and_then(Item::as_table_mut)
+      59           0 :             .and_then(|table| table.get_mut("clippy_utils"));
+      60           4 :     };
+      61           4 :     clippy_utils
+      62           4 :         .and_then(Item::as_inline_table_mut)
+      63           4 :         .and_then(|table| table.get_mut("rev"))
+      64           4 :         .map(|value| *value = Value::from(rev))
+      65           4 :         .ok_or_else(|| anyhow!("Could not set `clippy_utils` revision"))?;
+      66           4 :     write(cargo_toml, document.to_string()).map_err(Into::into)
+      67           4 : }
+      68             : 
+      69       11688 : pub fn toolchain_channel(path: &Path) -> Result<String> {
+      70       11688 :     let rust_toolchain = path.join("rust-toolchain");
+      71       11688 :     let contents = read_to_string(&rust_toolchain).with_context(|| {
+      72           0 :         format!(
+      73           0 :             "`read_to_string` failed for `{}`",
+      74           0 :             rust_toolchain.to_string_lossy(),
+      75           0 :         )
+      76       11688 :     })?;
+      77       11688 :     let document = contents.parse::<DocumentMut>()?;
+      78       11688 :     document
+      79       11688 :         .as_table()
+      80       11688 :         .get("toolchain")
+      81       11688 :         .and_then(Item::as_table)
+      82       11688 :         .and_then(|table| table.get("channel"))
+      83       11688 :         .and_then(Item::as_str)
+      84       11688 :         .map(ToOwned::to_owned)
+      85       11688 :         .ok_or_else(|| anyhow!("Could not determine Rust toolchain channel"))
+      86       11688 : }
+      87             : 
+      88           5 : pub fn set_toolchain_channel(path: &Path, channel: &str) -> Result<()> {
+      89           5 :     let rust_toolchain = path.join("rust-toolchain");
+      90           5 :     let contents = read_to_string(&rust_toolchain).with_context(|| {
+      91           0 :         format!(
+      92           0 :             "`read_to_string` failed for `{}`",
+      93           0 :             rust_toolchain.to_string_lossy(),
+      94           0 :         )
+      95           5 :     })?;
+      96           5 :     let mut document = contents.parse::<DocumentMut>()?;
+      97           5 :     document
+      98           5 :         .as_table_mut()
+      99           5 :         .get_mut("toolchain")
+     100           5 :         .and_then(Item::as_table_mut)
+     101           5 :         .and_then(|table| table.get_mut("channel"))
+     102           5 :         .and_then(Item::as_value_mut)
+     103           5 :         .map(|value| *value = Value::from(channel))
+     104           5 :         .ok_or_else(|| anyhow!("Could not set Rust toolchain channel"))?;
+     105           5 :     write(rust_toolchain, document.to_string()).map_err(Into::into)
+     106           5 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/command.rs.func-sort-c.html b/coverage/internal/src/command.rs.func-sort-c.html new file mode 100644 index 000000000..63291724f --- /dev/null +++ b/coverage/internal/src/command.rs.func-sort-c.html @@ -0,0 +1,92 @@ + + + + + + + LCOV - unnamed - internal/src/command.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - command.rs (source / functions)HitTotalCoverage
Test:unnamedLines:434791.5 %
Date:2024-04-23 03:30:56Functions:3560.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<std::process::Command as dylint_internal::command::CommandExt>::logged_output::{closure#0}0
<std::process::Command as dylint_internal::command::CommandExt>::success::{closure#0}0
dylint_internal::command::driver33
<std::process::Command as dylint_internal::command::CommandExt>::logged_output74
<std::process::Command as dylint_internal::command::CommandExt>::success125
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/command.rs.func.html b/coverage/internal/src/command.rs.func.html new file mode 100644 index 000000000..1fd571c2a --- /dev/null +++ b/coverage/internal/src/command.rs.func.html @@ -0,0 +1,92 @@ + + + + + + + LCOV - unnamed - internal/src/command.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - command.rs (source / functions)HitTotalCoverage
Test:unnamedLines:434791.5 %
Date:2024-04-23 03:30:56Functions:3560.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<std::process::Command as dylint_internal::command::CommandExt>::logged_output74
<std::process::Command as dylint_internal::command::CommandExt>::logged_output::{closure#0}0
<std::process::Command as dylint_internal::command::CommandExt>::success125
<std::process::Command as dylint_internal::command::CommandExt>::success::{closure#0}0
dylint_internal::command::driver33
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/command.rs.gcov.html b/coverage/internal/src/command.rs.gcov.html new file mode 100644 index 000000000..a270b0c5e --- /dev/null +++ b/coverage/internal/src/command.rs.gcov.html @@ -0,0 +1,154 @@ + + + + + + + LCOV - unnamed - internal/src/command.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - command.rs (source / functions)HitTotalCoverage
Test:unnamedLines:434791.5 %
Date:2024-04-23 03:30:56Functions:3560.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use anyhow::{ensure, Context, Result};
+       2             : use std::{
+       3             :     path::Path,
+       4             :     process::{Command, Output},
+       5             : };
+       6             : 
+       7             : #[allow(clippy::module_name_repetitions)]
+       8             : pub trait CommandExt {
+       9             :     fn logged_output(&mut self, require_success: bool) -> Result<Output>;
+      10             :     fn success(&mut self) -> Result<()>;
+      11             : }
+      12             : 
+      13             : impl CommandExt for Command {
+      14             :     #[cfg_attr(dylint_lib = "general", allow(non_local_effect_before_error_return))]
+      15             :     #[cfg_attr(dylint_lib = "overscoped_allow", allow(overscoped_allow))]
+      16          74 :     fn logged_output(&mut self, require_success: bool) -> Result<Output> {
+      17          74 :         log::debug!("{:?}", self.get_envs().collect::<Vec<_>>());
+      18          74 :         log::debug!("{:?}", self.get_current_dir());
+      19          74 :         log::debug!("{:?}", self);
+      20             : 
+      21             :         #[allow(clippy::disallowed_methods)]
+      22          74 :         let output = self
+      23          74 :             .output()
+      24          74 :             .with_context(|| format!("Could not get output of `{self:?}`"))?;
+      25             : 
+      26          74 :         ensure!(
+      27          74 :             !require_success || output.status.success(),
+      28           0 :             "command failed: {:?}\nstdout: {:?}\nstderr: {:?}",
+      29           0 :             self,
+      30           0 :             std::str::from_utf8(&output.stdout).unwrap_or_default(),
+      31           0 :             std::str::from_utf8(&output.stderr).unwrap_or_default()
+      32             :         );
+      33             : 
+      34          74 :         Ok(output)
+      35          74 :     }
+      36             : 
+      37             :     // smoelius: Why not get the status by calling `self.output()`? Because we don't want stdout and
+      38             :     // stderr to be captured.
+      39             :     #[cfg_attr(dylint_lib = "general", allow(non_local_effect_before_error_return))]
+      40             :     #[cfg_attr(dylint_lib = "overscoped_allow", allow(overscoped_allow))]
+      41         125 :     fn success(&mut self) -> Result<()> {
+      42         125 :         log::debug!("{:?}", self.get_envs().collect::<Vec<_>>());
+      43         125 :         log::debug!("{:?}", self.get_current_dir());
+      44         125 :         log::debug!("{:?}", self);
+      45             : 
+      46         125 :         let status = self
+      47         125 :             .status()
+      48         125 :             .with_context(|| format!("Could not get status of `{self:?}`"))?;
+      49             : 
+      50         125 :         ensure!(status.success(), "command failed: {:?}", self);
+      51             : 
+      52         122 :         Ok(())
+      53         125 :     }
+      54             : }
+      55             : 
+      56             : #[allow(unused_variables)]
+      57          33 : pub fn driver(toolchain: &str, driver: &Path) -> Result<Command> {
+      58          33 :     #[allow(unused_mut)]
+      59          33 :     let mut command = Command::new(driver);
+      60          33 :     #[cfg(windows)]
+      61          33 :     {
+      62          33 :         // MinerSebas: To succesfully determine the dylint driver Version on Windows,
+      63          33 :         // it is neccesary to add some Libraries to the Path.
+      64          33 :         let rustup_home = crate::env::var(crate::env::RUSTUP_HOME)?;
+      65          33 :         let old_path = crate::env::var(crate::env::PATH)?;
+      66          33 :         let new_path = std::env::join_paths(
+      67          33 :             std::iter::once(
+      68          33 :                 Path::new(&rustup_home)
+      69          33 :                     .join("toolchains")
+      70          33 :                     .join(toolchain)
+      71          33 :                     .join("bin"),
+      72          33 :             )
+      73          33 :             .chain(std::env::split_paths(&old_path)),
+      74          33 :         )?;
+      75          33 :         command.envs(vec![(crate::env::PATH, new_path)]);
+      76          33 :     }
+      77          33 :     Ok(command)
+      78          33 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/env.rs.func-sort-c.html b/coverage/internal/src/env.rs.func-sort-c.html new file mode 100644 index 000000000..9c0589476 --- /dev/null +++ b/coverage/internal/src/env.rs.func-sort-c.html @@ -0,0 +1,88 @@ + + + + + + + LCOV - unnamed - internal/src/env.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - env.rs (source / functions)HitTotalCoverage
Test:unnamedLines:3650.0 %
Date:2024-04-23 03:30:56Functions:2450.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::env::enabled0
dylint_internal::env::enabled::{closure#0}0
dylint_internal::env::var::{closure#0}70
dylint_internal::env::var77
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/env.rs.func.html b/coverage/internal/src/env.rs.func.html new file mode 100644 index 000000000..48515cea0 --- /dev/null +++ b/coverage/internal/src/env.rs.func.html @@ -0,0 +1,88 @@ + + + + + + + LCOV - unnamed - internal/src/env.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - env.rs (source / functions)HitTotalCoverage
Test:unnamedLines:3650.0 %
Date:2024-04-23 03:30:56Functions:2450.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::env::enabled0
dylint_internal::env::enabled::{closure#0}0
dylint_internal::env::var77
dylint_internal::env::var::{closure#0}70
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/env.rs.gcov.html b/coverage/internal/src/env.rs.gcov.html new file mode 100644 index 000000000..8ab450a46 --- /dev/null +++ b/coverage/internal/src/env.rs.gcov.html @@ -0,0 +1,141 @@ + + + + + + + LCOV - unnamed - internal/src/env.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - env.rs (source / functions)HitTotalCoverage
Test:unnamedLines:3650.0 %
Date:2024-04-23 03:30:56Functions:2450.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use anyhow::{anyhow, Result};
+       2             : 
+       3             : macro_rules! declare_const {
+       4             :     ($var: ident) => {
+       5             :         pub const $var: &str = stringify!($var);
+       6             :     };
+       7             : }
+       8             : 
+       9             : declare_const!(CARGO);
+      10             : declare_const!(CARGO_CRATE_NAME);
+      11             : declare_const!(CARGO_HOME);
+      12             : declare_const!(CARGO_INCREMENTAL);
+      13             : declare_const!(CARGO_MANIFEST_DIR);
+      14             : declare_const!(CARGO_PKG_NAME);
+      15             : declare_const!(CARGO_PRIMARY_PACKAGE);
+      16             : declare_const!(CARGO_TARGET_DIR);
+      17             : declare_const!(CARGO_TERM_COLOR);
+      18             : declare_const!(CI);
+      19             : declare_const!(CLIPPY_DISABLE_DOCS_LINKS);
+      20             : declare_const!(CLIPPY_DRIVER_PATH);
+      21             : declare_const!(DOCS_RS);
+      22             : declare_const!(DYLINT_DRIVER_PATH);
+      23             : declare_const!(DYLINT_LIBRARY_PATH);
+      24             : declare_const!(DYLINT_LIBS);
+      25             : declare_const!(DYLINT_LIST);
+      26             : declare_const!(DYLINT_METADATA);
+      27             : declare_const!(DYLINT_NO_DEPS);
+      28             : declare_const!(DYLINT_RUSTFLAGS);
+      29             : declare_const!(DYLINT_TOML);
+      30             : declare_const!(OUT_DIR);
+      31             : declare_const!(PATH);
+      32             : declare_const!(RUSTC);
+      33             : declare_const!(RUSTC_WORKSPACE_WRAPPER);
+      34             : declare_const!(RUSTFLAGS);
+      35             : declare_const!(RUSTUP_HOME);
+      36             : declare_const!(RUSTUP_TOOLCHAIN);
+      37             : declare_const!(RUST_BACKTRACE);
+      38             : declare_const!(TARGET);
+      39             : 
+      40             : /// Returns true if the environment variable `key` is set to a non-zero value.
+      41             : ///
+      42             : /// # Examples
+      43             : ///
+      44             : /// ```
+      45             : /// use dylint_internal::env::enabled;
+      46             : /// use std::env;
+      47             : ///
+      48             : /// env::set_var("FOO", "1");
+      49             : /// assert_eq!(enabled("FOO"), true);
+      50             : ///
+      51             : /// env::set_var("FOO", "0");
+      52             : /// assert_eq!(enabled("FOO"), false);
+      53             : ///
+      54             : /// env::remove_var("FOO");
+      55             : /// assert_eq!(enabled("FOO"), false);
+      56             : /// ```
+      57             : #[must_use]
+      58           0 : pub fn enabled(key: &str) -> bool {
+      59           0 :     std::env::var(key).map_or(false, |value| value != "0")
+      60           0 : }
+      61             : 
+      62             : /// A wrapper around `std::env::var` that converts the error into an `anyhow::Error`.
+      63          77 : pub fn var(key: &str) -> Result<String> {
+      64          77 :     std::env::var(key).map_err(|err| anyhow!(format!("{err}: {key}")))
+      65          77 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/examples.rs.func-sort-c.html b/coverage/internal/src/examples.rs.func-sort-c.html new file mode 100644 index 000000000..6e148765a --- /dev/null +++ b/coverage/internal/src/examples.rs.func-sort-c.html @@ -0,0 +1,100 @@ + + + + + + + LCOV - unnamed - internal/src/examples.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - examples.rs (source / functions)HitTotalCoverage
Test:unnamedLines:495490.7 %
Date:2024-04-23 03:30:56Functions:4757.1 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::examples::build::{closure#0}0
dylint_internal::examples::iter::{closure#1}::{closure#0}0
dylint_internal::examples::iter::{closure#1}::{closure#1}0
dylint_internal::examples::build2
dylint_internal::examples::iter2
dylint_internal::examples::iter::{closure#1}108
dylint_internal::examples::iter::{closure#0}398
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/examples.rs.func.html b/coverage/internal/src/examples.rs.func.html new file mode 100644 index 000000000..806365c7c --- /dev/null +++ b/coverage/internal/src/examples.rs.func.html @@ -0,0 +1,100 @@ + + + + + + + LCOV - unnamed - internal/src/examples.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - examples.rs (source / functions)HitTotalCoverage
Test:unnamedLines:495490.7 %
Date:2024-04-23 03:30:56Functions:4757.1 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::examples::build2
dylint_internal::examples::build::{closure#0}0
dylint_internal::examples::iter2
dylint_internal::examples::iter::{closure#0}398
dylint_internal::examples::iter::{closure#1}108
dylint_internal::examples::iter::{closure#1}::{closure#0}0
dylint_internal::examples::iter::{closure#1}::{closure#1}0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/examples.rs.gcov.html b/coverage/internal/src/examples.rs.gcov.html new file mode 100644 index 000000000..51be3bbdb --- /dev/null +++ b/coverage/internal/src/examples.rs.gcov.html @@ -0,0 +1,141 @@ + + + + + + + LCOV - unnamed - internal/src/examples.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - examples.rs (source / functions)HitTotalCoverage
Test:unnamedLines:495490.7 %
Date:2024-04-23 03:30:56Functions:4757.1 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use crate::{rustup::SanitizeEnvironment, CommandExt};
+       2             : use anyhow::{anyhow, Context, Result};
+       3             : use std::path::{Path, PathBuf};
+       4             : use walkdir::WalkDir;
+       5             : 
+       6           2 : pub fn build() -> Result<()> {
+       7           2 :     // smoelius: The examples use `dylint-link` as the linker, so it must be built first.
+       8           2 :     #[cfg_attr(dylint_lib = "general", allow(abs_home_path))]
+       9           2 :     crate::cargo::build("dylint-link")
+      10           2 :         .build()
+      11           2 :         .sanitize_environment()
+      12           2 :         .current_dir(Path::new(env!("CARGO_MANIFEST_DIR")).join("../dylint-link"))
+      13           2 :         .success()?;
+      14             : 
+      15          16 :     for example in iter(true)? {
+      16          16 :         let example = example?;
+      17          16 :         let file_name = example
+      18          16 :             .file_name()
+      19          16 :             .ok_or_else(|| anyhow!("Could not get file name"))?;
+      20          16 :         crate::cargo::build(&format!("example `{}`", file_name.to_string_lossy()))
+      21          16 :             .build()
+      22          16 :             .sanitize_environment()
+      23          16 :             .current_dir(&example)
+      24          16 :             .success()?;
+      25             :     }
+      26             : 
+      27           2 :     Ok(())
+      28           2 : }
+      29             : 
+      30           2 : pub fn iter(workspace: bool) -> Result<impl Iterator<Item = Result<PathBuf>>> {
+      31           2 :     #[cfg_attr(dylint_lib = "general", allow(abs_home_path))]
+      32           2 :     let path_buf = Path::new(env!("CARGO_MANIFEST_DIR")).join("../examples");
+      33           2 :     // smoelius: Use `cargo_util::paths::normalize_path` instead of `canonicalize` so as not to
+      34           2 :     // "taint" the path with a path prefix on Windows.
+      35           2 :     let examples = cargo_util::paths::normalize_path(&path_buf);
+      36           2 :     let iter = WalkDir::new(examples)
+      37           2 :         .into_iter()
+      38         398 :         .filter_entry(|entry| entry.depth() <= 2);
+      39           2 :     Ok(iter
+      40         108 :         .map(move |entry| -> Result<Option<PathBuf>> {
+      41         108 :             let entry = entry?;
+      42         108 :             let path = entry.path();
+      43         108 :             let rust_toolchain_path = path.join("rust-toolchain");
+      44         108 :             let cargo_toml_path = path.join("Cargo.toml");
+      45         108 :             if entry.depth() < 1 || !path.is_dir() {
+      46          26 :                 return Ok(None);
+      47          82 :             }
+      48          82 :             if workspace
+      49          82 :                 && rust_toolchain_path.try_exists().with_context(|| {
+      50           0 :                     format!("Could not determine whether {rust_toolchain_path:?} exists")
+      51          82 :                 })?
+      52             :             {
+      53          16 :                 return Ok(Some(path.to_path_buf()));
+      54          66 :             }
+      55          66 :             if !workspace
+      56           0 :                 && cargo_toml_path.try_exists().with_context(|| {
+      57           0 :                     format!("Could not determine whether {cargo_toml_path:?} exists")
+      58           0 :                 })?
+      59             :             {
+      60           0 :                 return Ok(Some(path.to_path_buf()));
+      61          66 :             }
+      62          66 :             Ok(None)
+      63         108 :         })
+      64           2 :         .filter_map(Result::transpose))
+      65           2 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/filename.rs.func-sort-c.html b/coverage/internal/src/filename.rs.func-sort-c.html new file mode 100644 index 000000000..4dcfde43a --- /dev/null +++ b/coverage/internal/src/filename.rs.func-sort-c.html @@ -0,0 +1,88 @@ + + + + + + + LCOV - unnamed - internal/src/filename.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - filename.rs (source / functions)HitTotalCoverage
Test:unnamedLines:2222100.0 %
Date:2024-04-23 03:30:56Functions:44100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::filename::library_filename22
dylint_internal::filename::parse_target_name121
dylint_internal::filename::parse_filename227
dylint_internal::filename::parse_path_filename227
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/filename.rs.func.html b/coverage/internal/src/filename.rs.func.html new file mode 100644 index 000000000..1b0cdb191 --- /dev/null +++ b/coverage/internal/src/filename.rs.func.html @@ -0,0 +1,88 @@ + + + + + + + LCOV - unnamed - internal/src/filename.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - filename.rs (source / functions)HitTotalCoverage
Test:unnamedLines:2222100.0 %
Date:2024-04-23 03:30:56Functions:44100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::filename::library_filename22
dylint_internal::filename::parse_filename227
dylint_internal::filename::parse_path_filename227
dylint_internal::filename::parse_target_name121
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/filename.rs.gcov.html b/coverage/internal/src/filename.rs.gcov.html new file mode 100644 index 000000000..1634d73d7 --- /dev/null +++ b/coverage/internal/src/filename.rs.gcov.html @@ -0,0 +1,171 @@ + + + + + + + LCOV - unnamed - internal/src/filename.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - filename.rs (source / functions)HitTotalCoverage
Test:unnamedLines:2222100.0 %
Date:2024-04-23 03:30:56Functions:44100.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use std::{env::consts, path::Path};
+       2             : 
+       3             : /// Returns the filename of a Dylint library.
+       4             : ///
+       5             : /// # Examples
+       6             : ///
+       7             : /// ```
+       8             : /// use dylint_internal::library_filename;
+       9             : ///
+      10             : /// #[cfg(target_os = "linux")]
+      11             : /// assert_eq!(
+      12             : ///     library_filename("foo", "stable-x86_64-unknown-linux-gnu"),
+      13             : ///     "libfoo@stable-x86_64-unknown-linux-gnu.so"
+      14             : /// );
+      15             : ///
+      16             : /// #[cfg(target_os = "macos")]
+      17             : /// assert_eq!(
+      18             : ///     library_filename("foo", "stable-x86_64-apple-darwin"),
+      19             : ///     "libfoo@stable-x86_64-apple-darwin.dylib"
+      20             : /// );
+      21             : ///
+      22             : /// #[cfg(target_os = "windows")]
+      23             : /// assert_eq!(
+      24             : ///     library_filename("foo", "stable-x86_64-pc-windows-msvc"),
+      25             : ///     "foo@stable-x86_64-pc-windows-msvc.dll"
+      26             : /// );
+      27             : /// ```
+      28             : // smoelius: Build a standard rlib, and the filename will use snake case. `library_filename`'s
+      29             : // behavior is consistent with that.
+      30             : #[allow(clippy::module_name_repetitions, clippy::uninlined_format_args)]
+      31             : #[must_use]
+      32          22 : pub fn library_filename(lib_name: &str, toolchain: &str) -> String {
+      33          22 :     format!(
+      34          22 :         "{}{}@{}{}",
+      35          22 :         consts::DLL_PREFIX,
+      36          22 :         lib_name.replace('-', "_"),
+      37          22 :         toolchain,
+      38          22 :         consts::DLL_SUFFIX
+      39          22 :     )
+      40          22 : }
+      41             : 
+      42             : /// Parses the filename of a Dylint library path into a tuple of (name, toolchain).
+      43             : ///
+      44             : /// # Examples
+      45             : ///
+      46             : /// ```
+      47             : /// use dylint_internal::parse_path_filename;
+      48             : /// use std::path::Path;
+      49             : ///
+      50             : /// #[cfg(target_os = "linux")]
+      51             : /// assert_eq!(
+      52             : ///     parse_path_filename(Path::new("libfoo@stable-x86_64-unknown-linux-gnu.so")),
+      53             : ///     Some((
+      54             : ///         String::from("foo"),
+      55             : ///         String::from("stable-x86_64-unknown-linux-gnu")
+      56             : ///     ))
+      57             : /// );
+      58             : ///
+      59             : /// #[cfg(target_os = "macos")]
+      60             : /// assert_eq!(
+      61             : ///     parse_path_filename(Path::new("libfoo@stable-x86_64-apple-darwin.dylib")),
+      62             : ///     Some((
+      63             : ///         String::from("foo"),
+      64             : ///         String::from("stable-x86_64-apple-darwin")
+      65             : ///     ))
+      66             : /// );
+      67             : ///
+      68             : /// #[cfg(target_os = "windows")]
+      69             : /// assert_eq!(
+      70             : ///     parse_path_filename(Path::new("foo@stable-x86_64-pc-windows-msvc.dll")),
+      71             : ///     Some((
+      72             : ///         String::from("foo"),
+      73             : ///         String::from("stable-x86_64-pc-windows-msvc")
+      74             : ///     ))
+      75             : /// );
+      76             : /// ```
+      77             : #[allow(clippy::module_name_repetitions)]
+      78             : #[must_use]
+      79         227 : pub fn parse_path_filename(path: &Path) -> Option<(String, String)> {
+      80         227 :     let filename = path.file_name()?;
+      81         227 :     parse_filename(&filename.to_string_lossy())
+      82         227 : }
+      83             : 
+      84             : #[allow(clippy::module_name_repetitions)]
+      85             : #[must_use]
+      86         227 : pub fn parse_filename(filename: &str) -> Option<(String, String)> {
+      87         227 :     let file_stem = filename.strip_suffix(consts::DLL_SUFFIX)?;
+      88         121 :     let target_name = file_stem.strip_prefix(consts::DLL_PREFIX)?;
+      89         121 :     parse_target_name(target_name)
+      90         227 : }
+      91             : 
+      92         121 : fn parse_target_name(target_name: &str) -> Option<(String, String)> {
+      93         121 :     let (lib_name, toolchain) = target_name.split_once('@')?;
+      94          79 :     Some((lib_name.to_owned(), toolchain.to_owned()))
+      95         121 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/git.rs.func-sort-c.html b/coverage/internal/src/git.rs.func-sort-c.html new file mode 100644 index 000000000..be1b10496 --- /dev/null +++ b/coverage/internal/src/git.rs.func-sort-c.html @@ -0,0 +1,108 @@ + + + + + + + LCOV - unnamed - internal/src/git.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - git.rs (source / functions)HitTotalCoverage
Test:unnamedLines:324866.7 %
Date:2024-04-23 03:30:56Functions:3933.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::git::checkout::{closure#0}0
dylint_internal::git::checkout::{closure#1}0
dylint_internal::git::checkout::{closure#2}0
dylint_internal::git::checkout::{closure#3}0
dylint_internal::git::checkout::{closure#4}0
dylint_internal::git::clone_with_git20
dylint_internal::git::checkout9
dylint_internal::git::clone9
dylint_internal::git::clone_with_cli9
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/git.rs.func.html b/coverage/internal/src/git.rs.func.html new file mode 100644 index 000000000..df9eb0041 --- /dev/null +++ b/coverage/internal/src/git.rs.func.html @@ -0,0 +1,108 @@ + + + + + + + LCOV - unnamed - internal/src/git.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - git.rs (source / functions)HitTotalCoverage
Test:unnamedLines:324866.7 %
Date:2024-04-23 03:30:56Functions:3933.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::git::checkout9
dylint_internal::git::checkout::{closure#0}0
dylint_internal::git::checkout::{closure#1}0
dylint_internal::git::checkout::{closure#2}0
dylint_internal::git::checkout::{closure#3}0
dylint_internal::git::checkout::{closure#4}0
dylint_internal::git::clone9
dylint_internal::git::clone_with_cli9
dylint_internal::git::clone_with_git20
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/git.rs.gcov.html b/coverage/internal/src/git.rs.gcov.html new file mode 100644 index 000000000..5f997f59a --- /dev/null +++ b/coverage/internal/src/git.rs.gcov.html @@ -0,0 +1,160 @@ + + + + + + + LCOV - unnamed - internal/src/git.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - git.rs (source / functions)HitTotalCoverage
Test:unnamedLines:324866.7 %
Date:2024-04-23 03:30:56Functions:3933.3 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use crate::CommandExt;
+       2             : use anyhow::{Context, Result};
+       3             : use git2::Repository;
+       4             : use if_chain::if_chain;
+       5             : use std::{
+       6             :     path::Path,
+       7             :     process::{Command, Stdio},
+       8             : };
+       9             : 
+      10             : // smoelius: I think this imitates Cargo's default behavior:
+      11             : // https://doc.rust-lang.org/cargo/reference/config.html#netretry
+      12             : const N_RETRIES: usize = 2;
+      13             : 
+      14             : // smoelius: I think I may have run into https://github.com/libgit2/libgit2/issues/5294 a few times,
+      15             : // but I don't know of a good general-purpose solution. TODO: Investigate whether/how Cargo's
+      16             : // wrappers handle this.
+      17           9 : pub fn clone(url: &str, refname: &str, path: &Path, quiet: bool) -> Result<Repository> {
+      18           9 :     let repository = if Command::new("git")
+      19           9 :         .args(["--version"])
+      20           9 :         .stdout(Stdio::null())
+      21           9 :         .success()
+      22           9 :         .is_ok()
+      23             :     {
+      24           9 :         clone_with_cli(url, path, quiet)
+      25             :     } else {
+      26           0 :         clone_with_git2(url, path, quiet)
+      27           0 :     }?;
+      28             : 
+      29           9 :     checkout(&repository, refname)?;
+      30             : 
+      31           9 :     Ok(repository)
+      32           9 : }
+      33             : 
+      34           9 : fn clone_with_cli(url: &str, path: &Path, quiet: bool) -> Result<Repository> {
+      35           9 :     let mut command = Command::new("git");
+      36           9 :     command.args(["clone", url, &path.to_string_lossy()]);
+      37           9 :     if quiet {
+      38           0 :         command.args(["--quiet"]);
+      39           9 :     }
+      40           9 :     command.success()?;
+      41             : 
+      42           9 :     Repository::open(path).map_err(Into::into)
+      43           9 : }
+      44             : 
+      45           0 : fn clone_with_git2(url: &str, path: &Path, _quiet: bool) -> Result<Repository> {
+      46           0 :     let mut result = Repository::clone(url, path);
+      47             : 
+      48           0 :     for _ in 0..N_RETRIES {
+      49           0 :         if result.is_err() {
+      50           0 :             result = Repository::clone(url, path);
+      51           0 :         } else {
+      52           0 :             break;
+      53             :         }
+      54             :     }
+      55             : 
+      56           0 :     result.map_err(Into::into)
+      57           0 : }
+      58             : 
+      59             : // smoelius: `checkout` is based on: https://stackoverflow.com/a/67240436
+      60           9 : pub fn checkout(repository: &Repository, refname: &str) -> Result<()> {
+      61           9 :     let (object, reference) = repository
+      62           9 :         .revparse_ext(refname)
+      63           9 :         .with_context(|| format!("`revparse_ext` failed for `{refname}`"))?;
+      64             : 
+      65           9 :     repository
+      66           9 :         .checkout_tree(&object, None)
+      67           9 :         .with_context(|| format!("`checkout_tree` failed for `{object:?}`"))?;
+      68             : 
+      69           0 :     if_chain! {
+      70           9 :         if let Some(reference) = reference;
+      71           9 :         if let Some(refname) = reference.name();
+      72             :         then {
+      73           9 :             repository
+      74           9 :                 .set_head(refname)
+      75           9 :                 .with_context(|| format!("`set_head` failed for `{refname}`"))?;
+      76             :         } else {
+      77           0 :             repository
+      78           0 :                 .set_head_detached(object.id())
+      79           0 :                 .with_context(|| format!("`set_head_detached` failed for `{}`", object.id()))?;
+      80             :         }
+      81             :     }
+      82             : 
+      83           9 :     Ok(())
+      84           9 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/index-sort-f.html b/coverage/internal/src/index-sort-f.html new file mode 100644 index 000000000..5927d56be --- /dev/null +++ b/coverage/internal/src/index-sort-f.html @@ -0,0 +1,193 @@ + + + + + + + LCOV - unnamed - internal/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/srcHitTotalCoverage
Test:unnamedLines:49255988.0 %
Date:2024-04-23 03:30:56Functions:7412459.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
sed.rs +
100.0%
+
100.0 %10 / 1033.3 %2 / 6
git.rs +
66.7%66.7%
+
66.7 %32 / 4833.3 %3 / 9
env.rs +
50.0%50.0%
+
50.0 %3 / 650.0 %2 / 4
packaging.rs +
99.1%99.1%
+
99.1 %110 / 11153.6 %15 / 28
clippy_utils.rs +
74.7%74.7%
+
74.7 %68 / 9156.5 %13 / 23
examples.rs +
90.7%90.7%
+
90.7 %49 / 5457.1 %4 / 7
command.rs +
91.5%91.5%
+
91.5 %43 / 4760.0 %3 / 5
rustup.rs +
100.0%
+
100.0 %38 / 3870.0 %7 / 10
cargo.rs +
87.8%87.8%
+
87.8 %108 / 12372.0 %18 / 25
testing.rs +
100.0%
+
100.0 %9 / 9100.0 %3 / 3
filename.rs +
100.0%
+
100.0 %22 / 22100.0 %4 / 4
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/index-sort-l.html b/coverage/internal/src/index-sort-l.html new file mode 100644 index 000000000..9c2634af9 --- /dev/null +++ b/coverage/internal/src/index-sort-l.html @@ -0,0 +1,193 @@ + + + + + + + LCOV - unnamed - internal/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/srcHitTotalCoverage
Test:unnamedLines:49255988.0 %
Date:2024-04-23 03:30:56Functions:7412459.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
env.rs +
50.0%50.0%
+
50.0 %3 / 650.0 %2 / 4
git.rs +
66.7%66.7%
+
66.7 %32 / 4833.3 %3 / 9
clippy_utils.rs +
74.7%74.7%
+
74.7 %68 / 9156.5 %13 / 23
cargo.rs +
87.8%87.8%
+
87.8 %108 / 12372.0 %18 / 25
examples.rs +
90.7%90.7%
+
90.7 %49 / 5457.1 %4 / 7
command.rs +
91.5%91.5%
+
91.5 %43 / 4760.0 %3 / 5
packaging.rs +
99.1%99.1%
+
99.1 %110 / 11153.6 %15 / 28
testing.rs +
100.0%
+
100.0 %9 / 9100.0 %3 / 3
sed.rs +
100.0%
+
100.0 %10 / 1033.3 %2 / 6
filename.rs +
100.0%
+
100.0 %22 / 22100.0 %4 / 4
rustup.rs +
100.0%
+
100.0 %38 / 3870.0 %7 / 10
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/index.html b/coverage/internal/src/index.html new file mode 100644 index 000000000..4c6080d74 --- /dev/null +++ b/coverage/internal/src/index.html @@ -0,0 +1,193 @@ + + + + + + + LCOV - unnamed - internal/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/srcHitTotalCoverage
Test:unnamedLines:49255988.0 %
Date:2024-04-23 03:30:56Functions:7412459.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
cargo.rs +
87.8%87.8%
+
87.8 %108 / 12372.0 %18 / 25
clippy_utils.rs +
74.7%74.7%
+
74.7 %68 / 9156.5 %13 / 23
command.rs +
91.5%91.5%
+
91.5 %43 / 4760.0 %3 / 5
env.rs +
50.0%50.0%
+
50.0 %3 / 650.0 %2 / 4
examples.rs +
90.7%90.7%
+
90.7 %49 / 5457.1 %4 / 7
filename.rs +
100.0%
+
100.0 %22 / 22100.0 %4 / 4
git.rs +
66.7%66.7%
+
66.7 %32 / 4833.3 %3 / 9
packaging.rs +
99.1%99.1%
+
99.1 %110 / 11153.6 %15 / 28
rustup.rs +
100.0%
+
100.0 %38 / 3870.0 %7 / 10
sed.rs +
100.0%
+
100.0 %10 / 1033.3 %2 / 6
testing.rs +
100.0%
+
100.0 %9 / 9100.0 %3 / 3
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/packaging.rs.func-sort-c.html b/coverage/internal/src/packaging.rs.func-sort-c.html new file mode 100644 index 000000000..7d4ef020f --- /dev/null +++ b/coverage/internal/src/packaging.rs.func-sort-c.html @@ -0,0 +1,184 @@ + + + + + + + LCOV - unnamed - internal/src/packaging.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - packaging.rs (source / functions)HitTotalCoverage
Test:unnamedLines:11011199.1 %
Date:2024-04-23 03:30:56Functions:152853.6 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint_internal::packaging::Template as rust_embed::RustEmbed>::get0
<dylint_internal::packaging::Template as rust_embed::RustEmbed>::iter0
dylint_internal::packaging::isolate::{closure#0}0
dylint_internal::packaging::isolate::{closure#2}0
dylint_internal::packaging::new_template::{closure#0}0
dylint_internal::packaging::new_template::{closure#1}0
dylint_internal::packaging::new_template::{closure#2}0
dylint_internal::packaging::new_template::{closure#3}0
dylint_internal::packaging::new_template::{closure#4}0
dylint_internal::packaging::use_local_packages::{closure#0}0
dylint_internal::packaging::use_local_packages::{closure#3}0
dylint_internal::packaging::use_local_packages::{closure#5}0
dylint_internal::packaging::use_local_packages::{closure#6}0
dylint_internal::packaging::test::template_has_initial_version1
dylint_internal::packaging::test::template_has_initial_version::{closure#0}1
dylint_internal::packaging::test::template_includes_only_whitelisted_paths1
dylint_internal::packaging::test::template_includes_only_whitelisted_paths::{closure#0}8
dylint_internal::packaging::new_template10
dylint_internal::packaging::use_local_packages10
dylint_internal::packaging::use_local_packages::{closure#1}10
dylint_internal::packaging::use_local_packages::{closure#2}10
<dylint_internal::packaging::Template>::iter11
dylint_internal::packaging::isolate13
dylint_internal::packaging::isolate::{closure#1}13
<dylint_internal::packaging::Template>::get80
<dylint_internal::packaging::Template>::iter::{closure#0}88
dylint_internal::packaging::use_local_packages::{closure#4}180
dylint_internal::packaging::use_local_packages::{closure#4}::{closure#0}180
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/packaging.rs.func.html b/coverage/internal/src/packaging.rs.func.html new file mode 100644 index 000000000..64178011a --- /dev/null +++ b/coverage/internal/src/packaging.rs.func.html @@ -0,0 +1,184 @@ + + + + + + + LCOV - unnamed - internal/src/packaging.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - packaging.rs (source / functions)HitTotalCoverage
Test:unnamedLines:11011199.1 %
Date:2024-04-23 03:30:56Functions:152853.6 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint_internal::packaging::Template as rust_embed::RustEmbed>::get0
<dylint_internal::packaging::Template as rust_embed::RustEmbed>::iter0
<dylint_internal::packaging::Template>::get80
<dylint_internal::packaging::Template>::iter11
<dylint_internal::packaging::Template>::iter::{closure#0}88
dylint_internal::packaging::isolate13
dylint_internal::packaging::isolate::{closure#0}0
dylint_internal::packaging::isolate::{closure#1}13
dylint_internal::packaging::isolate::{closure#2}0
dylint_internal::packaging::new_template10
dylint_internal::packaging::new_template::{closure#0}0
dylint_internal::packaging::new_template::{closure#1}0
dylint_internal::packaging::new_template::{closure#2}0
dylint_internal::packaging::new_template::{closure#3}0
dylint_internal::packaging::new_template::{closure#4}0
dylint_internal::packaging::test::template_has_initial_version1
dylint_internal::packaging::test::template_has_initial_version::{closure#0}1
dylint_internal::packaging::test::template_includes_only_whitelisted_paths1
dylint_internal::packaging::test::template_includes_only_whitelisted_paths::{closure#0}8
dylint_internal::packaging::use_local_packages10
dylint_internal::packaging::use_local_packages::{closure#0}0
dylint_internal::packaging::use_local_packages::{closure#1}10
dylint_internal::packaging::use_local_packages::{closure#2}10
dylint_internal::packaging::use_local_packages::{closure#3}0
dylint_internal::packaging::use_local_packages::{closure#4}180
dylint_internal::packaging::use_local_packages::{closure#4}::{closure#0}180
dylint_internal::packaging::use_local_packages::{closure#5}0
dylint_internal::packaging::use_local_packages::{closure#6}0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/packaging.rs.gcov.html b/coverage/internal/src/packaging.rs.gcov.html new file mode 100644 index 000000000..e383ba4b0 --- /dev/null +++ b/coverage/internal/src/packaging.rs.gcov.html @@ -0,0 +1,246 @@ + + + + + + + LCOV - unnamed - internal/src/packaging.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - packaging.rs (source / functions)HitTotalCoverage
Test:unnamedLines:11011199.1 %
Date:2024-04-23 03:30:56Functions:152853.6 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : // smoelius: Since the update to `rust_embed` 8.3.0, `unnecessary_conversion_for_trait` started
+       2             : // firing on `struct Template`. Requiring `!expr.span.from_expansion()` in
+       3             : // `unnecessary_conversion_for_trait` causes one of its tests to fail. So allow the lint for now.
+       4             : // smoelius: `abs_home_path` now fires as well.
+       5             : #![cfg_attr(dylint_lib = "general", allow(abs_home_path))]
+       6             : #![cfg_attr(dylint_lib = "overscoped_allow", allow(overscoped_allow))]
+       7             : #![cfg_attr(dylint_lib = "supplementary", allow(unnecessary_conversion_for_trait))]
+       8             : 
+       9             : use crate::cargo::{current_metadata, package};
+      10             : use anyhow::{anyhow, Context, Result};
+      11             : use rust_embed::RustEmbed;
+      12             : use std::{
+      13             :     fs::{create_dir_all, OpenOptions},
+      14             :     io::Write,
+      15             :     path::Path,
+      16             : };
+      17             : 
+      18         171 : #[derive(RustEmbed)]
+      19             : #[folder = "template"]
+      20             : #[exclude = "Cargo.lock"]
+      21             : #[exclude = "target/*"]
+      22             : struct Template;
+      23             : 
+      24          10 : pub fn new_template(to: &Path) -> Result<()> {
+      25          90 :     for path in Template::iter() {
+      26          80 :         let embedded_file = Template::get(&path)
+      27          80 :             .ok_or_else(|| anyhow!("Could not get embedded file `{}`", path))?;
+      28          80 :         let to_path = to.join(path.trim_end_matches('~'));
+      29          80 :         let parent = to_path
+      30          80 :             .parent()
+      31          80 :             .ok_or_else(|| anyhow!("Could not get parent directory"))?;
+      32          80 :         create_dir_all(parent).with_context(|| {
+      33           0 :             format!("`create_dir_all` failed for `{}`", parent.to_string_lossy())
+      34          80 :         })?;
+      35          80 :         let mut file = OpenOptions::new()
+      36          80 :             .create(true)
+      37          80 :             .truncate(true)
+      38          80 :             .write(true)
+      39          80 :             .open(&to_path)
+      40          80 :             .with_context(|| format!("Could not open `{}`", to_path.to_string_lossy()))?;
+      41          80 :         file.write_all(&embedded_file.data)
+      42          80 :             .with_context(|| format!("Could not write to {to_path:?}"))?;
+      43             :     }
+      44             : 
+      45          10 :     Ok(())
+      46          10 : }
+      47             : 
+      48             : // smoelius: If a package is checked out in the current directory, this must be dealt with:
+      49             : // error: current package believes it's in a workspace when it's not
+      50          13 : pub fn isolate(path: &Path) -> Result<()> {
+      51          13 :     let manifest = path.join("Cargo.toml");
+      52          13 :     let mut file = OpenOptions::new()
+      53          13 :         .append(true)
+      54          13 :         .open(&manifest)
+      55          13 :         .with_context(|| format!("Could not open `{}`", manifest.to_string_lossy()))?;
+      56             : 
+      57          13 :     writeln!(file)
+      58          13 :         .and_then(|()| writeln!(file, "[workspace]"))
+      59          13 :         .with_context(|| format!("Could not write to `{}`", manifest.to_string_lossy()))?;
+      60             : 
+      61          13 :     Ok(())
+      62          13 : }
+      63             : 
+      64             : // smoelius: If you clone, say, `dylint-template` and run `cargo test` on it, it will obtain Dylint
+      65             : // packages from `crates.io`. But for the tests in this repository, you often want it to use the
+      66             : // packages in this repository. The function `use_local_packages` patches a workspace's `Cargo.toml`
+      67             : // file to do so.
+      68          10 : pub fn use_local_packages(path: &Path) -> Result<()> {
+      69          10 :     let metadata = current_metadata()?;
+      70             : 
+      71          10 :     let manifest = path.join("Cargo.toml");
+      72             : 
+      73          10 :     let mut file = OpenOptions::new()
+      74          10 :         .append(true)
+      75          10 :         .open(&manifest)
+      76          10 :         .with_context(|| format!("Could not open `{}`", manifest.to_string_lossy()))?;
+      77             : 
+      78             :     // smoelius: `use_local_packages` broke when `dylint_linting` was removed from the workspace.
+      79             :     // For now, add `dylint_linting` manually.
+      80          10 :     writeln!(file)
+      81          10 :         .and_then(|()| writeln!(file, "[patch.crates-io]"))
+      82          10 :         .and_then(|()| {
+      83          10 :             writeln!(
+      84          10 :                 file,
+      85          10 :                 r#"dylint_linting = {{ path = "{}" }}"#,
+      86          10 :                 metadata
+      87          10 :                     .workspace_root
+      88          10 :                     .join("utils/linting")
+      89          10 :                     .to_string()
+      90          10 :                     .replace('\\', "\\\\")
+      91          10 :             )
+      92          10 :         })
+      93          10 :         .with_context(|| format!("Could not write to `{}`", manifest.to_string_lossy()))?;
+      94             : 
+      95          70 :     for package_id in &metadata.workspace_members {
+      96          60 :         let package = package(&metadata, package_id)?;
+      97          60 :         if package.publish == Some(vec![])
+      98          50 :             || package
+      99          50 :                 .targets
+     100          50 :                 .iter()
+     101         180 :                 .all(|target| target.kind.iter().all(|kind| kind != "lib"))
+     102             :         {
+     103          30 :             continue;
+     104          30 :         }
+     105          30 :         let path = package
+     106          30 :             .manifest_path
+     107          30 :             .parent()
+     108          30 :             .ok_or_else(|| anyhow!("Could not get parent directory"))?;
+     109          30 :         writeln!(
+     110          30 :             file,
+     111          30 :             r#"{} = {{ path = "{}" }}"#,
+     112          30 :             package.name,
+     113          30 :             path.to_string().replace('\\', "\\\\")
+     114          30 :         )
+     115          30 :         .with_context(|| format!("Could not write to `{}`", manifest.to_string_lossy()))?;
+     116             :     }
+     117             : 
+     118          10 :     Ok(())
+     119          10 : }
+     120             : 
+     121             : #[cfg(test)]
+     122             : mod test {
+     123             :     use super::*;
+     124             :     use std::fs::read_to_string;
+     125             :     use toml_edit::{DocumentMut, Item};
+     126             : 
+     127             :     #[cfg_attr(
+     128             :         dylint_lib = "assert_eq_arg_misordering",
+     129             :         allow(assert_eq_arg_misordering)
+     130             :     )]
+     131             :     #[test]
+     132           1 :     fn template_includes_only_whitelisted_paths() {
+     133           1 :         const PATHS: [&str; 8] = [
+     134           1 :             ".cargo/config.toml",
+     135           1 :             ".gitignore",
+     136           1 :             "Cargo.toml~",
+     137           1 :             "README.md",
+     138           1 :             "rust-toolchain",
+     139           1 :             "src/lib.rs",
+     140           1 :             "ui/main.rs",
+     141           1 :             "ui/main.stderr",
+     142           1 :         ];
+     143           1 : 
+     144           1 :         let mut paths_sorted = PATHS.to_vec();
+     145           1 :         paths_sorted.sort_unstable();
+     146           1 :         assert_eq!(paths_sorted, PATHS);
+     147             : 
+     148           1 :         let paths = Template::iter()
+     149           8 :             .filter(|path| PATHS.binary_search(&&**path).is_err())
+     150           1 :             .collect::<Vec<_>>();
+     151           1 : 
+     152           1 :         assert!(paths.is_empty(), "found {paths:#?}");
+     153           1 :     }
+     154             : 
+     155             :     #[test]
+     156           1 :     fn template_has_initial_version() {
+     157           1 :         let contents =
+     158           1 :             read_to_string(Path::new(env!("CARGO_MANIFEST_DIR")).join("template/Cargo.toml~"))
+     159           1 :                 .unwrap();
+     160           1 :         let document = contents.parse::<DocumentMut>().unwrap();
+     161           1 :         let version = document
+     162           1 :             .as_table()
+     163           1 :             .get("package")
+     164           1 :             .and_then(Item::as_table)
+     165           1 :             .and_then(|table| table.get("version"))
+     166           1 :             .and_then(Item::as_str)
+     167           1 :             .unwrap();
+     168           1 :         assert_eq!("0.1.0", version);
+     169           1 :     }
+     170             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/rustup.rs.func-sort-c.html b/coverage/internal/src/rustup.rs.func-sort-c.html new file mode 100644 index 000000000..d3d75639d --- /dev/null +++ b/coverage/internal/src/rustup.rs.func-sort-c.html @@ -0,0 +1,112 @@ + + + + + + + LCOV - unnamed - internal/src/rustup.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - rustup.rs (source / functions)HitTotalCoverage
Test:unnamedLines:3838100.0 %
Date:2024-04-23 03:30:56Functions:71070.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::rustup::active_toolchain::{closure#1}0
dylint_internal::rustup::is_rustc::<_>0
dylint_internal::rustup::toolchain_path::{closure#0}0
dylint_internal::rustup::is_rustc::<str>1
dylint_internal::rustup::rustc_is_rustc1
dylint_internal::rustup::is_rustc::<&&str>6
dylint_internal::rustup::toolchain_path7
dylint_internal::rustup::active_toolchain27
dylint_internal::rustup::active_toolchain::{closure#0}27
<std::process::Command as dylint_internal::rustup::SanitizeEnvironment>::sanitize_environment111
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/rustup.rs.func.html b/coverage/internal/src/rustup.rs.func.html new file mode 100644 index 000000000..77a4074d4 --- /dev/null +++ b/coverage/internal/src/rustup.rs.func.html @@ -0,0 +1,112 @@ + + + + + + + LCOV - unnamed - internal/src/rustup.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - rustup.rs (source / functions)HitTotalCoverage
Test:unnamedLines:3838100.0 %
Date:2024-04-23 03:30:56Functions:71070.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<std::process::Command as dylint_internal::rustup::SanitizeEnvironment>::sanitize_environment111
dylint_internal::rustup::active_toolchain27
dylint_internal::rustup::active_toolchain::{closure#0}27
dylint_internal::rustup::active_toolchain::{closure#1}0
dylint_internal::rustup::is_rustc::<&&str>6
dylint_internal::rustup::is_rustc::<_>0
dylint_internal::rustup::is_rustc::<str>1
dylint_internal::rustup::rustc_is_rustc1
dylint_internal::rustup::toolchain_path7
dylint_internal::rustup::toolchain_path::{closure#0}0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/rustup.rs.gcov.html b/coverage/internal/src/rustup.rs.gcov.html new file mode 100644 index 000000000..d430ea7f6 --- /dev/null +++ b/coverage/internal/src/rustup.rs.gcov.html @@ -0,0 +1,136 @@ + + + + + + + LCOV - unnamed - internal/src/rustup.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - rustup.rs (source / functions)HitTotalCoverage
Test:unnamedLines:3838100.0 %
Date:2024-04-23 03:30:56Functions:71070.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use crate::{env, CommandExt};
+       2             : use anyhow::{anyhow, Result};
+       3             : use std::{
+       4             :     ffi::OsStr,
+       5             :     path::{Path, PathBuf},
+       6             :     process::Command,
+       7             : };
+       8             : 
+       9             : // smoelius: Should this be merged into `CommandExt`?
+      10             : pub trait SanitizeEnvironment {
+      11             :     fn sanitize_environment(&mut self) -> &mut Self;
+      12             : }
+      13             : 
+      14             : impl SanitizeEnvironment for Command {
+      15         111 :     fn sanitize_environment(&mut self) -> &mut Self {
+      16         111 :         self.env_remove(env::CARGO);
+      17         111 :         self.env_remove(env::RUSTC);
+      18         111 :         self.env_remove(env::RUSTUP_TOOLCHAIN);
+      19         111 :         self
+      20         111 :     }
+      21             : }
+      22             : 
+      23             : // smoelius: Consider carefully whether you need to call this function! In most cases, the toolchain
+      24             : // you want is not the one returned by rustup.
+      25          27 : pub fn active_toolchain(path: &Path) -> Result<String> {
+      26          27 :     let output = Command::new("rustup")
+      27          27 :         .sanitize_environment()
+      28          27 :         .current_dir(path)
+      29          27 :         .args(["show", "active-toolchain"])
+      30          27 :         .logged_output(true)?;
+      31          27 :     let stdout = std::str::from_utf8(&output.stdout)?;
+      32          27 :     stdout
+      33          27 :         .split_once(' ')
+      34          27 :         .map(|(s, _)| s.to_owned())
+      35          27 :         .ok_or_else(|| anyhow!("Could not determine active toolchain"))
+      36          27 : }
+      37             : 
+      38           7 : pub fn toolchain_path(path: &Path) -> Result<PathBuf> {
+      39           7 :     let output = Command::new("rustup")
+      40           7 :         .sanitize_environment()
+      41           7 :         .current_dir(path)
+      42           7 :         .args(["which", "rustc"])
+      43           7 :         .logged_output(true)?;
+      44           7 :     let stdout = std::str::from_utf8(&output.stdout)?;
+      45           7 :     let path = PathBuf::from(stdout);
+      46           7 :     // smoelius: `path` should end with `/bin/rustc`.
+      47           7 :     path.ancestors()
+      48           7 :         .nth(2)
+      49           7 :         .map(Into::into)
+      50           7 :         .ok_or_else(|| anyhow!("Could not get ancestor"))
+      51           7 : }
+      52             : 
+      53           7 : pub fn is_rustc<T: AsRef<OsStr> + ?Sized>(arg: &T) -> bool {
+      54           7 :     Path::new(arg).file_stem() == Some(OsStr::new("rustc"))
+      55           7 : }
+      56             : 
+      57             : #[test]
+      58           1 : fn rustc_is_rustc() {
+      59           1 :     assert!(is_rustc("rustc"));
+      60           1 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/sed.rs.func-sort-c.html b/coverage/internal/src/sed.rs.func-sort-c.html new file mode 100644 index 000000000..8dc161dd7 --- /dev/null +++ b/coverage/internal/src/sed.rs.func-sort-c.html @@ -0,0 +1,96 @@ + + + + + + + LCOV - unnamed - internal/src/sed.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - sed.rs (source / functions)HitTotalCoverage
Test:unnamedLines:1010100.0 %
Date:2024-04-23 03:30:56Functions:2633.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::sed::find_and_replace::<&alloc::string::String>::{closure#0}0
dylint_internal::sed::find_and_replace::<&str>::{closure#0}0
dylint_internal::sed::find_and_replace::<_>0
dylint_internal::sed::find_and_replace::<_>::{closure#0}0
dylint_internal::sed::find_and_replace::<&str>1
dylint_internal::sed::find_and_replace::<&alloc::string::String>32
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/sed.rs.func.html b/coverage/internal/src/sed.rs.func.html new file mode 100644 index 000000000..007b38c7b --- /dev/null +++ b/coverage/internal/src/sed.rs.func.html @@ -0,0 +1,96 @@ + + + + + + + LCOV - unnamed - internal/src/sed.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - sed.rs (source / functions)HitTotalCoverage
Test:unnamedLines:1010100.0 %
Date:2024-04-23 03:30:56Functions:2633.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::sed::find_and_replace::<&alloc::string::String>32
dylint_internal::sed::find_and_replace::<&alloc::string::String>::{closure#0}0
dylint_internal::sed::find_and_replace::<&str>1
dylint_internal::sed::find_and_replace::<&str>::{closure#0}0
dylint_internal::sed::find_and_replace::<_>0
dylint_internal::sed::find_and_replace::<_>::{closure#0}0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/sed.rs.gcov.html b/coverage/internal/src/sed.rs.gcov.html new file mode 100644 index 000000000..80e1396cf --- /dev/null +++ b/coverage/internal/src/sed.rs.gcov.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - internal/src/sed.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - sed.rs (source / functions)HitTotalCoverage
Test:unnamedLines:1010100.0 %
Date:2024-04-23 03:30:56Functions:2633.3 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use anyhow::{Context, Result};
+       2             : use regex::Regex;
+       3             : use std::{
+       4             :     fs::{read_to_string, write},
+       5             :     path::Path,
+       6             : };
+       7             : 
+       8          33 : pub fn find_and_replace<R>(path: &Path, re: &str, replacement: R) -> Result<()>
+       9          33 : where
+      10          33 :     R: AsRef<str>,
+      11          33 : {
+      12          33 :     let before = read_to_string(path)
+      13          33 :         .with_context(|| format!("`read_to_string` failed for `{}`", path.to_string_lossy()))?;
+      14          33 :     let re = Regex::new(re)?;
+      15          33 :     let after = re.replace_all(&before, replacement.as_ref());
+      16          33 :     write(path, after.as_bytes()).map_err(Into::into)
+      17          33 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/testing.rs.func-sort-c.html b/coverage/internal/src/testing.rs.func-sort-c.html new file mode 100644 index 000000000..34dfa2ebc --- /dev/null +++ b/coverage/internal/src/testing.rs.func-sort-c.html @@ -0,0 +1,84 @@ + + + + + + + LCOV - unnamed - internal/src/testing.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - testing.rs (source / functions)HitTotalCoverage
Test:unnamedLines:99100.0 %
Date:2024-04-23 03:30:56Functions:33100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::testing::new_template9
dylint_internal::testing::init54
dylint_internal::testing::init___rust_ctor___ctor::init___rust_ctor___ctor54
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/testing.rs.func.html b/coverage/internal/src/testing.rs.func.html new file mode 100644 index 000000000..d9f9e2366 --- /dev/null +++ b/coverage/internal/src/testing.rs.func.html @@ -0,0 +1,84 @@ + + + + + + + LCOV - unnamed - internal/src/testing.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - testing.rs (source / functions)HitTotalCoverage
Test:unnamedLines:99100.0 %
Date:2024-04-23 03:30:56Functions:33100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
dylint_internal::testing::init54
dylint_internal::testing::init___rust_ctor___ctor::init___rust_ctor___ctor54
dylint_internal::testing::new_template9
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/internal/src/testing.rs.gcov.html b/coverage/internal/src/testing.rs.gcov.html new file mode 100644 index 000000000..47b9560a3 --- /dev/null +++ b/coverage/internal/src/testing.rs.gcov.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - unnamed - internal/src/testing.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - internal/src - testing.rs (source / functions)HitTotalCoverage
Test:unnamedLines:99100.0 %
Date:2024-04-23 03:30:56Functions:33100.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use anyhow::Result;
+       2             : use std::path::Path;
+       3             : 
+       4          54 : #[ctor::ctor]
+       5          54 : fn init() {
+       6          54 :     env_logger::init();
+       7          54 : }
+       8             : 
+       9           9 : pub fn new_template(path: &Path) -> Result<()> {
+      10           9 :     crate::packaging::new_template(path)?;
+      11           9 :     crate::packaging::use_local_packages(path)?;
+      12           9 :     Ok(())
+      13           9 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/ruby.png b/coverage/ruby.png new file mode 100644 index 000000000..991b6d4ec Binary files /dev/null and b/coverage/ruby.png differ diff --git a/coverage/snow.png b/coverage/snow.png new file mode 100644 index 000000000..2cdae107f Binary files /dev/null and b/coverage/snow.png differ diff --git a/coverage/updown.png b/coverage/updown.png new file mode 100644 index 000000000..aa56a238b Binary files /dev/null and b/coverage/updown.png differ diff --git a/coverage/utils/linting/src/index-sort-f.html b/coverage/utils/linting/src/index-sort-f.html new file mode 100644 index 000000000..527061597 --- /dev/null +++ b/coverage/utils/linting/src/index-sort-f.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - utils/linting/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/linting/srcHitTotalCoverage
Test:unnamedLines:01180.0 %
Date:2024-04-23 03:30:56Functions:0220.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
lib.rs +
0.0%
+
0.0 %0 / 1180.0 %0 / 22
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/utils/linting/src/index-sort-l.html b/coverage/utils/linting/src/index-sort-l.html new file mode 100644 index 000000000..5f9ccb6c8 --- /dev/null +++ b/coverage/utils/linting/src/index-sort-l.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - utils/linting/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/linting/srcHitTotalCoverage
Test:unnamedLines:01180.0 %
Date:2024-04-23 03:30:56Functions:0220.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
lib.rs +
0.0%
+
0.0 %0 / 1180.0 %0 / 22
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/utils/linting/src/index.html b/coverage/utils/linting/src/index.html new file mode 100644 index 000000000..cc51ad35f --- /dev/null +++ b/coverage/utils/linting/src/index.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - unnamed - utils/linting/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/linting/srcHitTotalCoverage
Test:unnamedLines:01180.0 %
Date:2024-04-23 03:30:56Functions:0220.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
lib.rs +
0.0%
+
0.0 %0 / 1180.0 %0 / 22
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/utils/linting/src/lib.rs.func-sort-c.html b/coverage/utils/linting/src/lib.rs.func-sort-c.html new file mode 100644 index 000000000..f4eb167a5 --- /dev/null +++ b/coverage/utils/linting/src/lib.rs.func-sort-c.html @@ -0,0 +1,160 @@ + + + + + + + LCOV - unnamed - utils/linting/src/lib.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/linting/src - lib.rs (source / functions)HitTotalCoverage
Test:unnamedLines:01180.0 %
Date:2024-04-23 03:30:56Functions:0220.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint_linting::ConfigError as core::convert::From<_>>::from0
<dylint_linting::ConfigError as core::fmt::Display>::fmt0
<dylint_linting::ConfigErrorInner as core::convert::From<cargo_metadata::errors::Error>>::from0
<dylint_linting::ConfigErrorInner as core::convert::From<toml::de::Error>>::from0
<dylint_linting::ConfigErrorInner as core::error::Error>::source0
<dylint_linting::ConfigErrorInner as core::fmt::Display>::fmt0
<rustc_session::session::Session as dylint_linting::ParseSess>::parse_sess0
dylint_linting::config::<_>0
dylint_linting::config_or_default::<_>0
dylint_linting::config_or_default::<_>::{closure#0}0
dylint_linting::config_toml0
dylint_linting::early_error::<_>0
dylint_linting::init_config0
dylint_linting::init_config::{closure#0}0
dylint_linting::local_crate_source_file0
dylint_linting::try_init_config0
dylint_linting::try_init_config::{closure#0}0
dylint_linting::try_init_config::{closure#1}0
dylint_linting::try_init_config::{closure#2}0
dylint_linting::try_init_config::{closure#3}0
dylint_linting::try_init_config::{closure#3}::{closure#0}0
dylint_linting::try_init_config::{closure#4}0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/utils/linting/src/lib.rs.func.html b/coverage/utils/linting/src/lib.rs.func.html new file mode 100644 index 000000000..29a1b0c3c --- /dev/null +++ b/coverage/utils/linting/src/lib.rs.func.html @@ -0,0 +1,160 @@ + + + + + + + LCOV - unnamed - utils/linting/src/lib.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/linting/src - lib.rs (source / functions)HitTotalCoverage
Test:unnamedLines:01180.0 %
Date:2024-04-23 03:30:56Functions:0220.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint_linting::ConfigError as core::convert::From<_>>::from0
<dylint_linting::ConfigError as core::fmt::Display>::fmt0
<dylint_linting::ConfigErrorInner as core::convert::From<cargo_metadata::errors::Error>>::from0
<dylint_linting::ConfigErrorInner as core::convert::From<toml::de::Error>>::from0
<dylint_linting::ConfigErrorInner as core::error::Error>::source0
<dylint_linting::ConfigErrorInner as core::fmt::Display>::fmt0
<rustc_session::session::Session as dylint_linting::ParseSess>::parse_sess0
dylint_linting::config::<_>0
dylint_linting::config_or_default::<_>0
dylint_linting::config_or_default::<_>::{closure#0}0
dylint_linting::config_toml0
dylint_linting::early_error::<_>0
dylint_linting::init_config0
dylint_linting::init_config::{closure#0}0
dylint_linting::local_crate_source_file0
dylint_linting::try_init_config0
dylint_linting::try_init_config::{closure#0}0
dylint_linting::try_init_config::{closure#1}0
dylint_linting::try_init_config::{closure#2}0
dylint_linting::try_init_config::{closure#3}0
dylint_linting::try_init_config::{closure#3}::{closure#0}0
dylint_linting::try_init_config::{closure#4}0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/utils/linting/src/lib.rs.gcov.html b/coverage/utils/linting/src/lib.rs.gcov.html new file mode 100644 index 000000000..8d7c26002 --- /dev/null +++ b/coverage/utils/linting/src/lib.rs.gcov.html @@ -0,0 +1,800 @@ + + + + + + + LCOV - unnamed - utils/linting/src/lib.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/linting/src - lib.rs (source / functions)HitTotalCoverage
Test:unnamedLines:01180.0 %
Date:2024-04-23 03:30:56Functions:0220.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : //! This crate provides macros for creating [Dylint] libraries, and utilities for creating
+       2             : //! configurable libraries.
+       3             : //!
+       4             : //! **Contents**
+       5             : //!
+       6             : //! - [`dylint_library!`]
+       7             : //! - [`declare_late_lint!`, `declare_early_lint!`, `declare_pre_expansion_lint!`]
+       8             : //! - [`impl_late_lint!`, `impl_early_lint!`, `impl_pre_expansion_lint!`]
+       9             : //! - [`constituent` feature]
+      10             : //! - [Configurable libraries]
+      11             : //!
+      12             : //! # `dylint_library!`
+      13             : //!
+      14             : //! The `dylint_library!` macro expands to the following:
+      15             : //!
+      16             : //! ```rust,ignore
+      17             : //! #[allow(unused_extern_crates)]
+      18             : //! extern crate rustc_driver;
+      19             : //!
+      20             : //! #[no_mangle]
+      21             : //! pub extern "C" fn dylint_version() -> *mut std::os::raw::c_char {
+      22             : //!     std::ffi::CString::new($crate::DYLINT_VERSION)
+      23             : //!         .unwrap()
+      24             : //!         .into_raw()
+      25             : //! }
+      26             : //! ```
+      27             : //!
+      28             : //! If your library uses the `dylint_library!` macro and the [`dylint-link`] tool, then all you
+      29             : //! should have to do is implement the [`register_lints`] function. See the [examples] in this
+      30             : //! repository.
+      31             : //!
+      32             : //! # `declare_late_lint!`, etc.
+      33             : //!
+      34             : //! If your library contains just one lint, using `declare_late_lint!`, etc. can make your code more
+      35             : //! concise. Each of these macros requires the same arguments as [`declare_lint!`], and wraps the
+      36             : //! following:
+      37             : //!
+      38             : //! - a call to `dylint_library!`
+      39             : //! - an implementation of the `register_lints` function
+      40             : //! - a call to `declare_lint!`
+      41             : //! - a call to [`declare_lint_pass!`]
+      42             : //!
+      43             : //! For example, `declare_late_lint!(vis NAME, Level, "description")` expands to the following:
+      44             : //!
+      45             : //! ```rust,ignore
+      46             : //! dylint_linting::dylint_library!();
+      47             : //!
+      48             : //! extern crate rustc_lint;
+      49             : //! extern crate rustc_session;
+      50             : //!
+      51             : //! #[no_mangle]
+      52             : //! pub fn register_lints(sess: &rustc_session::Session, lint_store: &mut rustc_lint::LintStore) {
+      53             : //!     dylint_linting::init_config(sess);
+      54             : //!     lint_store.register_lints(&[NAME]);
+      55             : //!     lint_store.register_late_pass(|_| Box::new(Name));
+      56             : //! }
+      57             : //!
+      58             : //! rustc_session::declare_lint!(vis NAME, Level, "description");
+      59             : //!
+      60             : //! rustc_session::declare_lint_pass!(Name => [NAME]);
+      61             : //! ```
+      62             : //!
+      63             : //! `declare_early_lint!` and `declare_pre_expansion_lint!` are defined similarly.
+      64             : //!
+      65             : //! # `impl_late_lint!`, etc.
+      66             : //!
+      67             : //! `impl_late_lint!`, etc. are like `declare_late_lint!`, etc. except:
+      68             : //!
+      69             : //! - each calls [`impl_lint_pass!`] instead of `declare_lint_pass!`;
+      70             : //! - each requires an additional argument to specify the value of the lint's [`LintPass`]
+      71             : //!   structure.
+      72             : //!
+      73             : //! That is, `impl_late_lint!`'s additional argument is what goes here:
+      74             : //!
+      75             : //! ```rust,ignore
+      76             : //!     lint_store.register_late_pass(|_| Box::new(...));
+      77             : //!                                                ^^^
+      78             : //! ```
+      79             : //!
+      80             : //! # `constituent` feature
+      81             : //!
+      82             : //! Enabling the package-level `constituent` feature changes the way the above macros work.
+      83             : //! Specifically, it causes them to _exclude_:
+      84             : //!
+      85             : //! - the call to `dylint_library!`
+      86             : //! - the use of `#[no_mangle]` just prior to the declaration of `register_lints`
+      87             : //!
+      88             : //! Such changes facilitate inclusion of a lint declared with one of the above macros into a larger
+      89             : //! library. That is:
+      90             : //!
+      91             : //! - With the feature turned off, the lint can be built as a library by itself.
+      92             : //! - With the feature turned on, the lint can be built as part of a larger library, alongside other
+      93             : //!   lints.
+      94             : //!
+      95             : //! The [general-purpose] and [supplementary] lints in this repository employ this technique.
+      96             : //! That is, each general-purpose lint can be built as a library by itself, or as part of the
+      97             : //! [`general` library]. An analogous statement applies to the supplementary lints and the
+      98             : //! [`supplementary` library]. The `constituent` feature is the underlying mechanism that makes this
+      99             : //! work.
+     100             : //!
+     101             : //! # Configurable libraries
+     102             : //!
+     103             : //! Libraries can be configured by including a `dylint.toml` file in the target workspace's root
+     104             : //! directory. This crate provides the following functions for reading and parsing `dylint.toml`
+     105             : //! files:
+     106             : //!
+     107             : //! - [`config_or_default`]
+     108             : //! - [`config`]
+     109             : //! - [`config_toml`]
+     110             : //! - [`init_config`]
+     111             : //! - [`try_init_config`]
+     112             : //!
+     113             : //! A configurable library containing just one lint will typically have a `lib.rs` file of the
+     114             : //! following form:
+     115             : //!
+     116             : //! ```rust,ignore
+     117             : //! dylint_linting::impl_late_lint! {
+     118             : //!     ...,
+     119             : //!     LintName::new()
+     120             : //! }
+     121             : //!
+     122             : //! // Lint configuration
+     123             : //! #[derive(Default, serde::Deserialize)]
+     124             : //! struct Config {
+     125             : //!     boolean: bool,
+     126             : //!     strings: Vec<String>,
+     127             : //! }
+     128             : //!
+     129             : //! // Keep a copy of the configuration in the `LintPass` structure.
+     130             : //! struct LintName {
+     131             : //!     config: Config,
+     132             : //! }
+     133             : //!
+     134             : //! // Read the configuration from the `dylint.toml` file, or use the default configuration if
+     135             : //! // none is present.
+     136             : //! impl LintName {
+     137             : //!     pub fn new() -> Self {
+     138             : //!         Self {
+     139             : //!             config: dylint_linting::config_or_default(env!("CARGO_PKG_NAME")),
+     140             : //!         }
+     141             : //!     }
+     142             : //! }
+     143             : //! ```
+     144             : //!
+     145             : //! For a concrete example of a `lib.rs` file with this form, see the
+     146             : //! [`non_local_effect_before_error_return`] library in this repository.
+     147             : //!
+     148             : //! A library containing more than one lint must implement the `register_lints` function without
+     149             : //! relying on the above macros. If the library is configurable, then its `register_lints` function
+     150             : //! should include a call to `dylint_linting::init_config`, as in the following example:
+     151             : //!
+     152             : //! ```rust,ignore
+     153             : //! #[no_mangle]
+     154             : //! pub fn register_lints(sess: &rustc_session::Session, lint_store: &mut rustc_lint::LintStore) {
+     155             : //!     // `init_config` or `try_init_config` must be called before `config_or_default`, `config`,
+     156             : //!     // or `config_toml` is called.
+     157             : //!     dylint_linting::init_config(sess);
+     158             : //!
+     159             : //!     lint_store.register_lints(&[FIRST_LINT_NAME, SECOND_LINT_NAME]);
+     160             : //!
+     161             : //!     lint_store.register_late_pass(|_| Box::new(LintPassName::new()));
+     162             : //! }
+     163             : //! ```
+     164             : //!
+     165             : //! Additional documentation on `config_or_default`, etc. can be found on [docs.rs].
+     166             : //!
+     167             : //! [Configurable libraries]: #configurable-libraries
+     168             : //! [Dylint]: https://github.com/trailofbits/dylint/tree/master
+     169             : //! [`LintPass`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LintPass.html
+     170             : //! [`config_or_default`]: https://docs.rs/dylint_linting/latest/dylint_linting/fn.config_or_default.html
+     171             : //! [`config_toml`]: https://docs.rs/dylint_linting/latest/dylint_linting/fn.config_toml.html
+     172             : //! [`config`]: https://docs.rs/dylint_linting/latest/dylint_linting/fn.config.html
+     173             : //! [`constituent` feature]: #constituent-feature
+     174             : //! [`declare_late_lint!`, `declare_early_lint!`, `declare_pre_expansion_lint!`]: #declare_late_lint-etc
+     175             : //! [`declare_lint!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/macro.declare_lint.html
+     176             : //! [`declare_lint_pass!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/macro.declare_lint_pass.html
+     177             : //! [`dylint-link`]: https://github.com/trailofbits/dylint/tree/master/dylint-link
+     178             : //! [`dylint_library!`]: #dylint_library
+     179             : //! [`general` library]: https://github.com/trailofbits/dylint/tree/master/examples/general/src/lib.rs
+     180             : //! [`impl_late_lint!`, `impl_early_lint!`, `impl_pre_expansion_lint!`]: #impl_late_lint-etc
+     181             : //! [`impl_lint_pass!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/macro.impl_lint_pass.html
+     182             : //! [`init_config`]: https://docs.rs/dylint_linting/latest/dylint_linting/fn.init_config.html
+     183             : //! [`non_local_effect_before_error_return`]: https://github.com/trailofbits/dylint/tree/master/examples/general/non_local_effect_before_error_return/src/lib.rs
+     184             : //! [`register_lints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Config.html#structfield.register_lints
+     185             : //! [`supplementary` library]: https://github.com/trailofbits/dylint/tree/master/examples/supplementary/src/lib.rs
+     186             : //! [`try_init_config`]: https://docs.rs/dylint_linting/latest/dylint_linting/fn.try_init_config.html
+     187             : //! [docs.rs documentation]: https://docs.rs/dylint_linting/latest/dylint_linting/
+     188             : //! [docs.rs]: https://docs.rs/dylint_linting/latest/dylint_linting/
+     189             : //! [examples]: https://github.com/trailofbits/dylint/tree/master/examples
+     190             : //! [general-purpose]: https://github.com/trailofbits/dylint/tree/master/examples/general
+     191             : //! [supplementary]: https://github.com/trailofbits/dylint/tree/master/examples/supplementary
+     192             : 
+     193             : #![feature(rustc_private)]
+     194             : #![warn(unused_extern_crates)]
+     195             : 
+     196             : #[allow(unused_extern_crates)]
+     197             : extern crate rustc_driver;
+     198             : 
+     199             : extern crate rustc_session;
+     200             : extern crate rustc_span;
+     201             : 
+     202             : use dylint_internal::env;
+     203             : use rustc_span::Symbol;
+     204             : use std::{
+     205             :     any::type_name,
+     206             :     fs::read_to_string,
+     207             :     path::{Path, PathBuf},
+     208             :     sync::OnceLock,
+     209             : };
+     210             : use thiserror::Error;
+     211             : 
+     212             : pub const DYLINT_VERSION: &str = "0.1.0";
+     213             : 
+     214             : pub use paste;
+     215             : 
+     216             : // smoelius: Including `extern crate rustc_driver` causes the library to link against
+     217             : // `librustc_driver.so`, which dylint-driver also links against. So, essentially, the library uses
+     218             : // dylint-driver's copy of the Rust compiler crates.
+     219             : #[macro_export]
+     220             : macro_rules! dylint_library {
+     221             :     () => {
+     222             :         #[allow(unused_extern_crates)]
+     223             :         extern crate rustc_driver;
+     224             : 
+     225             :         #[doc(hidden)]
+     226             :         #[no_mangle]
+     227             :         pub extern "C" fn dylint_version() -> *mut std::os::raw::c_char {
+     228             :             std::ffi::CString::new($crate::DYLINT_VERSION)
+     229             :                 .unwrap()
+     230             :                 .into_raw()
+     231             :         }
+     232             :     };
+     233             : }
+     234             : 
+     235             : #[cfg(not(feature = "constituent"))]
+     236             : #[doc(hidden)]
+     237             : #[macro_export]
+     238             : macro_rules! __maybe_exclude {
+     239             :     ($item:item) => {
+     240             :         $item
+     241             :     };
+     242             : }
+     243             : 
+     244             : #[cfg(feature = "constituent")]
+     245             : #[doc(hidden)]
+     246             : #[macro_export]
+     247             : macro_rules! __maybe_exclude {
+     248             :     ($item:item) => {};
+     249             : }
+     250             : 
+     251             : #[cfg(not(feature = "constituent"))]
+     252             : #[doc(hidden)]
+     253             : #[macro_export]
+     254             : macro_rules! __maybe_mangle {
+     255             :     ($item:item) => {
+     256             :         #[no_mangle]
+     257             :         $item
+     258             :     };
+     259             : }
+     260             : 
+     261             : #[cfg(feature = "constituent")]
+     262             : #[doc(hidden)]
+     263             : #[macro_export]
+     264             : macro_rules! __maybe_mangle {
+     265             :     ($item:item) => {
+     266             :         $item
+     267             :     };
+     268             : }
+     269             : 
+     270             : #[doc(hidden)]
+     271             : #[macro_export]
+     272             : macro_rules! __declare_and_register_lint {
+     273             :     ($(#[$attr:meta])* $vis:vis $NAME:ident, $Level:ident, $desc:expr, $register_pass_method:ident, $pass:expr) => {
+     274             :         $crate::__maybe_exclude! {
+     275             :             $crate::dylint_library!();
+     276             :         }
+     277             : 
+     278             :         extern crate rustc_lint;
+     279             :         extern crate rustc_session;
+     280             : 
+     281             :         $crate::__maybe_mangle! {
+     282             :             #[allow(clippy::no_mangle_with_rust_abi)]
+     283             :             pub fn register_lints(sess: &rustc_session::Session, lint_store: &mut rustc_lint::LintStore) {
+     284             :                 $crate::init_config(sess);
+     285             :                 lint_store.register_lints(&[$NAME]);
+     286             :                 lint_store.$register_pass_method($pass);
+     287             :             }
+     288             :         }
+     289             : 
+     290             :         rustc_session::declare_lint!($(#[$attr])* $vis $NAME, $Level, $desc);
+     291             :     };
+     292             : }
+     293             : 
+     294             : #[rustversion::before(2022-09-08)]
+     295             : #[doc(hidden)]
+     296             : #[macro_export]
+     297             : macro_rules! __make_late_closure {
+     298             :     ($pass:expr) => {
+     299             :         || Box::new($pass)
+     300             :     };
+     301             : }
+     302             : 
+     303             : // smoelius: Relevant PR and merge commit:
+     304             : // - https://github.com/rust-lang/rust/pull/101501
+     305             : // - https://github.com/rust-lang/rust/commit/87788097b776f8e3662f76627944230684b671bd
+     306             : #[rustversion::since(2022-09-08)]
+     307             : #[doc(hidden)]
+     308             : #[macro_export]
+     309             : macro_rules! __make_late_closure {
+     310             :     ($pass:expr) => {
+     311             :         |_| Box::new($pass)
+     312             :     };
+     313             : }
+     314             : 
+     315             : #[macro_export]
+     316             : macro_rules! impl_pre_expansion_lint {
+     317             :     ($(#[$attr:meta])* $vis:vis $NAME:ident, $Level:ident, $desc:expr, $pass:expr) => {
+     318             :         $crate::__declare_and_register_lint!(
+     319             :             $(#[$attr])* $vis $NAME,
+     320             :             $Level,
+     321             :             $desc,
+     322             :             register_pre_expansion_pass,
+     323             :             || Box::new($pass)
+     324             :         );
+     325             :         $crate::paste::paste! {
+     326             :             rustc_session::impl_lint_pass!([< $NAME:camel >] => [$NAME]);
+     327             :         }
+     328             :     };
+     329             : }
+     330             : 
+     331             : #[macro_export]
+     332             : macro_rules! impl_early_lint {
+     333             :     ($(#[$attr:meta])* $vis:vis $NAME:ident, $Level:ident, $desc:expr, $pass:expr) => {
+     334             :         $crate::__declare_and_register_lint!(
+     335             :             $(#[$attr])* $vis $NAME,
+     336             :             $Level,
+     337             :             $desc,
+     338             :             register_early_pass,
+     339             :             || Box::new($pass)
+     340             :         );
+     341             :         $crate::paste::paste! {
+     342             :             rustc_session::impl_lint_pass!([< $NAME:camel >] => [$NAME]);
+     343             :         }
+     344             :     };
+     345             : }
+     346             : 
+     347             : #[macro_export]
+     348             : macro_rules! impl_late_lint {
+     349             :     ($(#[$attr:meta])* $vis:vis $NAME:ident, $Level:ident, $desc:expr, $pass:expr) => {
+     350             :         $crate::__declare_and_register_lint!(
+     351             :             $(#[$attr])* $vis $NAME,
+     352             :             $Level,
+     353             :             $desc,
+     354             :             register_late_pass,
+     355             :             $crate::__make_late_closure!($pass)
+     356             :         );
+     357             :         $crate::paste::paste! {
+     358             :             rustc_session::impl_lint_pass!([< $NAME:camel >] => [$NAME]);
+     359             :         }
+     360             :     };
+     361             : }
+     362             : 
+     363             : #[macro_export]
+     364             : macro_rules! declare_pre_expansion_lint {
+     365             :     ($(#[$attr:meta])* $vis:vis $NAME:ident, $Level:ident, $desc:expr) => {
+     366             :         $crate::paste::paste! {
+     367             :             $crate::__declare_and_register_lint!(
+     368             :                 $(#[$attr])* $vis $NAME,
+     369             :                 $Level,
+     370             :                 $desc,
+     371             :                 register_pre_expansion_pass,
+     372             :                 || Box::new([< $NAME:camel >])
+     373             :             );
+     374             :             rustc_session::declare_lint_pass!([< $NAME:camel >] => [$NAME]);
+     375             :         }
+     376             :     };
+     377             : }
+     378             : 
+     379             : #[macro_export]
+     380             : macro_rules! declare_early_lint {
+     381             :     ($(#[$attr:meta])* $vis:vis $NAME:ident, $Level:ident, $desc:expr) => {
+     382             :         $crate::paste::paste! {
+     383             :             $crate::__declare_and_register_lint!(
+     384             :                 $(#[$attr])* $vis $NAME,
+     385             :                 $Level,
+     386             :                 $desc,
+     387             :                 register_early_pass,
+     388             :                 || Box::new([< $NAME:camel >])
+     389             :             );
+     390             :             rustc_session::declare_lint_pass!([< $NAME:camel >] => [$NAME]);
+     391             :         }
+     392             :     };
+     393             : }
+     394             : 
+     395             : #[macro_export]
+     396             : macro_rules! declare_late_lint {
+     397             :     ($(#[$attr:meta])* $vis:vis $NAME:ident, $Level:ident, $desc:expr) => {
+     398             :         $crate::paste::paste! {
+     399             :             $crate::__declare_and_register_lint!(
+     400             :                 $(#[$attr])* $vis $NAME,
+     401             :                 $Level,
+     402             :                 $desc,
+     403             :                 register_late_pass,
+     404             :                 $crate::__make_late_closure!([< $NAME:camel >])
+     405             :             );
+     406             :             rustc_session::declare_lint_pass!([< $NAME:camel >] => [$NAME]);
+     407             :         }
+     408             :     };
+     409             : }
+     410             : 
+     411             : pub type ConfigResult<T> = Result<T, ConfigError>;
+     412             : 
+     413             : #[derive(Debug)]
+     414             : pub struct ConfigError {
+     415             :     inner: ConfigErrorInner,
+     416             : }
+     417             : 
+     418             : impl std::fmt::Display for ConfigError {
+     419           0 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+     420           0 :         write!(f, "{}", self.inner)
+     421           0 :     }
+     422             : }
+     423             : 
+     424             : impl<T> From<T> for ConfigError
+     425             : where
+     426             :     ConfigErrorInner: From<T>,
+     427             : {
+     428           0 :     fn from(value: T) -> Self {
+     429           0 :         Self {
+     430           0 :             inner: ConfigErrorInner::from(value),
+     431           0 :         }
+     432           0 :     }
+     433             : }
+     434             : 
+     435           0 : #[derive(Debug, Error)]
+     436             : enum ConfigErrorInner {
+     437             :     #[error("cargo metadata error: {0}")]
+     438             :     CargoMetadata(#[from] cargo_metadata::Error),
+     439             :     #[error("io error: {0}: {1}")]
+     440             :     Io(String, std::io::Error),
+     441             :     #[error("toml error: {0}")]
+     442             :     Toml(#[from] toml::de::Error),
+     443             :     #[error("{0}")]
+     444             :     Other(String),
+     445             : }
+     446             : 
+     447             : static CONFIG_TABLE: OnceLock<toml::value::Table> = OnceLock::new();
+     448             : 
+     449             : /// Reads and deserializes an entry from the workspace's `dylint.toml` file, and returns the default
+     450             : /// value if the entry is not present.
+     451             : ///
+     452             : /// - If the target workspace's `dylint.toml` file contains key `name` and its value can be
+     453             : ///   deserializes as `T`, `config_or_default` returns the deserialized value.
+     454             : /// - If the target workspace's `dylint.toml` file does not exist or does not contain key `name`,
+     455             : ///   `config_or_default` returns `T::default()`.
+     456             : /// - If an error occurs (e.g., the value cannot be deserialized as `T`), `config_or_default`
+     457             : ///   panics.
+     458             : ///
+     459             : /// Note: `init_config` or `try_init_config` must be called before `config_or_default` is called.
+     460             : /// However, the `register_lints` function generated by `impl_late_lint`, etc. includes a call to
+     461             : /// `init_config`.
+     462           0 : pub fn config_or_default<T: Default + serde::de::DeserializeOwned>(name: &str) -> T {
+     463           0 :     config::<T>(name).map_or_else(
+     464           0 :         |error| {
+     465           0 :             panic!(
+     466           0 :                 "Could not parse config as `{}`: {}",
+     467           0 :                 type_name::<T>(),
+     468           0 :                 error
+     469           0 :             )
+     470           0 :         },
+     471           0 :         Option::unwrap_or_default,
+     472           0 :     )
+     473           0 : }
+     474             : 
+     475             : /// Reads and deserializes an entry from the workspace's `dylint.toml` file.
+     476             : ///
+     477             : /// Returns:
+     478             : /// - `Ok(Some(...))` if the target workspace's `dylint.toml` file contains key `name` and its value
+     479             : ///   can be deserialized as `T`
+     480             : /// - `Ok(None)` if the target workspace's `dylint.toml` file does not exist or does not contain key
+     481             : ///   `name`
+     482             : /// - `Err(...)` if an error occurs (e.g., the value cannot be deserialized as `T`)
+     483             : ///
+     484             : /// Note: `init_config` or `try_init_config` must be called before `config` is called. However, the
+     485             : /// `register_lints` function generated by `impl_late_lint`, etc. includes a call to `init_config`.
+     486           0 : pub fn config<T: serde::de::DeserializeOwned>(name: &str) -> ConfigResult<Option<T>> {
+     487           0 :     let toml = config_toml(name)?;
+     488           0 :     toml.map(toml::Value::try_into::<T>)
+     489           0 :         .transpose()
+     490           0 :         .map_err(Into::into)
+     491           0 : }
+     492             : 
+     493             : /// Reads an entry from the workspace's `dylint.toml` file as a raw `toml::Value`.
+     494             : ///
+     495             : /// Returns:
+     496             : /// - `Ok(Some(...))` if the target workspace's `dylint.toml` file contains key `name`
+     497             : /// - `Ok(None)` if the target workspace's `dylint.toml` file does not exist or does not contain key
+     498             : ///   `name`
+     499             : /// - `Err(...)` if an error occurs (e.g., `init_config` was not called)
+     500             : ///
+     501             : /// Note: `init_config` or `try_init_config` must be called before `config_toml` is called. However,
+     502             : /// the `register_lints` function generated by `impl_late_lint`, etc. includes a call to
+     503             : /// `init_config`.
+     504           0 : pub fn config_toml(name: &str) -> ConfigResult<Option<toml::Value>> {
+     505           0 :     let Some(config_table) = CONFIG_TABLE.get() else {
+     506           0 :         return Err(ConfigErrorInner::Other(
+     507           0 :             "Config is not initialized; `init_config` should have been called from \
+     508           0 :              `register_lints`"
+     509           0 :                 .into(),
+     510           0 :         )
+     511           0 :         .into());
+     512             :     };
+     513           0 :     Ok(config_table.get(name).cloned())
+     514           0 : }
+     515             : 
+     516             : /// A wrapper around `try_init_config`. Calls `rustc_session::early_error` if `try_init_config`
+     517             : /// returns an error.
+     518             : ///
+     519             : /// Note: `init_config` or `try_init_config` must be called before `config_or_default`, `config`, or
+     520             : /// `config_toml` is called. However, the `register_lints` function generated by `impl_late_lint`,
+     521             : /// etc. includes a call to `init_config`.
+     522           0 : pub fn init_config(sess: &rustc_session::Session) {
+     523           0 :     try_init_config(sess).unwrap_or_else(|err| {
+     524           0 :         let msg = format!("could not read configuration file: {err}");
+     525           0 :         early_error(msg);
+     526           0 :     });
+     527           0 : }
+     528             : 
+     529             : trait ParseSess {
+     530             :     fn parse_sess(&self) -> &rustc_session::parse::ParseSess;
+     531             : }
+     532             : 
+     533             : impl ParseSess for rustc_session::Session {
+     534             :     #[rustversion::before(2024-03-05)]
+     535             :     fn parse_sess(&self) -> &rustc_session::parse::ParseSess {
+     536             :         &self.parse_sess
+     537             :     }
+     538             : 
+     539             :     #[rustversion::since(2024-03-05)]
+     540           0 :     fn parse_sess(&self) -> &rustc_session::parse::ParseSess {
+     541           0 :         &self.psess
+     542           0 :     }
+     543             : }
+     544             : 
+     545             : /// Reads the target workspace's `dylint.toml` file and parses it as a `toml::value::Table`.
+     546             : ///
+     547             : /// Note: `init_config` or `try_init_config` must be called before `config_or_default`, `config`, or
+     548             : /// `config_toml` is called. However, the `register_lints` function generated by `impl_late_lint`,
+     549             : /// etc. includes a call to `init_config`.
+     550           0 : pub fn try_init_config(sess: &rustc_session::Session) -> ConfigResult<()> {
+     551           0 :     if CONFIG_TABLE.get().is_some() {
+     552           0 :         return Ok(());
+     553           0 :     }
+     554             : 
+     555             :     #[cfg_attr(dylint_lib = "supplementary", allow(commented_code))]
+     556           0 :     let value = if let Ok(value) = std::env::var(env::DYLINT_TOML) {
+     557           0 :         sess.parse_sess().env_depinfo.lock().insert((
+     558           0 :             Symbol::intern(env::DYLINT_TOML),
+     559           0 :             Some(Symbol::intern(&value)),
+     560           0 :         ));
+     561           0 :         Some(value)
+     562           0 :     } else if let Some(local_crate_source_file) = local_crate_source_file(sess).and_then(|path| {
+     563           0 :         if path == PathBuf::new() {
+     564           0 :             None
+     565             :         } else {
+     566           0 :             Some(path)
+     567             :         }
+     568           0 :     }) {
+     569             :         #[rustfmt::skip]
+     570             :         // smoelius: Canonicalizing `local_crate_source_file` causes errors like the following on
+     571             :         // Windows:
+     572             :         //
+     573             :         //   error: could not read configuration file: cargo metadata error: `cargo metadata` exited with an error: error: failed to load manifest for dependency `await_holding_span_guard`
+     574             :         //
+     575             :         //          Caused by:
+     576             :         //            failed to parse manifest at `D:\a\dylint\dylint\examples\general\await_holding_span_guard\Cargo.toml`
+     577             :         //
+     578             :         //          Caused by:
+     579             :         //            error inheriting `clippy_utils` from workspace root manifest's `workspace.dependencies.clippy_utils`
+     580             :         //
+     581             :         //          Caused by:
+     582             :         //            `workspace.dependencies` was not defined
+     583             :         //
+     584             :         // The issue is that `canonicalize` prepends `\\?\` to the path, and such "verbatim" paths
+     585             :         // cause problems for Cargo. See the following GitHub issue for more information:
+     586             :         // https://github.com/rust-lang/cargo/issues/9770#issuecomment-993069234
+     587             :         //
+     588             :         // For reasons that I don't understand, fixing this problem in Cargo would be difficult.
+     589             : 
+     590             :         /* let local_crate_source_file = local_crate_source_file.canonicalize().map_err(|error| {
+     591             :             ConfigErrorInner::Io(
+     592             :                 format!("Could not canonicalize {local_crate_source_file:?}"),
+     593             :                 error,
+     594             :             )
+     595             :         })?; */
+     596             : 
+     597           0 :         let mut parent = local_crate_source_file
+     598           0 :             .parent()
+     599           0 :             .ok_or_else(|| ConfigErrorInner::Other("Could not get parent directory".into()))?;
+     600             : 
+     601             :         // smoelius: https://users.rust-lang.org/t/pathbuf-equivalent-to-string-is-empty/24823
+     602           0 :         if parent.as_os_str().is_empty() {
+     603           0 :             parent = Path::new(".");
+     604           0 :         };
+     605             : 
+     606           0 :         let result = cargo_metadata::MetadataCommand::new()
+     607           0 :             .current_dir(parent)
+     608           0 :             .no_deps()
+     609           0 :             .exec();
+     610             : 
+     611           0 :         match result {
+     612           0 :             Err(cargo_metadata::Error::CargoMetadata { stderr })
+     613           0 :                 if stderr.contains("could not find `Cargo.toml`") =>
+     614           0 :             {
+     615           0 :                 None
+     616             :             }
+     617             :             _ => {
+     618           0 :                 let cargo_metadata::Metadata { workspace_root, .. } = result?;
+     619             : 
+     620           0 :                 let dylint_toml = workspace_root.join("dylint.toml");
+     621           0 : 
+     622           0 :                 if dylint_toml.try_exists().map_err(|error| {
+     623           0 :                     ConfigErrorInner::Io(format!("`try_exists` failed for {dylint_toml:?}"), error)
+     624           0 :                 })? {
+     625           0 :                     let value = read_to_string(&dylint_toml).map_err(|error| {
+     626           0 :                         ConfigErrorInner::Io(
+     627           0 :                             format!("`read_to_string` failed for {dylint_toml:?}"),
+     628           0 :                             error,
+     629           0 :                         )
+     630           0 :                     })?;
+     631           0 :                     sess.parse_sess()
+     632           0 :                         .file_depinfo
+     633           0 :                         .lock()
+     634           0 :                         .insert(Symbol::intern(dylint_toml.as_str()));
+     635           0 :                     Some(value)
+     636             :                 } else {
+     637           0 :                     None
+     638             :                 }
+     639             :             }
+     640             :         }
+     641             :     } else {
+     642           0 :         None
+     643             :     };
+     644             : 
+     645           0 :     let toml: Option<toml::Value> = value.as_deref().map(toml::from_str).transpose()?;
+     646             : 
+     647           0 :     let table = toml
+     648           0 :         .map(|toml| {
+     649           0 :             toml.as_table()
+     650           0 :                 .cloned()
+     651           0 :                 .ok_or_else(|| ConfigErrorInner::Other("Value is not a table".into()))
+     652           0 :         })
+     653           0 :         .transpose()?;
+     654             : 
+     655             :     // smoelius: Rewrite this function (`try_init_config`) and eliminate the next `expect` once
+     656             :     // `get_or_try_init` stabilizes: https://github.com/rust-lang/rust/issues/109737
+     657           0 :     CONFIG_TABLE
+     658           0 :         .set(table.unwrap_or_default())
+     659           0 :         .expect("`CONFIG_TABLE` was determined to be unset above");
+     660           0 : 
+     661           0 :     Ok(())
+     662           0 : }
+     663             : 
+     664             : #[rustversion::before(2023-01-19)]
+     665             : fn local_crate_source_file(sess: &rustc_session::Session) -> Option<PathBuf> {
+     666             :     sess.local_crate_source_file.clone()
+     667             : }
+     668             : 
+     669             : // smoelius: Relevant PR and merge commit:
+     670             : // - https://github.com/rust-lang/rust/pull/106810
+     671             : // - https://github.com/rust-lang/rust/commit/65d2f2a5f9c323c88d1068e8e90d0b47a20d491c
+     672             : #[rustversion::all(since(2023-01-19), before(2024-03-29))]
+     673             : fn local_crate_source_file(sess: &rustc_session::Session) -> Option<PathBuf> {
+     674             :     sess.local_crate_source_file()
+     675             : }
+     676             : 
+     677             : // smoelius: Relevant PR and merge commit:
+     678             : // - https://github.com/rust-lang/rust/pull/122450
+     679             : // - https://github.com/rust-lang/rust/commit/685927aae69657b46323cffbeb0062835bd7fa2b
+     680             : #[rustversion::since(2024-03-29)]
+     681           0 : fn local_crate_source_file(sess: &rustc_session::Session) -> Option<PathBuf> {
+     682           0 :     use rustc_span::RealFileName;
+     683           0 :     sess.local_crate_source_file()
+     684           0 :         .and_then(RealFileName::into_local_path)
+     685           0 : }
+     686             : 
+     687             : #[rustversion::before(2023-06-28)]
+     688             : fn early_error(msg: String) -> ! {
+     689             :     rustc_session::early_error(
+     690             :         rustc_session::config::ErrorOutputType::default(),
+     691             :         Box::leak(msg.into_boxed_str()) as &str,
+     692             :     )
+     693             : }
+     694             : 
+     695             : #[rustversion::since(2023-06-28)]
+     696             : extern crate rustc_errors;
+     697             : 
+     698             : #[rustversion::all(since(2023-06-28), before(2023-12-18))]
+     699             : fn early_error(msg: impl Into<rustc_errors::DiagnosticMessage>) -> ! {
+     700             :     let handler =
+     701             :         rustc_session::EarlyErrorHandler::new(rustc_session::config::ErrorOutputType::default());
+     702             :     handler.early_error(msg)
+     703             : }
+     704             : 
+     705             : #[rustversion::all(since(2023-12-18), before(2023-12-23))]
+     706             : fn early_error(msg: impl Into<rustc_errors::DiagnosticMessage>) -> ! {
+     707             :     let handler =
+     708             :         rustc_session::EarlyDiagCtxt::new(rustc_session::config::ErrorOutputType::default());
+     709             :     handler.early_error(msg)
+     710             : }
+     711             : 
+     712             : #[rustversion::all(since(2023-12-23), before(2024-03-05))]
+     713             : fn early_error(msg: impl Into<rustc_errors::DiagnosticMessage>) -> ! {
+     714             :     let handler =
+     715             :         rustc_session::EarlyDiagCtxt::new(rustc_session::config::ErrorOutputType::default());
+     716             :     handler.early_fatal(msg)
+     717             : }
+     718             : 
+     719             : #[rustversion::since(2024-03-05)]
+     720           0 : fn early_error(msg: impl Into<rustc_errors::DiagMessage>) -> ! {
+     721           0 :     let handler =
+     722           0 :         rustc_session::EarlyDiagCtxt::new(rustc_session::config::ErrorOutputType::default());
+     723           0 :     handler.early_fatal(msg)
+     724             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/utils/testing/src/index-sort-f.html b/coverage/utils/testing/src/index-sort-f.html new file mode 100644 index 000000000..d771b9bae --- /dev/null +++ b/coverage/utils/testing/src/index-sort-f.html @@ -0,0 +1,103 @@ + + + + + + + LCOV - unnamed - utils/testing/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/testing/srcHitTotalCoverage
Test:unnamedLines:02970.0 %
Date:2024-04-23 03:30:56Functions:0450.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
ui.rs +
0.0%
+
0.0 %0 / 600.0 %0 / 9
lib.rs +
0.0%
+
0.0 %0 / 2370.0 %0 / 36
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/utils/testing/src/index-sort-l.html b/coverage/utils/testing/src/index-sort-l.html new file mode 100644 index 000000000..7d5fe82ed --- /dev/null +++ b/coverage/utils/testing/src/index-sort-l.html @@ -0,0 +1,103 @@ + + + + + + + LCOV - unnamed - utils/testing/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/testing/srcHitTotalCoverage
Test:unnamedLines:02970.0 %
Date:2024-04-23 03:30:56Functions:0450.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
ui.rs +
0.0%
+
0.0 %0 / 600.0 %0 / 9
lib.rs +
0.0%
+
0.0 %0 / 2370.0 %0 / 36
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/utils/testing/src/index.html b/coverage/utils/testing/src/index.html new file mode 100644 index 000000000..2895e21e7 --- /dev/null +++ b/coverage/utils/testing/src/index.html @@ -0,0 +1,103 @@ + + + + + + + LCOV - unnamed - utils/testing/src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/testing/srcHitTotalCoverage
Test:unnamedLines:02970.0 %
Date:2024-04-23 03:30:56Functions:0450.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverage
lib.rs +
0.0%
+
0.0 %0 / 2370.0 %0 / 36
ui.rs +
0.0%
+
0.0 %0 / 600.0 %0 / 9
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/utils/testing/src/lib.rs.func-sort-c.html b/coverage/utils/testing/src/lib.rs.func-sort-c.html new file mode 100644 index 000000000..3222d505b --- /dev/null +++ b/coverage/utils/testing/src/lib.rs.func-sort-c.html @@ -0,0 +1,216 @@ + + + + + + + LCOV - unnamed - utils/testing/src/lib.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/testing/src - lib.rs (source / functions)HitTotalCoverage
Test:unnamedLines:02370.0 %
Date:2024-04-23 03:30:56Functions:0360.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint_testing::VarGuard as core::ops::drop::Drop>::drop0
<dylint_testing::VarGuard>::set::<_>0
dylint_testing::RE::{closure#0}0
dylint_testing::copy_with_extension::<_0
dylint_testing::dylint_libs0
dylint_testing::example_target0
dylint_testing::example_target::{closure#0}0
dylint_testing::example_target::{closure#1}0
dylint_testing::example_targets0
dylint_testing::example_targets::{closure#0}0
dylint_testing::initialize0
dylint_testing::initialize::{closure#0}0
dylint_testing::linking_flags0
dylint_testing::linking_flags::{closure#0}0
dylint_testing::next::<_0
dylint_testing::remove_example0
dylint_testing::remove_example::{closure#0}0
dylint_testing::remove_example::{closure#1}0
dylint_testing::remove_example::{closure#2}0
dylint_testing::run_example_test0
dylint_testing::run_example_test::{closure#0}0
dylint_testing::run_example_test::{closure#1}0
dylint_testing::run_example_test::{closure#2}0
dylint_testing::run_example_test::{closure#3}0
dylint_testing::run_tests0
dylint_testing::run_tests::{closure#0}0
dylint_testing::rustc_flags0
dylint_testing::rustc_flags::{closure#0}0
dylint_testing::rustc_flags::{closure#0}::{closure#0}0
dylint_testing::rustc_flags::{closure#0}::{closure#1}0
dylint_testing::rustc_flags::{closure#0}::{closure#1}::{closure#0}0
dylint_testing::rustc_flags::{closure#1}0
dylint_testing::snake_case0
dylint_testing::ui_test0
dylint_testing::ui_test_example0
dylint_testing::ui_test_examples0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/utils/testing/src/lib.rs.func.html b/coverage/utils/testing/src/lib.rs.func.html new file mode 100644 index 000000000..993fb95d8 --- /dev/null +++ b/coverage/utils/testing/src/lib.rs.func.html @@ -0,0 +1,216 @@ + + + + + + + LCOV - unnamed - utils/testing/src/lib.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/testing/src - lib.rs (source / functions)HitTotalCoverage
Test:unnamedLines:02370.0 %
Date:2024-04-23 03:30:56Functions:0360.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint_testing::VarGuard as core::ops::drop::Drop>::drop0
<dylint_testing::VarGuard>::set::<_>0
dylint_testing::RE::{closure#0}0
dylint_testing::copy_with_extension::<_0
dylint_testing::dylint_libs0
dylint_testing::example_target0
dylint_testing::example_target::{closure#0}0
dylint_testing::example_target::{closure#1}0
dylint_testing::example_targets0
dylint_testing::example_targets::{closure#0}0
dylint_testing::initialize0
dylint_testing::initialize::{closure#0}0
dylint_testing::linking_flags0
dylint_testing::linking_flags::{closure#0}0
dylint_testing::next::<_0
dylint_testing::remove_example0
dylint_testing::remove_example::{closure#0}0
dylint_testing::remove_example::{closure#1}0
dylint_testing::remove_example::{closure#2}0
dylint_testing::run_example_test0
dylint_testing::run_example_test::{closure#0}0
dylint_testing::run_example_test::{closure#1}0
dylint_testing::run_example_test::{closure#2}0
dylint_testing::run_example_test::{closure#3}0
dylint_testing::run_tests0
dylint_testing::run_tests::{closure#0}0
dylint_testing::rustc_flags0
dylint_testing::rustc_flags::{closure#0}0
dylint_testing::rustc_flags::{closure#0}::{closure#0}0
dylint_testing::rustc_flags::{closure#0}::{closure#1}0
dylint_testing::rustc_flags::{closure#0}::{closure#1}::{closure#0}0
dylint_testing::rustc_flags::{closure#1}0
dylint_testing::snake_case0
dylint_testing::ui_test0
dylint_testing::ui_test_example0
dylint_testing::ui_test_examples0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/utils/testing/src/lib.rs.gcov.html b/coverage/utils/testing/src/lib.rs.gcov.html new file mode 100644 index 000000000..13287002f --- /dev/null +++ b/coverage/utils/testing/src/lib.rs.gcov.html @@ -0,0 +1,553 @@ + + + + + + + LCOV - unnamed - utils/testing/src/lib.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/testing/src - lib.rs (source / functions)HitTotalCoverage
Test:unnamedLines:02370.0 %
Date:2024-04-23 03:30:56Functions:0360.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : //! This crate provides convenient access to the [`compiletest_rs`] package for testing [Dylint]
+       2             : //! libraries.
+       3             : //!
+       4             : //! **Note: If your test has dependencies, you must use `ui_test_example` or `ui_test_examples`.**
+       5             : //! See the [`question_mark_in_expression`] example in this repository.
+       6             : //!
+       7             : //! This crate provides the following three functions:
+       8             : //!
+       9             : //! - [`ui_test`] - test a library on all source files in a directory
+      10             : //! - [`ui_test_example`] - test a library on one example target
+      11             : //! - [`ui_test_examples`] - test a library on all example targets
+      12             : //!
+      13             : //! For most situations, you can add the following to your library's `lib.rs` file:
+      14             : //!
+      15             : //! ```rust,ignore
+      16             : //! #[test]
+      17             : //! fn ui() {
+      18             : //!     dylint_testing::ui_test(
+      19             : //!         env!("CARGO_PKG_NAME"),
+      20             : //!         &std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("ui"),
+      21             : //!     );
+      22             : //! }
+      23             : //! ```
+      24             : //!
+      25             : //! And include one or more `.rs` and `.stderr` files in a `ui` directory alongside your library's
+      26             : //! `src` directory. See the [examples] in this repository.
+      27             : //!
+      28             : //! # Test builder
+      29             : //!
+      30             : //! In addition to the above three functions, [`ui::Test`] is a test "builder." Currently, the main
+      31             : //! advantage of using `Test` over the above functions is that `Test` allows flags to be passed to
+      32             : //! `rustc`. For an example of its use, see [`non_thread_safe_call_in_test`] in this repository.
+      33             : //!
+      34             : //! `Test` has three constructors, which correspond to the above three functions as follows:
+      35             : //!
+      36             : //! - [`ui::Test::src_base`] <-> [`ui_test`]
+      37             : //! - [`ui::Test::example`] <-> [`ui_test_example`]
+      38             : //! - [`ui::Test::examples`] <-> [`ui_test_examples`]
+      39             : //!
+      40             : //! In each case, the constructor's arguments are exactly those of the corresponding function.
+      41             : //!
+      42             : //! A `Test` instance has the following methods:
+      43             : //!
+      44             : //! - `dylint_toml` - set the `dylint.toml` file's contents (for testing [configurable libraries])
+      45             : //! - `rustc_flags` - pass flags to the compiler when running the test
+      46             : //! - `run` - run the test
+      47             : //!
+      48             : //! # Updating `.stderr` files
+      49             : //!
+      50             : //! If the standard error that results from running your `.rs` file differs from the contents of
+      51             : //! your `.stderr` file, `compiletest_rs` will produce a report like the following:
+      52             : //!
+      53             : //! ```text
+      54             : //! diff of stderr:
+      55             : //!
+      56             : //!  error: calling `std::env::set_var` in a test could affect the outcome of other tests
+      57             : //!    --> $DIR/main.rs:8:5
+      58             : //!     |
+      59             : //!  LL |     std::env::set_var("KEY", "VALUE");
+      60             : //!     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+      61             : //!     |
+      62             : //!     = note: `-D non-thread-safe-call-in-test` implied by `-D warnings`
+      63             : //!
+      64             : //! -error: aborting due to previous error
+      65             : //! +error: calling `std::env::set_var` in a test could affect the outcome of other tests
+      66             : //! +  --> $DIR/main.rs:23:9
+      67             : //! +   |
+      68             : //! +LL |         std::env::set_var("KEY", "VALUE");
+      69             : //! +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+      70             : //! +
+      71             : //! +error: aborting due to 2 previous errors
+      72             : //!
+      73             : //!
+      74             : //!
+      75             : //! The actual stderr differed from the expected stderr.
+      76             : //! Actual stderr saved to ...
+      77             : //! ```
+      78             : //!
+      79             : //! The meaning of each line is as follows:
+      80             : //!
+      81             : //! - A line beginning with a plus (`+`) is in the actual standard error, but not in your `.stderr`
+      82             : //!   file.
+      83             : //! - A line beginning with a minus (`-`) is in your `.stderr` file, but not in the actual standard
+      84             : //!   error.
+      85             : //! - A line beginning with a space (` `) is in both the actual standard error and your `.stderr`
+      86             : //!   file, and is provided for context.
+      87             : //! - All other lines (e.g., `diff of stderr:`) contain `compiletest_rs` messages.
+      88             : //!
+      89             : //! **Note:** In the actual standard error, a blank line usually follows the `error: aborting due to
+      90             : //! N previous errors` line. So a correct `.stderr` file will typically contain one blank line at
+      91             : //! the end.
+      92             : //!
+      93             : //! In general, it is not too hard to update a `.stderr` file by hand. However, the `compiletest_rs`
+      94             : //! report should contain a line of the form `Actual stderr saved to PATH`. Copying `PATH` to your
+      95             : //! `.stderr` file should update it completely.
+      96             : //!
+      97             : //! Additional documentation on `compiletest_rs` can be found in [its repository].
+      98             : //!
+      99             : //! [Dylint]: https://github.com/trailofbits/dylint/tree/master
+     100             : //! [`compiletest_rs`]: https://github.com/Manishearth/compiletest-rs
+     101             : //! [`non_thread_safe_call_in_test`]: https://github.com/trailofbits/dylint/tree/master/examples/general/non_thread_safe_call_in_test/src/lib.rs
+     102             : //! [`question_mark_in_expression`]: https://github.com/trailofbits/dylint/tree/master/examples/restriction/question_mark_in_expression/Cargo.toml
+     103             : //! [`ui::Test::example`]: https://docs.rs/dylint_testing/latest/dylint_testing/ui/struct.Test.html#method.example
+     104             : //! [`ui::Test::examples`]: https://docs.rs/dylint_testing/latest/dylint_testing/ui/struct.Test.html#method.examples
+     105             : //! [`ui::Test::src_base`]: https://docs.rs/dylint_testing/latest/dylint_testing/ui/struct.Test.html#method.src_base
+     106             : //! [`ui::Test`]: https://docs.rs/dylint_testing/latest/dylint_testing/ui/struct.Test.html
+     107             : //! [`ui_test_example`]: https://docs.rs/dylint_testing/latest/dylint_testing/fn.ui_test_example.html
+     108             : //! [`ui_test_examples`]: https://docs.rs/dylint_testing/latest/dylint_testing/fn.ui_test_examples.html
+     109             : //! [`ui_test`]: https://docs.rs/dylint_testing/latest/dylint_testing/fn.ui_test.html
+     110             : //! [configurable libraries]: https://github.com/trailofbits/dylint/tree/master#configurable-libraries
+     111             : //! [docs.rs documentation]: https://docs.rs/dylint_testing/latest/dylint_testing/
+     112             : //! [examples]: https://github.com/trailofbits/dylint/tree/master/examples
+     113             : //! [its repository]: https://github.com/Manishearth/compiletest-rs
+     114             : 
+     115             : use anyhow::{anyhow, ensure, Context, Result};
+     116             : use cargo_metadata::{Metadata, Package, Target};
+     117             : use compiletest_rs as compiletest;
+     118             : use dylint_internal::{env, library_filename, rustup::is_rustc, CommandExt};
+     119             : use once_cell::sync::{Lazy, OnceCell};
+     120             : use regex::Regex;
+     121             : use std::{
+     122             :     env::{consts, remove_var, set_var, var_os},
+     123             :     ffi::{OsStr, OsString},
+     124             :     fs::{copy, read_dir, remove_file},
+     125             :     io::BufRead,
+     126             :     path::{Path, PathBuf},
+     127             :     sync::Mutex,
+     128             : };
+     129             : 
+     130             : pub mod ui;
+     131             : 
+     132             : static DRIVER: OnceCell<PathBuf> = OnceCell::new();
+     133             : static LINKING_FLAGS: OnceCell<Vec<String>> = OnceCell::new();
+     134             : 
+     135             : /// Test a library on all source files in a directory.
+     136             : ///
+     137             : /// - `name` is the name of a Dylint library to be tested. (Often, this is the same as the package
+     138             : ///   name.)
+     139             : /// - `src_base` is a directory containing:
+     140             : ///   - source files on which to test the library (`.rs` files), and
+     141             : ///   - the output those files should produce (`.stderr` files).
+     142           0 : pub fn ui_test(name: &str, src_base: &Path) {
+     143           0 :     ui::Test::src_base(name, src_base).run();
+     144           0 : }
+     145             : 
+     146             : /// Test a library on one example target.
+     147             : ///
+     148             : /// - `name` is the name of a Dylint library to be tested.
+     149             : /// - `example` is an example target on which to test the library.
+     150           0 : pub fn ui_test_example(name: &str, example: &str) {
+     151           0 :     ui::Test::example(name, example).run();
+     152           0 : }
+     153             : 
+     154             : /// Test a library on all example targets.
+     155             : ///
+     156             : /// - `name` is the name of a Dylint library to be tested.
+     157           0 : pub fn ui_test_examples(name: &str) {
+     158           0 :     ui::Test::examples(name).run();
+     159           0 : }
+     160             : 
+     161           0 : fn initialize(name: &str) -> Result<&Path> {
+     162           0 :     DRIVER
+     163           0 :         .get_or_try_init(|| {
+     164           0 :             let _ = env_logger::try_init();
+     165           0 : 
+     166           0 :             // smoelius: Try to order failures by how informative they are: failure to build the
+     167           0 :             // library, failure to find the library, failure to build/find the driver.
+     168           0 : 
+     169           0 :             dylint_internal::cargo::build(&format!("library `{name}`"))
+     170           0 :                 .build()
+     171           0 :                 .success()?;
+     172             : 
+     173             :             // smoelius: `DYLINT_LIBRARY_PATH` must be set before `dylint_libs` is called.
+     174             :             // smoelius: This was true when `dylint_libs` called `name_toolchain_map`, but that is
+     175             :             // no longer the case. I am leaving the comment here for now in case removal
+     176             :             // of the `name_toolchain_map` call causes a regression.
+     177           0 :             let metadata = dylint_internal::cargo::current_metadata().unwrap();
+     178           0 :             let dylint_library_path = metadata.target_directory.join("debug");
+     179           0 :             set_var(env::DYLINT_LIBRARY_PATH, dylint_library_path);
+     180             : 
+     181           0 :             let dylint_libs = dylint_libs(name)?;
+     182           0 :             let driver = dylint::driver_builder::get(
+     183           0 :                 &dylint::opts::Dylint::default(),
+     184           0 :                 env!("RUSTUP_TOOLCHAIN"),
+     185           0 :             )?;
+     186             : 
+     187           0 :             set_var(env::CLIPPY_DISABLE_DOCS_LINKS, "true");
+     188           0 :             set_var(env::DYLINT_LIBS, dylint_libs);
+     189           0 : 
+     190           0 :             Ok(driver)
+     191           0 :         })
+     192           0 :         .map(PathBuf::as_path)
+     193           0 : }
+     194             : 
+     195             : #[doc(hidden)]
+     196           0 : pub fn dylint_libs(name: &str) -> Result<String> {
+     197           0 :     let metadata = dylint_internal::cargo::current_metadata().unwrap();
+     198           0 :     let rustup_toolchain = env::var(env::RUSTUP_TOOLCHAIN)?;
+     199           0 :     let filename = library_filename(name, &rustup_toolchain);
+     200           0 :     let path = metadata.target_directory.join("debug").join(filename);
+     201           0 :     let paths = vec![path];
+     202           0 :     serde_json::to_string(&paths).map_err(Into::into)
+     203           0 : }
+     204             : 
+     205           0 : fn example_target(package: &Package, example: &str) -> Result<Target> {
+     206           0 :     package
+     207           0 :         .targets
+     208           0 :         .iter()
+     209           0 :         .find(|target| target.kind == ["example"] && target.name == example)
+     210           0 :         .cloned()
+     211           0 :         .ok_or_else(|| anyhow!("Could not find example `{}`", example))
+     212           0 : }
+     213             : 
+     214             : #[allow(clippy::unnecessary_wraps)]
+     215           0 : fn example_targets(package: &Package) -> Result<Vec<Target>> {
+     216           0 :     Ok(package
+     217           0 :         .targets
+     218           0 :         .iter()
+     219           0 :         .filter(|target| target.kind == ["example"])
+     220           0 :         .cloned()
+     221           0 :         .collect())
+     222           0 : }
+     223             : 
+     224           0 : fn run_example_test(
+     225           0 :     driver: &Path,
+     226           0 :     metadata: &Metadata,
+     227           0 :     package: &Package,
+     228           0 :     target: &Target,
+     229           0 :     config: &ui::Config,
+     230           0 : ) -> Result<()> {
+     231           0 :     let linking_flags = linking_flags(metadata, package, target)?;
+     232           0 :     let file_name = target
+     233           0 :         .src_path
+     234           0 :         .file_name()
+     235           0 :         .ok_or_else(|| anyhow!("Could not get file name"))?;
+     236             : 
+     237           0 :     let tempdir = tempfile::tempdir().with_context(|| "`tempdir` failed")?;
+     238           0 :     let src_base = tempdir.path();
+     239           0 :     let to = src_base.join(file_name);
+     240           0 : 
+     241           0 :     copy(&target.src_path, &to).with_context(|| {
+     242           0 :         format!(
+     243           0 :             "Could not copy `{}` to `{}`",
+     244           0 :             target.src_path,
+     245           0 :             to.to_string_lossy()
+     246           0 :         )
+     247           0 :     })?;
+     248           0 :     ["fixed", "stderr", "stdout"]
+     249           0 :         .map(|extension| copy_with_extension(&target.src_path, &to, extension).unwrap_or_default());
+     250           0 : 
+     251           0 :     let mut config = config.clone();
+     252           0 :     config.rustc_flags.extend(linking_flags.iter().cloned());
+     253           0 : 
+     254           0 :     run_tests(driver, src_base, &config);
+     255           0 : 
+     256           0 :     Ok(())
+     257           0 : }
+     258             : 
+     259           0 : fn linking_flags(
+     260           0 :     metadata: &Metadata,
+     261           0 :     package: &Package,
+     262           0 :     target: &Target,
+     263           0 : ) -> Result<&'static [String]> {
+     264           0 :     LINKING_FLAGS
+     265           0 :         .get_or_try_init(|| {
+     266           0 :             let rustc_flags = rustc_flags(metadata, package, target)?;
+     267             : 
+     268           0 :             let mut linking_flags = Vec::new();
+     269           0 : 
+     270           0 :             let mut iter = rustc_flags.into_iter();
+     271           0 :             while let Some(flag) = iter.next() {
+     272           0 :                 if flag.starts_with("--edition=") {
+     273           0 :                     linking_flags.push(flag);
+     274           0 :                 } else if flag == "--extern" || flag == "-L" {
+     275           0 :                     let arg = next(&flag, &mut iter)?;
+     276           0 :                     linking_flags.extend([flag, arg.trim_matches('\'').to_owned()]);
+     277           0 :                 }
+     278             :             }
+     279             : 
+     280           0 :             Ok(linking_flags)
+     281           0 :         })
+     282           0 :         .map(Vec::as_slice)
+     283           0 : }
+     284             : 
+     285             : // smoelius: We need to recover the `rustc` flags used to build a target. I can see four options:
+     286             : //
+     287             : // * Use `cargo build --build-plan`
+     288             : //   - Pros: Easily parsable JSON output
+     289             : //   - Cons: Unstable and likely to be removed: https://github.com/rust-lang/cargo/issues/7614
+     290             : // * Parse the output of `cargo build --verbose`
+     291             : //   - Pros: ?
+     292             : //   - Cons: Not as easily parsable, requires synchronization (see below)
+     293             : // * Use a custom executor like Siderophile does: https://github.com/trailofbits/siderophile/blob/26c067306f6c2f66d9530dacef6b17dbf59cdf8c/src/trawl_source/mod.rs#L399
+     294             : //   - Pros: Ground truth
+     295             : //   - Cons: Seems a bit of a heavy lift (Note: I think Siderophile's approach was inspired by
+     296             : //     `cargo-geiger`.)
+     297             : // * Set `RUSTC_WORKSPACE_WRAPPER` to something that logs `rustc` invocations
+     298             : //   - Pros: Ground truth
+     299             : //   - Cons: Requires a separate executable/script, portability could be an issue
+     300             : //
+     301             : // I am going with the second option for now, because it seems to be the least of all evils. This
+     302             : // decision may need to be revisited.
+     303             : 
+     304           0 : static RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"^\s*Running\s*`(.*)`$").unwrap());
+     305             : 
+     306           0 : fn rustc_flags(metadata: &Metadata, package: &Package, target: &Target) -> Result<Vec<String>> {
+     307             :     // smoelius: The following comments are old and retained for posterity. The linking flags are
+     308             :     // now initialized using a `OnceCell`, which makes the mutex unnecessary.
+     309             :     //   smoelius: Force rebuilding of the example by removing it. This is kind of messy. The
+     310             :     //   example is a shared resource that may be needed by multiple tests. For now, I lock a mutex
+     311             :     //   while the example is removed and put back.
+     312             :     //   smoelius: Should we use a temporary target directory here?
+     313           0 :     let output = {
+     314           0 :         remove_example(metadata, package, target)?;
+     315             : 
+     316             :         // smoelius: Because of lazy initialization, `cargo build` is run only once. Seeing
+     317             :         // "Building example `target`" for one example but not for others is confusing. So instead
+     318             :         // say "Building `package` examples".
+     319           0 :         dylint_internal::cargo::build(&format!("`{}` examples", package.name))
+     320           0 :             .build()
+     321           0 :             .envs([(env::CARGO_TERM_COLOR, "never")])
+     322           0 :             .args([
+     323           0 :                 "--manifest-path",
+     324           0 :                 package.manifest_path.as_ref(),
+     325           0 :                 "--example",
+     326           0 :                 &target.name,
+     327           0 :                 "--verbose",
+     328           0 :             ])
+     329           0 :             .logged_output(true)?
+     330             :     };
+     331             : 
+     332           0 :     let matches = output
+     333           0 :         .stderr
+     334           0 :         .lines()
+     335           0 :         .map(|line| {
+     336           0 :             let line =
+     337           0 :                 line.with_context(|| format!("Could not read from `{}`", package.manifest_path))?;
+     338           0 :             Ok((*RE).captures(&line).and_then(|captures| {
+     339           0 :                 let args = captures[1]
+     340           0 :                     .split(' ')
+     341           0 :                     .map(ToOwned::to_owned)
+     342           0 :                     .collect::<Vec<_>>();
+     343           0 :                 if args.first().map_or(false, is_rustc)
+     344           0 :                     && args
+     345           0 :                         .as_slice()
+     346           0 :                         .windows(2)
+     347           0 :                         .any(|window| window == ["--crate-name", &snake_case(&target.name)])
+     348             :                 {
+     349           0 :                     Some(args)
+     350             :                 } else {
+     351           0 :                     None
+     352             :                 }
+     353           0 :             }))
+     354           0 :         })
+     355           0 :         .collect::<Result<Vec<Option<Vec<_>>>>>()?;
+     356             : 
+     357           0 :     let mut matches = matches.into_iter().flatten().collect::<Vec<Vec<_>>>();
+     358           0 :     ensure!(
+     359           0 :         matches.len() <= 1,
+     360           0 :         "Found multiple `rustc` invocations for `{}`",
+     361             :         target.name
+     362             :     );
+     363           0 :     matches
+     364           0 :         .pop()
+     365           0 :         .ok_or_else(|| anyhow!("Found no `rustc` invocations for `{}`", target.name))
+     366           0 : }
+     367             : 
+     368           0 : fn remove_example(metadata: &Metadata, _package: &Package, target: &Target) -> Result<()> {
+     369           0 :     let examples = metadata.target_directory.join("debug/examples");
+     370           0 :     for entry in
+     371           0 :         read_dir(&examples).with_context(|| format!("`read_dir` failed for `{examples}`"))?
+     372             :     {
+     373           0 :         let entry = entry.with_context(|| format!("`read_dir` failed for `{examples}`"))?;
+     374           0 :         let path = entry.path();
+     375             : 
+     376           0 :         if let Some(file_name) = path.file_name() {
+     377           0 :             let s = file_name.to_string_lossy();
+     378           0 :             let target_name = snake_case(&target.name);
+     379           0 :             if s == target_name.clone() + consts::EXE_SUFFIX
+     380           0 :                 || s.starts_with(&(target_name.clone() + "-"))
+     381             :             {
+     382           0 :                 remove_file(&path).with_context(|| {
+     383           0 :                     format!("`remove_file` failed for `{}`", path.to_string_lossy())
+     384           0 :                 })?;
+     385           0 :             }
+     386           0 :         }
+     387             :     }
+     388             : 
+     389           0 :     Ok(())
+     390           0 : }
+     391             : 
+     392           0 : fn next<I, T>(flag: &str, iter: &mut I) -> Result<T>
+     393           0 : where
+     394           0 :     I: Iterator<Item = T>,
+     395           0 : {
+     396           0 :     iter.next()
+     397           0 :         .ok_or_else(|| anyhow!("Missing argument for `{}`", flag))
+     398           0 : }
+     399             : 
+     400           0 : fn copy_with_extension<P: AsRef<Path>, Q: AsRef<Path>>(
+     401           0 :     from: P,
+     402           0 :     to: Q,
+     403           0 :     extension: &str,
+     404           0 : ) -> Result<u64> {
+     405           0 :     let from = from.as_ref().with_extension(extension);
+     406           0 :     let to = to.as_ref().with_extension(extension);
+     407           0 :     copy(from, to).map_err(Into::into)
+     408           0 : }
+     409             : 
+     410             : static MUTEX: Mutex<()> = Mutex::new(());
+     411             : 
+     412           0 : fn run_tests(driver: &Path, src_base: &Path, config: &ui::Config) {
+     413           0 :     let _lock = MUTEX.lock().unwrap();
+     414           0 : 
+     415           0 :     // smoelius: There doesn't seem to be a way to set environment variables using `compiletest`'s
+     416           0 :     // [`Config`](https://docs.rs/compiletest_rs/0.7.1/compiletest_rs/common/struct.Config.html)
+     417           0 :     // struct. For comparison, where Clippy uses `compiletest`, it sets environment variables
+     418           0 :     // directly (see: https://github.com/rust-lang/rust-clippy/blob/master/tests/compile-test.rs).
+     419           0 :     //
+     420           0 :     // Of course, even if `compiletest` had such support, it would need to be incorporated into
+     421           0 :     // `dylint_testing`.
+     422           0 : 
+     423           0 :     let _var = config
+     424           0 :         .dylint_toml
+     425           0 :         .as_ref()
+     426           0 :         .map(|value| VarGuard::set(env::DYLINT_TOML, value));
+     427             : 
+     428           0 :     let config = compiletest::Config {
+     429           0 :         mode: compiletest::common::Mode::Ui,
+     430           0 :         rustc_path: driver.to_path_buf(),
+     431           0 :         src_base: src_base.to_path_buf(),
+     432           0 :         target_rustcflags: Some(
+     433           0 :             config.rustc_flags.clone().join(" ")
+     434           0 :                 + " --emit=metadata"
+     435           0 :                 + if cfg!(feature = "deny_warnings") {
+     436           0 :                     " -Dwarnings"
+     437             :                 } else {
+     438           0 :                     ""
+     439             :                 }
+     440           0 :                 + " -Zui-testing",
+     441           0 :         ),
+     442           0 :         ..compiletest::Config::default()
+     443           0 :     };
+     444           0 : 
+     445           0 :     compiletest::run_tests(&config);
+     446           0 : }
+     447             : 
+     448             : // smoelius: `VarGuard` was copied from:
+     449             : // https://github.com/rust-lang/rust-clippy/blob/9cc8da222b3893bc13bc13c8827e93f8ea246854/tests/compile-test.rs
+     450             : 
+     451             : /// Restores an env var on drop
+     452             : #[must_use]
+     453             : struct VarGuard {
+     454             :     key: &'static str,
+     455             :     value: Option<OsString>,
+     456             : }
+     457             : 
+     458             : impl VarGuard {
+     459           0 :     fn set(key: &'static str, val: impl AsRef<OsStr>) -> Self {
+     460           0 :         let value = var_os(key);
+     461           0 :         set_var(key, val);
+     462           0 :         Self { key, value }
+     463           0 :     }
+     464             : }
+     465             : 
+     466             : impl Drop for VarGuard {
+     467           0 :     fn drop(&mut self) {
+     468           0 :         match self.value.as_deref() {
+     469           0 :             None => remove_var(self.key),
+     470           0 :             Some(value) => set_var(self.key, value),
+     471             :         }
+     472           0 :     }
+     473             : }
+     474             : 
+     475           0 : fn snake_case(name: &str) -> String {
+     476           0 :     name.replace('-', "_")
+     477           0 : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/utils/testing/src/ui.rs.func-sort-c.html b/coverage/utils/testing/src/ui.rs.func-sort-c.html new file mode 100644 index 000000000..baf1827b7 --- /dev/null +++ b/coverage/utils/testing/src/ui.rs.func-sort-c.html @@ -0,0 +1,108 @@ + + + + + + + LCOV - unnamed - utils/testing/src/ui.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/testing/src - ui.rs (source / functions)HitTotalCoverage
Test:unnamedLines:0600.0 %
Date:2024-04-23 03:30:56Functions:090.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint_testing::ui::Test>::dylint_toml::<_>0
<dylint_testing::ui::Test>::example0
<dylint_testing::ui::Test>::examples0
<dylint_testing::ui::Test>::new0
<dylint_testing::ui::Test>::run0
<dylint_testing::ui::Test>::run_immutable0
<dylint_testing::ui::Test>::rustc_flags::<_0
<dylint_testing::ui::Test>::src_base0
dylint_testing::ui::test::rustc_flags0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/utils/testing/src/ui.rs.func.html b/coverage/utils/testing/src/ui.rs.func.html new file mode 100644 index 000000000..35c95cbc9 --- /dev/null +++ b/coverage/utils/testing/src/ui.rs.func.html @@ -0,0 +1,108 @@ + + + + + + + LCOV - unnamed - utils/testing/src/ui.rs - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/testing/src - ui.rs (source / functions)HitTotalCoverage
Test:unnamedLines:0600.0 %
Date:2024-04-23 03:30:56Functions:090.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
<dylint_testing::ui::Test>::dylint_toml::<_>0
<dylint_testing::ui::Test>::example0
<dylint_testing::ui::Test>::examples0
<dylint_testing::ui::Test>::new0
<dylint_testing::ui::Test>::run0
<dylint_testing::ui::Test>::run_immutable0
<dylint_testing::ui::Test>::rustc_flags::<_0
<dylint_testing::ui::Test>::src_base0
dylint_testing::ui::test::rustc_flags0
+
+
+ + + +
Generated by: LCOV version 1.14
+
+ + + diff --git a/coverage/utils/testing/src/ui.rs.gcov.html b/coverage/utils/testing/src/ui.rs.gcov.html new file mode 100644 index 000000000..b5862aeeb --- /dev/null +++ b/coverage/utils/testing/src/ui.rs.gcov.html @@ -0,0 +1,197 @@ + + + + + + + LCOV - unnamed - utils/testing/src/ui.rs + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - utils/testing/src - ui.rs (source / functions)HitTotalCoverage
Test:unnamedLines:0600.0 %
Date:2024-04-23 03:30:56Functions:090.0 %
+
+ + + + + + + + +

+
          Line data    Source code
+
+       1             : use crate::{example_target, example_targets, initialize, run_example_test, run_tests};
+       2             : use std::{
+       3             :     env::current_dir,
+       4             :     path::{Path, PathBuf},
+       5             : };
+       6             : 
+       7             : enum Target {
+       8             :     SrcBase(PathBuf),
+       9             :     Example(String),
+      10             :     Examples,
+      11             : }
+      12             : 
+      13             : #[derive(Clone, Default)]
+      14             : pub(super) struct Config {
+      15             :     pub(super) rustc_flags: Vec<String>,
+      16             :     pub(super) dylint_toml: Option<String>,
+      17             : }
+      18             : 
+      19             : /// Test builder
+      20             : pub struct Test {
+      21             :     name: String,
+      22             :     target: Target,
+      23             :     config: Config,
+      24             : }
+      25             : 
+      26             : impl Test {
+      27             :     /// Test a library on all source files in a directory (similar to [`ui_test`]).
+      28             :     ///
+      29             :     /// [`ui_test`]: crate::ui_test
+      30             :     #[must_use]
+      31           0 :     pub fn src_base(name: &str, src_base: &Path) -> Self {
+      32           0 :         Self::new(name, Target::SrcBase(src_base.to_owned()))
+      33           0 :     }
+      34             : 
+      35             :     /// Test a library on one example target (similar to [`ui_test_example`]).
+      36             :     ///
+      37             :     /// [`ui_test_example`]: crate::ui_test_example
+      38             :     #[must_use]
+      39           0 :     pub fn example(name: &str, example: &str) -> Self {
+      40           0 :         Self::new(name, Target::Example(example.to_owned()))
+      41           0 :     }
+      42             : 
+      43             :     /// Test a library on all example targets (similar to [`ui_test_examples`]).
+      44             :     ///
+      45             :     /// [`ui_test_examples`]: crate::ui_test_examples
+      46             :     #[must_use]
+      47           0 :     pub fn examples(name: &str) -> Self {
+      48           0 :         Self::new(name, Target::Examples)
+      49           0 :     }
+      50             : 
+      51             :     /// Pass flags to the compiler when running the test.
+      52           0 :     pub fn rustc_flags(
+      53           0 :         &mut self,
+      54           0 :         rustc_flags: impl IntoIterator<Item = impl AsRef<str>>,
+      55           0 :     ) -> &mut Self {
+      56           0 :         self.config
+      57           0 :             .rustc_flags
+      58           0 :             .extend(rustc_flags.into_iter().map(|s| s.as_ref().to_owned()));
+      59           0 :         self
+      60           0 :     }
+      61             : 
+      62             :     /// Set the `dylint.toml` file's contents (for testing configurable libraries).
+      63           0 :     pub fn dylint_toml(&mut self, dylint_toml: impl AsRef<str>) -> &mut Self {
+      64           0 :         self.config.dylint_toml = Some(dylint_toml.as_ref().to_owned());
+      65           0 :         self
+      66           0 :     }
+      67             : 
+      68             :     /// Run the test.
+      69           0 :     pub fn run(&mut self) {
+      70           0 :         self.run_immutable();
+      71           0 :     }
+      72             : 
+      73           0 :     fn new(name: &str, target: Target) -> Self {
+      74           0 :         Self {
+      75           0 :             name: name.to_owned(),
+      76           0 :             target,
+      77           0 :             config: Config::default(),
+      78           0 :         }
+      79           0 :     }
+      80             : 
+      81           0 :     fn run_immutable(&self) {
+      82           0 :         let driver = initialize(&self.name).unwrap();
+      83           0 : 
+      84           0 :         match &self.target {
+      85           0 :             Target::SrcBase(src_base) => {
+      86           0 :                 run_tests(driver, src_base, &self.config);
+      87           0 :             }
+      88           0 :             Target::Example(example) => {
+      89           0 :                 let metadata = dylint_internal::cargo::current_metadata().unwrap();
+      90           0 :                 let current_dir = current_dir().unwrap();
+      91           0 :                 let package =
+      92           0 :                     dylint_internal::cargo::package_with_root(&metadata, &current_dir).unwrap();
+      93           0 :                 let target = example_target(&package, example).unwrap();
+      94           0 : 
+      95           0 :                 run_example_test(driver, &metadata, &package, &target, &self.config).unwrap();
+      96           0 :             }
+      97             :             Target::Examples => {
+      98           0 :                 let metadata = dylint_internal::cargo::current_metadata().unwrap();
+      99           0 :                 let current_dir = current_dir().unwrap();
+     100           0 :                 let package =
+     101           0 :                     dylint_internal::cargo::package_with_root(&metadata, &current_dir).unwrap();
+     102           0 :                 let targets = example_targets(&package).unwrap();
+     103             : 
+     104           0 :                 for target in targets {
+     105           0 :                     run_example_test(driver, &metadata, &package, &target, &self.config).unwrap();
+     106           0 :                 }
+     107             :             }
+     108             :         }
+     109           0 :     }
+     110             : }
+     111             : 
+     112             : #[cfg(test)]
+     113             : mod test {
+     114             :     use super::*;
+     115             : 
+     116             :     // smoelius: Verify that `rustc_flags` compiles when used as intended.
+     117             :     #[allow(dead_code)]
+     118           0 :     fn rustc_flags() {
+     119           0 :         let _ = Test::src_base("name", &PathBuf::new()).rustc_flags(["--test"]);
+     120           0 :     }
+     121             : }
+
+
+
+ + + + +
Generated by: LCOV version 1.14
+
+ + +