1use std::ops::{Deref, DerefMut};
2use std::path::PathBuf;
3use std::process::Command;
4
5use clap::{ArgAction, Parser};
6
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10use crate::common::CommonOptions;
11use crate::heading;
12
13#[derive(Clone, Debug, Default, Parser)]
15#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
16pub struct CheckOptions {
17 #[arg(
19 short = 'p',
20 long = "package",
21 value_name = "SPEC",
22 action = ArgAction::Append,
23 num_args=0..=1,
24 help_heading = heading::PACKAGE_SELECTION,
25 )]
26 #[cfg_attr(feature = "serde", serde(default))]
27 pub packages: Vec<String>,
28
29 #[arg(long, help_heading = heading::PACKAGE_SELECTION)]
31 #[cfg_attr(feature = "serde", serde(default))]
32 pub workspace: bool,
33
34 #[arg(
36 long,
37 value_name = "SPEC",
38 action = ArgAction::Append,
39 help_heading = heading::PACKAGE_SELECTION,
40 )]
41 #[cfg_attr(feature = "serde", serde(default))]
42 pub exclude: Vec<String>,
43
44 #[arg(long, help_heading = heading::PACKAGE_SELECTION,)]
46 #[cfg_attr(feature = "serde", serde(default))]
47 pub all: bool,
48
49 #[arg(long, help_heading = heading::TARGET_SELECTION)]
51 #[cfg_attr(feature = "serde", serde(default))]
52 pub lib: bool,
53
54 #[arg(
56 long,
57 value_name = "NAME",
58 action = ArgAction::Append,
59 num_args=0..=1,
60 help_heading = heading::TARGET_SELECTION,
61 )]
62 #[cfg_attr(feature = "serde", serde(default))]
63 pub bin: Vec<String>,
64
65 #[arg(long, help_heading = heading::TARGET_SELECTION)]
67 #[cfg_attr(feature = "serde", serde(default))]
68 pub bins: bool,
69
70 #[arg(
72 long,
73 value_name = "NAME",
74 action = ArgAction::Append,
75 num_args=0..=1,
76 help_heading = heading::TARGET_SELECTION,
77 )]
78 #[cfg_attr(feature = "serde", serde(default))]
79 pub example: Vec<String>,
80
81 #[arg(long, help_heading = heading::TARGET_SELECTION)]
83 #[cfg_attr(feature = "serde", serde(default))]
84 pub examples: bool,
85
86 #[arg(
88 long,
89 value_name = "NAME",
90 action = ArgAction::Append,
91 help_heading = heading::TARGET_SELECTION,
92 )]
93 #[cfg_attr(feature = "serde", serde(default))]
94 pub test: Vec<String>,
95
96 #[arg(long, help_heading = heading::TARGET_SELECTION)]
98 #[cfg_attr(feature = "serde", serde(default))]
99 pub tests: bool,
100
101 #[arg(
103 long,
104 value_name = "NAME",
105 action = ArgAction::Append,
106 help_heading = heading::TARGET_SELECTION,
107 )]
108 #[cfg_attr(feature = "serde", serde(default))]
109 pub bench: Vec<String>,
110
111 #[arg(long, help_heading = heading::TARGET_SELECTION)]
113 #[cfg_attr(feature = "serde", serde(default))]
114 pub benches: bool,
115
116 #[arg(long, help_heading = heading::TARGET_SELECTION)]
118 #[cfg_attr(feature = "serde", serde(default))]
119 pub all_targets: bool,
120
121 #[arg(long)]
123 #[cfg_attr(feature = "serde", serde(default))]
124 pub future_incompat_report: bool,
125
126 #[arg(long, hide = true)]
128 #[cfg_attr(feature = "serde", serde(default))]
129 pub compile_time_deps: bool,
130}
131
132impl CheckOptions {
133 pub fn apply(&self, cmd: &mut Command) {
134 for pkg in &self.packages {
135 cmd.arg("--package").arg(pkg);
136 }
137 if self.workspace {
138 cmd.arg("--workspace");
139 }
140 for item in &self.exclude {
141 cmd.arg("--exclude").arg(item);
142 }
143 if self.all {
144 cmd.arg("--all");
145 }
146 if self.lib {
147 cmd.arg("--lib");
148 }
149 for bin in &self.bin {
150 cmd.arg("--bin").arg(bin);
151 }
152 if self.bins {
153 cmd.arg("--bins");
154 }
155 for example in &self.example {
156 cmd.arg("--example").arg(example);
157 }
158 if self.examples {
159 cmd.arg("--examples");
160 }
161 for test in &self.test {
162 cmd.arg("--test").arg(test);
163 }
164 if self.tests {
165 cmd.arg("--tests");
166 }
167 for bench in &self.bench {
168 cmd.arg("--bench").arg(bench);
169 }
170 if self.benches {
171 cmd.arg("--benches");
172 }
173 if self.all_targets {
174 cmd.arg("--all-targets");
175 }
176 if self.future_incompat_report {
177 cmd.arg("--future-incompat-report");
178 }
179 if self.compile_time_deps {
180 cmd.arg("--compile-time-deps");
181 }
182 }
183}
184
185#[derive(Clone, Debug, Default, Parser)]
187#[command(
188 display_order = 1,
189 after_help = "Run `cargo help check` for more detailed information."
190)]
191#[group(skip)]
192#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
193pub struct Check {
194 #[command(flatten)]
195 #[cfg_attr(feature = "serde", serde(flatten))]
196 pub common: CommonOptions,
197
198 #[command(flatten)]
199 #[cfg_attr(feature = "serde", serde(flatten))]
200 pub check: CheckOptions,
201
202 #[arg(long, value_name = "PATH", help_heading = heading::MANIFEST_OPTIONS)]
204 #[cfg_attr(feature = "serde", serde(default))]
205 pub manifest_path: Option<PathBuf>,
206
207 #[arg(
209 short = 'r',
210 long,
211 conflicts_with = "profile",
212 help_heading = heading::COMPILATION_OPTIONS,
213 )]
214 #[cfg_attr(feature = "serde", serde(default))]
215 pub release: bool,
216
217 #[arg(long, help_heading = heading::MANIFEST_OPTIONS)]
219 #[cfg_attr(feature = "serde", serde(default))]
220 pub ignore_rust_version: bool,
221
222 #[arg(long, help_heading = heading::COMPILATION_OPTIONS)]
224 #[cfg_attr(feature = "serde", serde(default))]
225 pub unit_graph: bool,
226}
227
228impl Check {
229 pub fn command(&self) -> Command {
231 let mut cmd = CommonOptions::cargo_command();
232 cmd.arg("check");
233
234 self.common.apply(&mut cmd);
235 self.check.apply(&mut cmd);
236
237 if let Some(path) = self.manifest_path.as_ref() {
238 cmd.arg("--manifest-path").arg(path);
239 }
240 if self.release {
241 cmd.arg("--release");
242 }
243 if self.ignore_rust_version {
244 cmd.arg("--ignore-rust-version");
245 }
246 if self.unit_graph {
247 cmd.arg("--unit-graph");
248 }
249
250 cmd
251 }
252}
253
254impl Deref for Check {
255 type Target = CommonOptions;
256
257 fn deref(&self) -> &Self::Target {
258 &self.common
259 }
260}
261
262impl DerefMut for Check {
263 fn deref_mut(&mut self) -> &mut Self::Target {
264 &mut self.common
265 }
266}
267
268#[cfg(test)]
269mod test {
270 use super::Check;
271 use clap::CommandFactory;
272
273 #[test]
274 fn verify_cli() {
275 <Check as CommandFactory>::command().debug_assert()
276 }
277}