Skip to content

Commit

Permalink
refactor(lints): Keep workspace and package lints separate
Browse files Browse the repository at this point in the history
  • Loading branch information
Muscraft committed Apr 24, 2024
1 parent 3c9df90 commit 426d526
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 36 deletions.
42 changes: 39 additions & 3 deletions src/cargo/core/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,21 @@ impl<'gctx> Workspace<'gctx> {
}

pub fn emit_lints(&self, pkg: &Package, path: &Path) -> CargoResult<()> {
let ws_lints = self
.root_maybe()
.workspace_config()
.inheritable()
.and_then(|i| i.lints().ok())
.unwrap_or_default();

let ws_cargo_lints = ws_lints
.get("cargo")
.cloned()
.unwrap_or_default()
.into_iter()
.map(|(k, v)| (k.replace('-', "_"), v))
.collect();

let mut error_count = 0;
let toml_lints = pkg
.manifest()
Expand All @@ -1197,9 +1212,30 @@ impl<'gctx> Workspace<'gctx> {
.map(|(name, lint)| (name.replace('-', "_"), lint))
.collect();

check_im_a_teapot(pkg, &path, &normalized_lints, &mut error_count, self.gctx)?;
check_implicit_features(pkg, &path, &normalized_lints, &mut error_count, self.gctx)?;
unused_dependencies(pkg, &path, &normalized_lints, &mut error_count, self.gctx)?;
check_im_a_teapot(
pkg,
&path,
&normalized_lints,
&ws_cargo_lints,
&mut error_count,
self.gctx,
)?;
check_implicit_features(
pkg,
&path,
&normalized_lints,
&ws_cargo_lints,
&mut error_count,
self.gctx,
)?;
unused_dependencies(
pkg,
&path,
&normalized_lints,
&ws_cargo_lints,
&mut error_count,
self.gctx,
)?;
if error_count > 0 {
Err(crate::util::errors::AlreadyPrintedError::new(anyhow!(
"encountered {error_count} errors(s) while running lints"
Expand Down
37 changes: 26 additions & 11 deletions src/cargo/util/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,12 @@ pub trait LevelTrait {
fn default_level(&self) -> LintLevel;
fn edition_lint_opts(&self) -> Option<(Edition, LintLevel)>;
fn name(&self) -> &str;
fn level_priority(&self, lints: &TomlToolLints, edition: Edition) -> (LintLevel, i8) {
fn level_priority(
&self,
pkg_lints: &TomlToolLints,
ws_lints: &TomlToolLints,
edition: Edition,
) -> (LintLevel, i8) {
let unspecified_level = if let Some(level) = self
.edition_lint_opts()
.filter(|(e, _)| edition >= *e)
Expand All @@ -80,7 +85,9 @@ pub trait LevelTrait {
return (unspecified_level, 0);
}

if let Some(defined_level) = lints.get(self.name()) {
if let Some(defined_level) = pkg_lints.get(self.name()) {
(defined_level.level().into(), defined_level.priority())
} else if let Some(defined_level) = ws_lints.get(self.name()) {
(defined_level.level().into(), defined_level.priority())
} else {
(unspecified_level, 0)
Expand Down Expand Up @@ -141,13 +148,18 @@ impl LevelTrait for Lint {
}

impl Lint {
pub fn level(&self, lints: &TomlToolLints, edition: Edition) -> LintLevel {
pub fn level(
&self,
lints: &TomlToolLints,
ws_lints: &TomlToolLints,
edition: Edition,
) -> LintLevel {
self.groups
.iter()
.map(|g| (g.name, g.level_priority(lints, edition)))
.map(|g| (g.name, g.level_priority(lints, ws_lints, edition)))
.chain(std::iter::once((
self.name,
self.level_priority(lints, edition),
self.level_priority(lints, ws_lints, edition),
)))
.max_by_key(|(n, (l, p))| (l == &LintLevel::Forbid, *p, std::cmp::Reverse(*n)))
.map(|(_, (l, _))| l)
Expand Down Expand Up @@ -207,12 +219,13 @@ const IM_A_TEAPOT: Lint = Lint {
pub fn check_im_a_teapot(
pkg: &Package,
path: &Path,
lints: &TomlToolLints,
pkg_lints: &TomlToolLints,
ws_lints: &TomlToolLints,
error_count: &mut usize,
gctx: &GlobalContext,
) -> CargoResult<()> {
let manifest = pkg.manifest();
let lint_level = IM_A_TEAPOT.level(lints, manifest.edition());
let lint_level = IM_A_TEAPOT.level(pkg_lints, ws_lints, manifest.edition());
if lint_level == LintLevel::Allow {
return Ok(());
}
Expand Down Expand Up @@ -275,7 +288,8 @@ const IMPLICIT_FEATURES: Lint = Lint {
pub fn check_implicit_features(
pkg: &Package,
path: &Path,
lints: &TomlToolLints,
pkg_lints: &TomlToolLints,
ws_lints: &TomlToolLints,
error_count: &mut usize,
gctx: &GlobalContext,
) -> CargoResult<()> {
Expand All @@ -286,7 +300,7 @@ pub fn check_implicit_features(
return Ok(());
}

let lint_level = IMPLICIT_FEATURES.level(lints, edition);
let lint_level = IMPLICIT_FEATURES.level(pkg_lints, ws_lints, edition);
if lint_level == LintLevel::Allow {
return Ok(());
}
Expand Down Expand Up @@ -358,7 +372,8 @@ const UNUSED_OPTIONAL_DEPENDENCY: Lint = Lint {
pub fn unused_dependencies(
pkg: &Package,
path: &Path,
lints: &TomlToolLints,
pkg_lints: &TomlToolLints,
ws_lints: &TomlToolLints,
error_count: &mut usize,
gctx: &GlobalContext,
) -> CargoResult<()> {
Expand All @@ -368,7 +383,7 @@ pub fn unused_dependencies(
return Ok(());
}

let lint_level = UNUSED_OPTIONAL_DEPENDENCY.level(lints, edition);
let lint_level = UNUSED_OPTIONAL_DEPENDENCY.level(pkg_lints, ws_lints, edition);
if lint_level == LintLevel::Allow {
return Ok(());
}
Expand Down
36 changes: 14 additions & 22 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,15 +411,7 @@ fn resolve_toml(
}
resolved_toml.target = (!resolved_target.is_empty()).then_some(resolved_target);

let resolved_lints = original_toml
.lints
.clone()
.map(|value| lints_inherit_with(value, || inherit()?.lints()))
.transpose()?;
resolved_toml.lints = resolved_lints.map(|lints| manifest::InheritableLints {
workspace: false,
lints,
});
resolved_toml.lints = original_toml.lints.clone();

let resolved_badges = original_toml
.badges
Expand Down Expand Up @@ -803,7 +795,7 @@ impl InheritableFields {
}

/// Gets the field `workspace.lint`.
fn lints(&self) -> CargoResult<manifest::TomlLints> {
pub fn lints(&self) -> CargoResult<manifest::TomlLints> {
let Some(val) = &self.lints else {
bail!("`workspace.lints` was not defined");
};
Expand Down Expand Up @@ -1284,18 +1276,18 @@ fn to_real_manifest(
}
}

verify_lints(
resolved_toml.resolved_lints().expect("previously resolved"),
gctx,
warnings,
)?;
let default = manifest::TomlLints::default();
let rustflags = lints_to_rustflags(
resolved_toml
.resolved_lints()
.expect("previously resolved")
.unwrap_or(&default),
);
let resolved_lints = original_toml
.lints
.clone()
.map(|value| {
lints_inherit_with(value, || {
load_inheritable_fields(gctx, manifest_file, &workspace_config)?.lints()
})
})
.transpose()?;

verify_lints(resolved_lints.as_ref(), gctx, warnings)?;
let rustflags = lints_to_rustflags(&resolved_lints.unwrap_or_default());

let metadata = ManifestMetadata {
description: resolved_package
Expand Down

0 comments on commit 426d526

Please sign in to comment.