]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs
Merge commit 'ac0e10aa68325235069a842f47499852b2dee79e' into clippyup
[rust.git] / src / tools / clippy / clippy_lints / src / cargo / common_metadata.rs
1 //! lint on missing cargo common metadata
2
3 use cargo_metadata::Metadata;
4 use clippy_utils::diagnostics::span_lint;
5 use rustc_lint::LateContext;
6 use rustc_span::source_map::DUMMY_SP;
7
8 use super::CARGO_COMMON_METADATA;
9
10 pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata, ignore_publish: bool) {
11     for package in &metadata.packages {
12         // only run the lint if publish is `None` (`publish = true` or skipped entirely)
13         // or if the vector isn't empty (`publish = ["something"]`)
14         if package.publish.as_ref().filter(|publish| publish.is_empty()).is_none() || ignore_publish {
15             if is_empty_str(&package.description) {
16                 missing_warning(cx, package, "package.description");
17             }
18
19             if is_empty_str(&package.license) && is_empty_str(&package.license_file) {
20                 missing_warning(cx, package, "either package.license or package.license_file");
21             }
22
23             if is_empty_str(&package.repository) {
24                 missing_warning(cx, package, "package.repository");
25             }
26
27             if is_empty_str(&package.readme) {
28                 missing_warning(cx, package, "package.readme");
29             }
30
31             if is_empty_vec(&package.keywords) {
32                 missing_warning(cx, package, "package.keywords");
33             }
34
35             if is_empty_vec(&package.categories) {
36                 missing_warning(cx, package, "package.categories");
37             }
38         }
39     }
40 }
41
42 fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, field: &str) {
43     let message = format!("package `{}` is missing `{field}` metadata", package.name);
44     span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message);
45 }
46
47 fn is_empty_str<T: AsRef<std::ffi::OsStr>>(value: &Option<T>) -> bool {
48     value.as_ref().map_or(true, |s| s.as_ref().is_empty())
49 }
50
51 fn is_empty_vec(value: &[String]) -> bool {
52     // This works because empty iterators return true
53     value.iter().all(String::is_empty)
54 }