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
127impl CheckOptions {
128 pub fn apply(&self, cmd: &mut Command) {
129 for pkg in &self.packages {
130 cmd.arg("--package").arg(pkg);
131 }
132 if self.workspace {
133 cmd.arg("--workspace");
134 }
135 for item in &self.exclude {
136 cmd.arg("--exclude").arg(item);
137 }
138 if self.all {
139 cmd.arg("--all");
140 }
141 if self.lib {
142 cmd.arg("--lib");
143 }
144 for bin in &self.bin {
145 cmd.arg("--bin").arg(bin);
146 }
147 if self.bins {
148 cmd.arg("--bins");
149 }
150 for example in &self.example {
151 cmd.arg("--example").arg(example);
152 }
153 if self.examples {
154 cmd.arg("--examples");
155 }
156 for test in &self.test {
157 cmd.arg("--test").arg(test);
158 }
159 if self.tests {
160 cmd.arg("--tests");
161 }
162 for bench in &self.bench {
163 cmd.arg("--bench").arg(bench);
164 }
165 if self.benches {
166 cmd.arg("--benches");
167 }
168 if self.all_targets {
169 cmd.arg("--all-targets");
170 }
171 if self.future_incompat_report {
172 cmd.arg("--future-incompat-report");
173 }
174 }
175}
176
177#[derive(Clone, Debug, Default, Parser)]
179#[command(
180 display_order = 1,
181 after_help = "Run `cargo help check` for more detailed information."
182)]
183#[group(skip)]
184#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
185pub struct Check {
186 #[command(flatten)]
187 #[cfg_attr(feature = "serde", serde(flatten))]
188 pub common: CommonOptions,
189
190 #[command(flatten)]
191 #[cfg_attr(feature = "serde", serde(flatten))]
192 pub check: CheckOptions,
193
194 #[arg(long, value_name = "PATH", help_heading = heading::MANIFEST_OPTIONS)]
196 #[cfg_attr(feature = "serde", serde(default))]
197 pub manifest_path: Option<PathBuf>,
198
199 #[arg(short = 'r', long, help_heading = heading::COMPILATION_OPTIONS)]
201 #[cfg_attr(feature = "serde", serde(default))]
202 pub release: bool,
203
204 #[arg(long)]
206 #[cfg_attr(feature = "serde", serde(default))]
207 pub ignore_rust_version: bool,
208
209 #[arg(long, help_heading = heading::COMPILATION_OPTIONS)]
211 #[cfg_attr(feature = "serde", serde(default))]
212 pub unit_graph: bool,
213}
214
215impl Check {
216 pub fn command(&self) -> Command {
218 let mut cmd = CommonOptions::cargo_command();
219 cmd.arg("check");
220
221 self.common.apply(&mut cmd);
222 self.check.apply(&mut cmd);
223
224 if let Some(path) = self.manifest_path.as_ref() {
225 cmd.arg("--manifest-path").arg(path);
226 }
227 if self.release {
228 cmd.arg("--release");
229 }
230 if self.ignore_rust_version {
231 cmd.arg("--ignore-rust-version");
232 }
233 if self.unit_graph {
234 cmd.arg("--unit-graph");
235 }
236
237 cmd
238 }
239}
240
241impl Deref for Check {
242 type Target = CommonOptions;
243
244 fn deref(&self) -> &Self::Target {
245 &self.common
246 }
247}
248
249impl DerefMut for Check {
250 fn deref_mut(&mut self) -> &mut Self::Target {
251 &mut self.common
252 }
253}
254
255#[cfg(test)]
256mod test {
257 use super::Check;
258 use clap::CommandFactory;
259
260 #[test]
261 fn verify_cli() {
262 <Check as CommandFactory>::command().debug_assert()
263 }
264}