1#![feature(exit_status_error)]
2
3use std::{env, process};
4
5pub fn fmt() {
6 #[cfg(not(miri))]
7 {
8 let mut command = process::Command::new(env::var("CARGO").unwrap());
9 command.args(["fmt", "--all"]);
10
11 let config = "--config=style_edition=2024,imports_granularity=Crate,\
12 group_imports=StdExternalCrate,use_field_init_shorthand=true,\
13 format_code_in_doc_comments=true,format_macro_bodies=true,\
14 format_macro_matchers=true,format_strings=true,wrap_comments=true,\
15 overflow_delimited_expr=true";
16 if env::var_os("UPDATE_EXPECT").is_some() {
17 command
18 .args(["--", config])
19 .status()
20 .unwrap()
21 .exit_ok()
22 .unwrap();
23 } else {
24 command
25 .args(["--", "--check", config])
26 .status()
27 .unwrap()
28 .exit_ok()
29 .unwrap();
30 }
31 }
32}
33
34pub fn clippy() {
35 #[cfg(not(miri))]
36 {
37 let mut command = process::Command::new(env::var("CARGO").unwrap());
38 command.args(["clippy", "--workspace"]);
39
40 let config = [
41 ["-W", "clippy::all"],
42 ["-W", "clippy::pedantic"],
43 ["-W", "clippy::nursery"],
44 ["-W", "clippy::cargo"],
45 ["-W", "clippy::float_cmp_const"],
46 ["-W", "clippy::empty_structs_with_brackets"],
47 ["-A", "clippy::multiple_crate_versions"],
48 ["-A", "clippy::module_name_repetitions"],
49 ["-A", "clippy::too_many_lines"],
50 ["-A", "clippy::too_many_arguments"],
51 ["-A", "clippy::cognitive_complexity"],
52 ["-A", "clippy::type_complexity"],
53 ["-A", "clippy::missing_panics_doc"],
54 ["-A", "clippy::missing_errors_doc"],
55 ["-A", "clippy::blocks_in_conditions"],
56 ["-A", "clippy::unnecessary_debug_formatting"],
57 ["-A", "clippy::struct_excessive_bools"],
58 ["-A", "clippy::non_send_fields_in_send_ty"],
59 ]
60 .as_flattened();
61 if env::var_os("UPDATE_EXPECT").is_some() {
62 command
63 .args(["--fix", "--allow-dirty", "--allow-staged", "--"])
64 .args(config)
65 .status()
66 .unwrap()
67 .exit_ok()
68 .unwrap();
69 } else {
70 command
71 .args(["--", "-D", "warnings"])
72 .args(config)
73 .status()
74 .unwrap()
75 .exit_ok()
76 .unwrap();
77 }
78 }
79}
80
81#[cfg(feature = "api")]
82pub fn api() {
83 #[cfg(not(miri))] {
85 use expect_test::expect_file;
86
87 let json_path = rustdoc_json::Builder::default()
88 .all_features(true)
89 .build()
90 .unwrap();
91
92 let api = public_api::Builder::from_rustdoc_json(json_path)
93 .build()
94 .unwrap()
95 .to_string();
96
97 expect_file![path_from_root("api.golden")].assert_eq(&api);
98 }
99}
100
101#[cfg(feature = "clap")]
102pub fn help_for_review(command: clap_builder::Command) {
103 #[derive(Copy, Clone)]
104 enum LongOrShortHelp {
105 Long,
106 Short,
107 }
108
109 fn write_help(
110 buffer: &mut impl std::fmt::Write,
111 cmd: &mut clap_builder::Command,
112 long_or_short_help: LongOrShortHelp,
113 ) {
114 write!(buffer, "{}", match long_or_short_help {
115 LongOrShortHelp::Long => cmd.render_long_help(),
116 LongOrShortHelp::Short => cmd.render_help(),
117 })
118 .unwrap();
119
120 for sub in cmd.get_subcommands_mut() {
121 if sub.get_name() == "help" {
122 continue;
123 }
124
125 writeln!(buffer).unwrap();
126 writeln!(buffer, "---").unwrap();
127 writeln!(buffer).unwrap();
128
129 write_help(buffer, sub, long_or_short_help);
130 }
131 }
132
133 #[cfg(not(miri))] {
135 use expect_test::expect_file;
136
137 let mut command = command.term_width(100);
138 command.build();
139
140 let mut long = String::new();
141 let mut short = String::new();
142
143 write_help(&mut long, &mut command, LongOrShortHelp::Long);
144 write_help(&mut short, &mut command, LongOrShortHelp::Short);
145
146 expect_file![path_from_root("command-reference.golden")].assert_eq(&long);
147 expect_file![path_from_root("command-reference-short.golden")].assert_eq(&short);
148 }
149}
150
151#[cfg(any(feature = "api", feature = "clap"))]
152fn path_from_root(path: &str) -> std::path::PathBuf {
153 let mut dir = std::path::PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
154 dir.push(path);
155 dir
156}