Skip to content

Commit

Permalink
feat: Add unstable im_a_teapot lint
Browse files Browse the repository at this point in the history
  • Loading branch information
Muscraft committed Apr 21, 2024
1 parent 00a64e4 commit 2d40a47
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 47 deletions.
3 changes: 2 additions & 1 deletion src/cargo/core/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::sources::{PathSource, CRATES_IO_INDEX, CRATES_IO_REGISTRY};
use crate::util::edit_distance;
use crate::util::errors::{CargoResult, ManifestError};
use crate::util::interning::InternedString;
use crate::util::lints::{check_implicit_features, unused_dependencies};
use crate::util::lints::{check_im_a_teapot, check_implicit_features, unused_dependencies};
use crate::util::toml::{read_manifest, InheritableFields};
use crate::util::{
context::CargoResolverConfig, context::CargoResolverPrecedence, context::ConfigRelativePath,
Expand Down Expand Up @@ -1206,6 +1206,7 @@ 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)?;
if error_count > 0 {
Expand Down
55 changes: 55 additions & 0 deletions src/cargo/util/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,61 @@ impl From<TomlLintLevel> for LintLevel {
}
}

const IM_A_TEAPOT: Lint = Lint {
name: "im_a_teapot",
desc: "`im_a_teapot` is specified",
groups: &[],
default_level: LintLevel::Allow,
edition_lint_opts: None,
};

pub fn check_im_a_teapot(
pkg: &Package,
path: &Path,
lints: &TomlToolLints,
error_count: &mut usize,
gctx: &GlobalContext,
) -> CargoResult<()> {
let manifest = pkg.manifest();
let lint_level = IM_A_TEAPOT.level(lints, manifest.edition());
if lint_level == LintLevel::Allow {
return Ok(());
}

if manifest
.resolved_toml()
.package()
.is_some_and(|p| p.im_a_teapot.is_some())
{
if lint_level == LintLevel::Forbid || lint_level == LintLevel::Deny {
*error_count += 1;
}
let level = lint_level.to_diagnostic_level();
let manifest_path = rel_cwd_manifest_path(path, gctx);
let emitted_reason = format!("`cargo::{}` is set to `{lint_level}`", IM_A_TEAPOT.name);

let key_span = get_span(manifest.document(), &["package", "im-a-teapot"], false).unwrap();
let value_span = get_span(manifest.document(), &["package", "im-a-teapot"], true).unwrap();
let message = level
.title(IM_A_TEAPOT.desc)
.snippet(
Snippet::source(manifest.contents())
.origin(&manifest_path)
.annotation(level.span(key_span.start..value_span.end))
.fold(true),
)
.footer(Level::Note.title(&emitted_reason));
let renderer = Renderer::styled().term_width(
gctx.shell()
.err_width()
.diagnostic_terminal_width()
.unwrap_or(annotate_snippets::renderer::DEFAULT_TERM_WIDTH),
);
writeln!(gctx.shell().err(), "{}", renderer.render(message))?;
}
Ok(())
}

/// By default, cargo will treat any optional dependency as a [feature]. As of
/// cargo 1.60, these can be disabled by declaring a feature that activates the
/// optional dependency as `dep:<name>` (see [RFC #3143]).
Expand Down
102 changes: 56 additions & 46 deletions tests/testsuite/lints_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -756,14 +756,14 @@ fn cargo_lints_nightly_required() {
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
[lints.cargo]
"unused-features" = "deny"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
[lints.cargo]
im-a-teapot = "warn"
"#,
)
.file("src/lib.rs", "")
Expand All @@ -790,21 +790,24 @@ fn cargo_lints_no_z_flag() {
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
cargo-features = ["test-dummy-unstable"]
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
im-a-teapot = true
[lints.cargo]
"unused-features" = "deny"
[lints.cargo]
im-a-teapot = "warn"
"#,
)
.file("src/lib.rs", "")
.build();

foo.cargo("check")
.masquerade_as_nightly_cargo(&["-Zcargo-lints"])
.masquerade_as_nightly_cargo(&["cargo-lints", "test-dummy-unstable"])
.with_stderr(
"\
[WARNING] unused manifest key `lints.cargo` (may be supported in a future version)
Expand All @@ -819,27 +822,37 @@ consider passing `-Zcargo-lints` to enable this feature.

#[cargo_test]
fn cargo_lints_success() {
let foo = project()
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
cargo-features = ["test-dummy-unstable"]
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
im-a-teapot = true
[lints.cargo]
"unused-features" = "deny"
[lints.cargo]
im-a-teapot = "warn"
"#,
)
.file("src/lib.rs", "")
.build();

foo.cargo("check -Zcargo-lints")
.masquerade_as_nightly_cargo(&["-Zcargo-lints"])
p.cargo("check -Zcargo-lints")
.masquerade_as_nightly_cargo(&["cargo-lints", "test-dummy-unstable"])
.with_stderr(
"\
warning: `im_a_teapot` is specified
--> Cargo.toml:9:1
|
9 | im-a-teapot = true
| ------------------
|
= note: `cargo::im_a_teapot` is set to `warn`
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] [..]
",
Expand All @@ -849,40 +862,37 @@ fn cargo_lints_success() {

#[cargo_test]
fn cargo_lints_underscore_supported() {
Package::new("bar", "0.1.0").publish();
let foo = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2021"
authors = []
cargo-features = ["test-dummy-unstable"]
[lints.cargo]
"implicit_features" = "warn"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
im-a-teapot = true
[dependencies]
bar = { version = "0.1.0", optional = true }
[lints.cargo]
im_a_teapot = "warn"
"#,
)
.file("src/lib.rs", "")
.build();

foo.cargo("check -Zcargo-lints")
.masquerade_as_nightly_cargo(&["-Zcargo-lints"])
.masquerade_as_nightly_cargo(&["cargo-lints", "test-dummy-unstable"])
.with_stderr(
"\
warning: implicit features for optional dependencies is deprecated and will be unavailable in the 2024 edition
--> Cargo.toml:12:17
|
12 | bar = { version = \"0.1.0\", optional = true }
| ---
|
= note: `cargo::implicit_features` is set to `warn`
[UPDATING] `dummy-registry` index
[LOCKING] [..]
warning: `im_a_teapot` is specified
--> Cargo.toml:9:1
|
9 | im-a-teapot = true
| ------------------
|
= note: `cargo::im_a_teapot` is set to `warn`
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] [..]
",
Expand Down

0 comments on commit 2d40a47

Please sign in to comment.