1 //! Tidy checks source code in this repository.
3 //! This program runs all of the various tidy checks for style, cleanliness,
4 //! etc. This is run by default on `./x.py test` and as part of the auto
5 //! builders. The tidy checks can be executed with `./x.py test tidy`.
9 use std::collections::VecDeque;
11 use std::num::NonZeroUsize;
12 use std::path::PathBuf;
14 use std::str::FromStr;
15 use std::sync::atomic::{AtomicBool, Ordering};
16 use std::thread::{scope, ScopedJoinHandle};
19 let root_path: PathBuf = env::args_os().nth(1).expect("need path to root of repo").into();
20 let cargo: PathBuf = env::args_os().nth(2).expect("need path to cargo").into();
21 let output_directory: PathBuf =
22 env::args_os().nth(3).expect("need path to output directory").into();
23 let concurrency: NonZeroUsize =
24 FromStr::from_str(&env::args().nth(4).expect("need concurrency"))
25 .expect("concurrency must be a number");
27 let src_path = root_path.join("src");
28 let library_path = root_path.join("library");
29 let compiler_path = root_path.join("compiler");
31 let args: Vec<String> = env::args().skip(1).collect();
33 let verbose = args.iter().any(|s| *s == "--verbose");
34 let bless = args.iter().any(|s| *s == "--bless");
36 let bad = std::sync::Arc::new(AtomicBool::new(false));
38 let drain_handles = |handles: &mut VecDeque<ScopedJoinHandle<'_, ()>>| {
39 // poll all threads for completion before awaiting the oldest one
40 for i in (0..handles.len()).rev() {
41 if handles[i].is_finished() {
42 handles.swap_remove_back(i).unwrap().join().unwrap();
46 while handles.len() >= concurrency.get() {
47 handles.pop_front().unwrap().join().unwrap();
52 let mut handles: VecDeque<ScopedJoinHandle<'_, ()>> =
53 VecDeque::with_capacity(concurrency.get());
56 ($p:ident $(, $args:expr)* ) => {
57 drain_handles(&mut handles);
59 let handle = s.spawn(|| {
61 $p::check($($args),* , &mut flag);
63 bad.store(true, Ordering::Relaxed);
66 handles.push_back(handle);
70 check!(target_specific_tests, &src_path);
72 // Checks that are done on the cargo workspace.
73 check!(deps, &root_path, &cargo);
74 check!(extdeps, &root_path);
77 check!(debug_artifacts, &src_path);
78 check!(ui_tests, &src_path);
79 check!(mir_opt_tests, &src_path, bless);
81 // Checks that only make sense for the compiler.
82 check!(errors, &compiler_path);
83 check!(error_codes_check, &[&src_path, &compiler_path]);
85 // Checks that only make sense for the std libs.
86 check!(pal, &library_path);
87 check!(primitive_docs, &library_path);
89 // Checks that need to be done for both the compiler and std libraries.
90 check!(unit_tests, &src_path);
91 check!(unit_tests, &compiler_path);
92 check!(unit_tests, &library_path);
94 if bins::check_filesystem_support(&[&root_path], &output_directory) {
95 check!(bins, &root_path);
98 check!(style, &src_path);
99 check!(style, &compiler_path);
100 check!(style, &library_path);
102 check!(edition, &src_path);
103 check!(edition, &compiler_path);
104 check!(edition, &library_path);
106 check!(alphabetical, &src_path);
107 check!(alphabetical, &compiler_path);
108 check!(alphabetical, &library_path);
111 drain_handles(&mut handles);
113 let mut flag = false;
114 let r = features::check(&src_path, &compiler_path, &library_path, &mut flag, verbose);
116 bad.store(true, Ordering::Relaxed);
120 check!(unstable_book, &src_path, collected);
123 if bad.load(Ordering::Relaxed) {
124 eprintln!("some tidy checks failed");