Skip to main content

cargo/diagnostics/rules/
im_a_teapot.rs

1use std::path::Path;
2
3use cargo_util_terminal::report::AnnotationKind;
4use cargo_util_terminal::report::Group;
5use cargo_util_terminal::report::Level;
6use cargo_util_terminal::report::Origin;
7use cargo_util_terminal::report::Snippet;
8use tracing::instrument;
9
10use super::TEST_DUMMY_UNSTABLE;
11use crate::CargoResult;
12use crate::GlobalContext;
13use crate::diagnostics::Lint;
14use crate::diagnostics::LintLevelProduct;
15use crate::diagnostics::ScopedDiagnosticStats;
16use crate::diagnostics::get_key_value_span;
17use crate::diagnostics::workspace_rel_path;
18use crate::workspace::Feature;
19use crate::workspace::Package;
20use crate::workspace::Workspace;
21
22/// This lint is only to be used for testing purposes
23pub static LINT: &Lint = &Lint {
24    name: "im_a_teapot",
25    primary_group: &TEST_DUMMY_UNSTABLE,
26    msrv: None,
27    feature_gate: Some(Feature::test_dummy_unstable()),
28    docs: None,
29};
30
31#[instrument(skip_all)]
32pub(crate) fn lint_package(
33    ws: &Workspace<'_>,
34    pkg: &Package,
35    path: &Path,
36    level: LintLevelProduct,
37    pkg_stats: &mut ScopedDiagnosticStats<'_>,
38    gctx: &GlobalContext,
39) -> CargoResult<()> {
40    let manifest = pkg.manifest();
41    let LintLevelProduct {
42        level: lint_level,
43        source,
44    } = level;
45
46    if manifest
47        .normalized_toml()
48        .package()
49        .is_some_and(|p| p.im_a_teapot.is_some())
50    {
51        let level = lint_level.to_diagnostic_level();
52        let manifest_path = workspace_rel_path(ws, path);
53        let emitted_source = LINT.emitted_source(lint_level, source);
54
55        let mut desc = Group::with_title(level.primary_title("`im_a_teapot` is specified"));
56
57        if let Some(document) = manifest.document()
58            && let Some(contents) = manifest.contents()
59        {
60            let span = get_key_value_span(document, &["package", "im-a-teapot"]).unwrap();
61
62            desc = desc.element(
63                Snippet::source(contents)
64                    .path(&manifest_path)
65                    .annotation(AnnotationKind::Primary.span(span.key.start..span.value.end)),
66            );
67        } else {
68            desc = desc.element(Origin::path(&manifest_path));
69        }
70
71        let report = &[desc.element(Level::NOTE.message(&emitted_source))];
72
73        pkg_stats.record_lint(lint_level);
74        gctx.shell().print_report(report, lint_level.force())?;
75    }
76    Ok(())
77}