Skip to content

Commit 2d40a47

Browse files
committed
feat: Add unstable im_a_teapot lint
1 parent 00a64e4 commit 2d40a47

File tree

3 files changed

+113
-47
lines changed

3 files changed

+113
-47
lines changed

src/cargo/core/workspace.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::sources::{PathSource, CRATES_IO_INDEX, CRATES_IO_REGISTRY};
2424
use crate::util::edit_distance;
2525
use crate::util::errors::{CargoResult, ManifestError};
2626
use crate::util::interning::InternedString;
27-
use crate::util::lints::{check_implicit_features, unused_dependencies};
27+
use crate::util::lints::{check_im_a_teapot, check_implicit_features, unused_dependencies};
2828
use crate::util::toml::{read_manifest, InheritableFields};
2929
use crate::util::{
3030
context::CargoResolverConfig, context::CargoResolverPrecedence, context::ConfigRelativePath,
@@ -1206,6 +1206,7 @@ impl<'gctx> Workspace<'gctx> {
12061206
.map(|(name, lint)| (name.replace('-', "_"), lint))
12071207
.collect();
12081208

1209+
check_im_a_teapot(pkg, &path, &normalized_lints, &mut error_count, self.gctx)?;
12091210
check_implicit_features(pkg, &path, &normalized_lints, &mut error_count, self.gctx)?;
12101211
unused_dependencies(pkg, &path, &normalized_lints, &mut error_count, self.gctx)?;
12111212
if error_count > 0 {

src/cargo/util/lints.rs

+55
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,61 @@ impl From<TomlLintLevel> for LintLevel {
142142
}
143143
}
144144

145+
const IM_A_TEAPOT: Lint = Lint {
146+
name: "im_a_teapot",
147+
desc: "`im_a_teapot` is specified",
148+
groups: &[],
149+
default_level: LintLevel::Allow,
150+
edition_lint_opts: None,
151+
};
152+
153+
pub fn check_im_a_teapot(
154+
pkg: &Package,
155+
path: &Path,
156+
lints: &TomlToolLints,
157+
error_count: &mut usize,
158+
gctx: &GlobalContext,
159+
) -> CargoResult<()> {
160+
let manifest = pkg.manifest();
161+
let lint_level = IM_A_TEAPOT.level(lints, manifest.edition());
162+
if lint_level == LintLevel::Allow {
163+
return Ok(());
164+
}
165+
166+
if manifest
167+
.resolved_toml()
168+
.package()
169+
.is_some_and(|p| p.im_a_teapot.is_some())
170+
{
171+
if lint_level == LintLevel::Forbid || lint_level == LintLevel::Deny {
172+
*error_count += 1;
173+
}
174+
let level = lint_level.to_diagnostic_level();
175+
let manifest_path = rel_cwd_manifest_path(path, gctx);
176+
let emitted_reason = format!("`cargo::{}` is set to `{lint_level}`", IM_A_TEAPOT.name);
177+
178+
let key_span = get_span(manifest.document(), &["package", "im-a-teapot"], false).unwrap();
179+
let value_span = get_span(manifest.document(), &["package", "im-a-teapot"], true).unwrap();
180+
let message = level
181+
.title(IM_A_TEAPOT.desc)
182+
.snippet(
183+
Snippet::source(manifest.contents())
184+
.origin(&manifest_path)
185+
.annotation(level.span(key_span.start..value_span.end))
186+
.fold(true),
187+
)
188+
.footer(Level::Note.title(&emitted_reason));
189+
let renderer = Renderer::styled().term_width(
190+
gctx.shell()
191+
.err_width()
192+
.diagnostic_terminal_width()
193+
.unwrap_or(annotate_snippets::renderer::DEFAULT_TERM_WIDTH),
194+
);
195+
writeln!(gctx.shell().err(), "{}", renderer.render(message))?;
196+
}
197+
Ok(())
198+
}
199+
145200
/// By default, cargo will treat any optional dependency as a [feature]. As of
146201
/// cargo 1.60, these can be disabled by declaring a feature that activates the
147202
/// optional dependency as `dep:<name>` (see [RFC #3143]).

tests/testsuite/lints_table.rs

+56-46
Original file line numberDiff line numberDiff line change
@@ -756,14 +756,14 @@ fn cargo_lints_nightly_required() {
756756
.file(
757757
"Cargo.toml",
758758
r#"
759-
[package]
760-
name = "foo"
761-
version = "0.0.1"
762-
edition = "2015"
763-
authors = []
764-
765-
[lints.cargo]
766-
"unused-features" = "deny"
759+
[package]
760+
name = "foo"
761+
version = "0.0.1"
762+
edition = "2015"
763+
authors = []
764+
765+
[lints.cargo]
766+
im-a-teapot = "warn"
767767
"#,
768768
)
769769
.file("src/lib.rs", "")
@@ -790,21 +790,24 @@ fn cargo_lints_no_z_flag() {
790790
.file(
791791
"Cargo.toml",
792792
r#"
793-
[package]
794-
name = "foo"
795-
version = "0.0.1"
796-
edition = "2015"
797-
authors = []
793+
cargo-features = ["test-dummy-unstable"]
794+
795+
[package]
796+
name = "foo"
797+
version = "0.0.1"
798+
edition = "2015"
799+
authors = []
800+
im-a-teapot = true
798801
799-
[lints.cargo]
800-
"unused-features" = "deny"
802+
[lints.cargo]
803+
im-a-teapot = "warn"
801804
"#,
802805
)
803806
.file("src/lib.rs", "")
804807
.build();
805808

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

820823
#[cargo_test]
821824
fn cargo_lints_success() {
822-
let foo = project()
825+
let p = project()
823826
.file(
824827
"Cargo.toml",
825828
r#"
826-
[package]
827-
name = "foo"
828-
version = "0.0.1"
829-
edition = "2015"
830-
authors = []
829+
cargo-features = ["test-dummy-unstable"]
830+
831+
[package]
832+
name = "foo"
833+
version = "0.0.1"
834+
edition = "2015"
835+
authors = []
836+
im-a-teapot = true
831837
832-
[lints.cargo]
833-
"unused-features" = "deny"
838+
[lints.cargo]
839+
im-a-teapot = "warn"
834840
"#,
835841
)
836842
.file("src/lib.rs", "")
837843
.build();
838844

839-
foo.cargo("check -Zcargo-lints")
840-
.masquerade_as_nightly_cargo(&["-Zcargo-lints"])
845+
p.cargo("check -Zcargo-lints")
846+
.masquerade_as_nightly_cargo(&["cargo-lints", "test-dummy-unstable"])
841847
.with_stderr(
842848
"\
849+
warning: `im_a_teapot` is specified
850+
--> Cargo.toml:9:1
851+
|
852+
9 | im-a-teapot = true
853+
| ------------------
854+
|
855+
= note: `cargo::im_a_teapot` is set to `warn`
843856
[CHECKING] foo v0.0.1 ([CWD])
844857
[FINISHED] [..]
845858
",
@@ -849,40 +862,37 @@ fn cargo_lints_success() {
849862

850863
#[cargo_test]
851864
fn cargo_lints_underscore_supported() {
852-
Package::new("bar", "0.1.0").publish();
853865
let foo = project()
854866
.file(
855867
"Cargo.toml",
856868
r#"
857-
[package]
858-
name = "foo"
859-
version = "0.0.1"
860-
edition = "2021"
861-
authors = []
869+
cargo-features = ["test-dummy-unstable"]
862870
863-
[lints.cargo]
864-
"implicit_features" = "warn"
871+
[package]
872+
name = "foo"
873+
version = "0.0.1"
874+
edition = "2015"
875+
authors = []
876+
im-a-teapot = true
865877
866-
[dependencies]
867-
bar = { version = "0.1.0", optional = true }
878+
[lints.cargo]
879+
im_a_teapot = "warn"
868880
"#,
869881
)
870882
.file("src/lib.rs", "")
871883
.build();
872884

873885
foo.cargo("check -Zcargo-lints")
874-
.masquerade_as_nightly_cargo(&["-Zcargo-lints"])
886+
.masquerade_as_nightly_cargo(&["cargo-lints", "test-dummy-unstable"])
875887
.with_stderr(
876888
"\
877-
warning: implicit features for optional dependencies is deprecated and will be unavailable in the 2024 edition
878-
--> Cargo.toml:12:17
879-
|
880-
12 | bar = { version = \"0.1.0\", optional = true }
881-
| ---
882-
|
883-
= note: `cargo::implicit_features` is set to `warn`
884-
[UPDATING] `dummy-registry` index
885-
[LOCKING] [..]
889+
warning: `im_a_teapot` is specified
890+
--> Cargo.toml:9:1
891+
|
892+
9 | im-a-teapot = true
893+
| ------------------
894+
|
895+
= note: `cargo::im_a_teapot` is set to `warn`
886896
[CHECKING] foo v0.0.1 ([CWD])
887897
[FINISHED] [..]
888898
",

0 commit comments

Comments
 (0)