Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ cargo-platform = { path = "crates/cargo-platform", version = "0.3.0" }
cargo-test-macro = { version = "0.4.9", path = "crates/cargo-test-macro" }
cargo-test-support = { version = "0.10.0", path = "crates/cargo-test-support" }
cargo-util = { version = "0.2.27", path = "crates/cargo-util" }
cargo-util-schemas = { version = "0.12.0", path = "crates/cargo-util-schemas" }
cargo-util-schemas = { version = "0.12.1", path = "crates/cargo-util-schemas" }
cargo_metadata = "0.23.1"
clap = "4.5.53"
clap_complete = { version = "4.5.64", features = ["unstable-dynamic"] }
Expand All @@ -54,6 +54,7 @@ git2-curl = "0.21.0"
gix = { version = "0.77.0", default-features = false, features = ["progress-tree", "parallel", "dirwalk", "status"] }
glob = "0.3.3"
handlebars = { version = "6.4.0", features = ["dir_source"] }
heck = "0.5.0"
hex = "0.4.3"
hmac = "0.12.1"
home = "0.5.12"
Expand Down Expand Up @@ -176,6 +177,7 @@ git2.workspace = true
git2-curl.workspace = true
gix.workspace = true
glob.workspace = true
heck.workspace = true
hex.workspace = true
hmac.workspace = true
home.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/cargo-util-schemas/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cargo-util-schemas"
version = "0.12.0"
version = "0.12.1"
rust-version = "1.92" # MSRV:1
edition.workspace = true
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/cargo-util-schemas/src/manifest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1796,7 +1796,7 @@ impl<'de> de::Deserialize<'de> for VecStringOrBool {
}
}

#[derive(Clone)]
#[derive(Clone, PartialEq, Eq)]
pub struct PathValue(pub PathBuf);

impl fmt::Debug for PathValue {
Expand Down
9 changes: 9 additions & 0 deletions src/cargo/core/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use crate::lints::analyze_cargo_lints_table;
use crate::lints::rules::blanket_hint_mostly_unused;
use crate::lints::rules::check_im_a_teapot;
use crate::lints::rules::implicit_minimum_version_req;
use crate::lints::rules::non_kebab_case_bin;
use crate::ops;
use crate::ops::lockfile::LOCKFILE_NAME;
use crate::sources::{CRATES_IO_INDEX, CRATES_IO_REGISTRY, PathSource, SourceConfigMap};
Expand Down Expand Up @@ -1354,6 +1355,14 @@ impl<'gctx> Workspace<'gctx> {
&mut run_error_count,
self.gctx,
)?;
non_kebab_case_bin(
self,
pkg.into(),
&path,
&cargo_lints,
&mut run_error_count,
self.gctx,
)?;

if run_error_count > 0 {
let plural = if run_error_count == 1 { "" } else { "s" };
Expand Down
91 changes: 68 additions & 23 deletions src/cargo/lints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,40 +218,85 @@ pub struct TomlSpan {
pub value: Range<usize>,
}

pub fn get_key_value<'doc>(
#[derive(Copy, Clone)]
pub enum TomlIndex<'i> {
Key(&'i str),
Offset(usize),
}

impl<'i> TomlIndex<'i> {
fn as_key(&self) -> Option<&'i str> {
match self {
TomlIndex::Key(key) => Some(key),
TomlIndex::Offset(_) => None,
}
}
}

pub trait AsIndex {
fn as_index<'i>(&'i self) -> TomlIndex<'i>;
}

impl AsIndex for TomlIndex<'_> {
fn as_index<'i>(&'i self) -> TomlIndex<'i> {
match self {
TomlIndex::Key(key) => TomlIndex::Key(key),
TomlIndex::Offset(offset) => TomlIndex::Offset(*offset),
}
}
}

impl AsIndex for &str {
fn as_index<'i>(&'i self) -> TomlIndex<'i> {
TomlIndex::Key(self)
}
}

impl AsIndex for usize {
fn as_index<'i>(&'i self) -> TomlIndex<'i> {
TomlIndex::Offset(*self)
}
}

pub fn get_key_value<'doc, 'i>(
document: &'doc toml::Spanned<toml::de::DeTable<'static>>,
path: &[&str],
path: &[impl AsIndex],
) -> Option<(
&'doc toml::Spanned<Cow<'doc, str>>,
&'doc toml::Spanned<toml::de::DeValue<'static>>,
)> {
let mut table = document.get_ref();
let mut iter = path.into_iter().peekable();
while let Some(key) = iter.next() {
let key_s: &str = key.as_ref();
let (key, item) = table.get_key_value(key_s)?;
if iter.peek().is_none() {
return Some((key, item));
}
if let Some(next_table) = item.get_ref().as_table() {
table = next_table;
}
if iter.peek().is_some() {
if let Some(array) = item.get_ref().as_array() {
let next = iter.next().unwrap();
return array.iter().find_map(|item| match item.get_ref() {
toml::de::DeValue::String(s) if s == next => Some((key, item)),
_ => None,
});
let table = document.get_ref();
let mut iter = path.into_iter();
let index0 = iter.next()?.as_index();
let key0 = index0.as_key()?;
let (mut current_key, mut current_item) = table.get_key_value(key0)?;

while let Some(index) = iter.next() {
match index.as_index() {
TomlIndex::Key(key) => {
if let Some(table) = current_item.get_ref().as_table() {
(current_key, current_item) = table.get_key_value(key)?;
} else if let Some(array) = current_item.get_ref().as_array() {
current_item = array.iter().find(|item| match item.get_ref() {
toml::de::DeValue::String(s) => s == key,
_ => false,
})?;
} else {
return None;
}
}
TomlIndex::Offset(offset) => {
let array = current_item.get_ref().as_array()?;
current_item = array.get(offset)?;
}
}
}
None
Some((current_key, current_item))
}

pub fn get_key_value_span(
pub fn get_key_value_span<'i>(
document: &toml::Spanned<toml::de::DeTable<'static>>,
path: &[&str],
path: &[impl AsIndex],
) -> Option<TomlSpan> {
get_key_value(document, path).map(|(k, v)| TomlSpan {
key: k.span(),
Expand Down
3 changes: 3 additions & 0 deletions src/cargo/lints/rules/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
mod blanket_hint_mostly_unused;
mod im_a_teapot;
mod implicit_minimum_version_req;
mod non_kebab_case_bin;
mod unknown_lints;

pub use blanket_hint_mostly_unused::blanket_hint_mostly_unused;
pub use im_a_teapot::check_im_a_teapot;
pub use implicit_minimum_version_req::implicit_minimum_version_req;
pub use non_kebab_case_bin::non_kebab_case_bin;
pub use unknown_lints::output_unknown_lints;

pub const LINTS: &[crate::lints::Lint] = &[
blanket_hint_mostly_unused::LINT,
implicit_minimum_version_req::LINT,
im_a_teapot::LINT,
non_kebab_case_bin::LINT,
unknown_lints::LINT,
];
Loading