1 use cargo_metadata::MetadataCommand;
2 use clippy_utils::diagnostics::span_lint;
3 use clippy_utils::is_lint_allowed;
4 use rustc_hir::hir_id::CRATE_HIR_ID;
5 use rustc_lint::{LateContext, LateLintPass, Lint};
6 use rustc_session::{declare_tool_lint, impl_lint_pass};
7 use rustc_span::DUMMY_SP;
11 mod multiple_crate_versions;
12 mod wildcard_dependencies;
14 declare_clippy_lint! {
16 /// Checks to see if all common metadata is defined in
17 /// `Cargo.toml`. See: https://rust-lang-nursery.github.io/api-guidelines/documentation.html#cargotoml-includes-all-common-metadata-c-metadata
19 /// ### Why is this bad?
20 /// It will be more difficult for users to discover the
21 /// purpose of the crate, and key information related to it.
25 /// # This `Cargo.toml` is missing a description field:
28 /// version = "0.0.212"
29 /// repository = "https://github.com/rust-lang/rust-clippy"
30 /// readme = "README.md"
31 /// license = "MIT OR Apache-2.0"
32 /// keywords = ["clippy", "lint", "plugin"]
33 /// categories = ["development-tools", "development-tools::cargo-plugins"]
36 /// Should include a description field like:
39 /// # This `Cargo.toml` includes all common metadata
42 /// version = "0.0.212"
43 /// description = "A bunch of helpful lints to avoid common pitfalls in Rust"
44 /// repository = "https://github.com/rust-lang/rust-clippy"
45 /// readme = "README.md"
46 /// license = "MIT OR Apache-2.0"
47 /// keywords = ["clippy", "lint", "plugin"]
48 /// categories = ["development-tools", "development-tools::cargo-plugins"]
50 #[clippy::version = "1.32.0"]
51 pub CARGO_COMMON_METADATA,
53 "common metadata is defined in `Cargo.toml`"
56 declare_clippy_lint! {
58 /// Checks for feature names with prefix `use-`, `with-` or suffix `-support`
60 /// ### Why is this bad?
61 /// These prefixes and suffixes have no significant meaning.
65 /// # The `Cargo.toml` with feature name redundancy
67 /// default = ["use-abc", "with-def", "ghi-support"]
68 /// use-abc = [] // redundant
69 /// with-def = [] // redundant
70 /// ghi-support = [] // redundant
76 /// default = ["abc", "def", "ghi"]
82 #[clippy::version = "1.57.0"]
83 pub REDUNDANT_FEATURE_NAMES,
85 "usage of a redundant feature name"
88 declare_clippy_lint! {
90 /// Checks for negative feature names with prefix `no-` or `not-`
92 /// ### Why is this bad?
93 /// Features are supposed to be additive, and negatively-named features violate it.
97 /// # The `Cargo.toml` with negative feature names
107 /// default = ["abc", "def"]
112 #[clippy::version = "1.57.0"]
113 pub NEGATIVE_FEATURE_NAMES,
115 "usage of a negative feature name"
118 declare_clippy_lint! {
120 /// Checks to see if multiple versions of a crate are being
123 /// ### Why is this bad?
124 /// This bloats the size of targets, and can lead to
125 /// confusing error messages when structs or traits are used interchangeably
126 /// between different versions of a crate.
128 /// ### Known problems
129 /// Because this can be caused purely by the dependencies
130 /// themselves, it's not always possible to fix this issue.
134 /// # This will pull in both winapi v0.3.x and v0.2.x, triggering a warning.
137 /// ansi_term = "=0.11.0"
139 #[clippy::version = "pre 1.29.0"]
140 pub MULTIPLE_CRATE_VERSIONS,
142 "multiple versions of the same crate being used"
145 declare_clippy_lint! {
147 /// Checks for wildcard dependencies in the `Cargo.toml`.
149 /// ### Why is this bad?
150 /// [As the edition guide says](https://rust-lang-nursery.github.io/edition-guide/rust-2018/cargo-and-crates-io/crates-io-disallows-wildcard-dependencies.html),
151 /// it is highly unlikely that you work with any possible version of your dependency,
152 /// and wildcard dependencies would cause unnecessary breakage in the ecosystem.
159 #[clippy::version = "1.32.0"]
160 pub WILDCARD_DEPENDENCIES,
162 "wildcard dependencies being used"
166 pub ignore_publish: bool,
169 impl_lint_pass!(Cargo => [
170 CARGO_COMMON_METADATA,
171 REDUNDANT_FEATURE_NAMES,
172 NEGATIVE_FEATURE_NAMES,
173 MULTIPLE_CRATE_VERSIONS,
174 WILDCARD_DEPENDENCIES
177 impl LateLintPass<'_> for Cargo {
178 fn check_crate(&mut self, cx: &LateContext<'_>) {
179 static NO_DEPS_LINTS: &[&Lint] = &[
180 CARGO_COMMON_METADATA,
181 REDUNDANT_FEATURE_NAMES,
182 NEGATIVE_FEATURE_NAMES,
183 WILDCARD_DEPENDENCIES,
185 static WITH_DEPS_LINTS: &[&Lint] = &[MULTIPLE_CRATE_VERSIONS];
189 .all(|&lint| is_lint_allowed(cx, lint, CRATE_HIR_ID))
191 match MetadataCommand::new().no_deps().exec() {
193 common_metadata::check(cx, &metadata, self.ignore_publish);
194 feature_name::check(cx, &metadata);
195 wildcard_dependencies::check(cx, &metadata);
198 for lint in NO_DEPS_LINTS {
199 span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {}", e));
207 .all(|&lint| is_lint_allowed(cx, lint, CRATE_HIR_ID))
209 match MetadataCommand::new().exec() {
211 multiple_crate_versions::check(cx, &metadata);
214 for lint in WITH_DEPS_LINTS {
215 span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {}", e));