12add0d91Sopenharmony_ci//! Simple script to verify the coding style of this library 22add0d91Sopenharmony_ci//! 32add0d91Sopenharmony_ci//! ## How to run 42add0d91Sopenharmony_ci//! 52add0d91Sopenharmony_ci//! The first argument to this script is the directory to run on, so running 62add0d91Sopenharmony_ci//! this script should be as simple as: 72add0d91Sopenharmony_ci//! 82add0d91Sopenharmony_ci//! ```notrust 92add0d91Sopenharmony_ci//! rustc ci/style.rs 102add0d91Sopenharmony_ci//! ./style src 112add0d91Sopenharmony_ci//! ``` 122add0d91Sopenharmony_ci//! 132add0d91Sopenharmony_ci//! ## Guidelines 142add0d91Sopenharmony_ci//! 152add0d91Sopenharmony_ci//! The current style is: 162add0d91Sopenharmony_ci//! 172add0d91Sopenharmony_ci//! * Specific module layout: 182add0d91Sopenharmony_ci//! 1. use directives 192add0d91Sopenharmony_ci//! 2. typedefs 202add0d91Sopenharmony_ci//! 3. structs 212add0d91Sopenharmony_ci//! 4. constants 222add0d91Sopenharmony_ci//! 5. f! { ... } functions 232add0d91Sopenharmony_ci//! 6. extern functions 242add0d91Sopenharmony_ci//! 7. modules + pub use 252add0d91Sopenharmony_ci//! 262add0d91Sopenharmony_ci//! Things not verified: 272add0d91Sopenharmony_ci//! 282add0d91Sopenharmony_ci//! * alignment 292add0d91Sopenharmony_ci//! * leading colons on paths 302add0d91Sopenharmony_ci 312add0d91Sopenharmony_ciuse std::env; 322add0d91Sopenharmony_ciuse std::fs; 332add0d91Sopenharmony_ciuse std::io::prelude::*; 342add0d91Sopenharmony_ciuse std::path::Path; 352add0d91Sopenharmony_ci 362add0d91Sopenharmony_cimacro_rules! t { 372add0d91Sopenharmony_ci ($e:expr) => { 382add0d91Sopenharmony_ci match $e { 392add0d91Sopenharmony_ci Ok(e) => e, 402add0d91Sopenharmony_ci Err(e) => panic!("{} failed with {}", stringify!($e), e), 412add0d91Sopenharmony_ci } 422add0d91Sopenharmony_ci }; 432add0d91Sopenharmony_ci} 442add0d91Sopenharmony_ci 452add0d91Sopenharmony_cifn main() { 462add0d91Sopenharmony_ci let arg = env::args().skip(1).next().unwrap_or(".".to_string()); 472add0d91Sopenharmony_ci 482add0d91Sopenharmony_ci let mut errors = Errors { errs: false }; 492add0d91Sopenharmony_ci walk(Path::new(&arg), &mut errors); 502add0d91Sopenharmony_ci 512add0d91Sopenharmony_ci if errors.errs { 522add0d91Sopenharmony_ci panic!("found some lint errors"); 532add0d91Sopenharmony_ci } else { 542add0d91Sopenharmony_ci println!("good style!"); 552add0d91Sopenharmony_ci } 562add0d91Sopenharmony_ci} 572add0d91Sopenharmony_ci 582add0d91Sopenharmony_cifn walk(path: &Path, err: &mut Errors) { 592add0d91Sopenharmony_ci for entry in t!(path.read_dir()).map(|e| t!(e)) { 602add0d91Sopenharmony_ci let path = entry.path(); 612add0d91Sopenharmony_ci if t!(entry.file_type()).is_dir() { 622add0d91Sopenharmony_ci walk(&path, err); 632add0d91Sopenharmony_ci continue; 642add0d91Sopenharmony_ci } 652add0d91Sopenharmony_ci 662add0d91Sopenharmony_ci let name = entry.file_name().into_string().unwrap(); 672add0d91Sopenharmony_ci match &name[..] { 682add0d91Sopenharmony_ci n if !n.ends_with(".rs") => continue, 692add0d91Sopenharmony_ci 702add0d91Sopenharmony_ci "lib.rs" | "macros.rs" => continue, 712add0d91Sopenharmony_ci 722add0d91Sopenharmony_ci _ => {} 732add0d91Sopenharmony_ci } 742add0d91Sopenharmony_ci 752add0d91Sopenharmony_ci let mut contents = String::new(); 762add0d91Sopenharmony_ci t!(t!(fs::File::open(&path)).read_to_string(&mut contents)); 772add0d91Sopenharmony_ci 782add0d91Sopenharmony_ci check_style(&contents, &path, err); 792add0d91Sopenharmony_ci } 802add0d91Sopenharmony_ci} 812add0d91Sopenharmony_ci 822add0d91Sopenharmony_cistruct Errors { 832add0d91Sopenharmony_ci errs: bool, 842add0d91Sopenharmony_ci} 852add0d91Sopenharmony_ci 862add0d91Sopenharmony_ci#[derive(Clone, Copy, PartialEq)] 872add0d91Sopenharmony_cienum State { 882add0d91Sopenharmony_ci Start, 892add0d91Sopenharmony_ci Imports, 902add0d91Sopenharmony_ci Typedefs, 912add0d91Sopenharmony_ci Structs, 922add0d91Sopenharmony_ci Constants, 932add0d91Sopenharmony_ci FunctionDefinitions, 942add0d91Sopenharmony_ci Functions, 952add0d91Sopenharmony_ci Modules, 962add0d91Sopenharmony_ci} 972add0d91Sopenharmony_ci 982add0d91Sopenharmony_cifn check_style(file: &str, path: &Path, err: &mut Errors) { 992add0d91Sopenharmony_ci let mut state = State::Start; 1002add0d91Sopenharmony_ci let mut s_macros = 0; 1012add0d91Sopenharmony_ci let mut f_macros = 0; 1022add0d91Sopenharmony_ci let mut in_impl = false; 1032add0d91Sopenharmony_ci 1042add0d91Sopenharmony_ci for (i, line) in file.lines().enumerate() { 1052add0d91Sopenharmony_ci if line.contains("#[cfg(") 1062add0d91Sopenharmony_ci && line.contains(']') 1072add0d91Sopenharmony_ci && !line.contains(" if ") 1082add0d91Sopenharmony_ci && !(line.contains("target_endian") || line.contains("target_arch")) 1092add0d91Sopenharmony_ci { 1102add0d91Sopenharmony_ci if state != State::Structs { 1112add0d91Sopenharmony_ci err.error(path, i, "use cfg_if! and submodules instead of #[cfg]"); 1122add0d91Sopenharmony_ci } 1132add0d91Sopenharmony_ci } 1142add0d91Sopenharmony_ci if line.contains("#[derive(") && (line.contains("Copy") || line.contains("Clone")) { 1152add0d91Sopenharmony_ci err.error(path, i, "impl ::Copy and ::Clone manually"); 1162add0d91Sopenharmony_ci } 1172add0d91Sopenharmony_ci if line.contains("impl") { 1182add0d91Sopenharmony_ci in_impl = true; 1192add0d91Sopenharmony_ci } 1202add0d91Sopenharmony_ci if in_impl && line.starts_with('}') { 1212add0d91Sopenharmony_ci in_impl = false; 1222add0d91Sopenharmony_ci } 1232add0d91Sopenharmony_ci 1242add0d91Sopenharmony_ci let orig_line = line; 1252add0d91Sopenharmony_ci let line = line.trim_start(); 1262add0d91Sopenharmony_ci let is_pub = line.starts_with("pub "); 1272add0d91Sopenharmony_ci let line = if is_pub { &line[4..] } else { line }; 1282add0d91Sopenharmony_ci 1292add0d91Sopenharmony_ci let line_state = if line.starts_with("use ") { 1302add0d91Sopenharmony_ci if line.contains("c_void") { 1312add0d91Sopenharmony_ci continue; 1322add0d91Sopenharmony_ci } 1332add0d91Sopenharmony_ci if is_pub { 1342add0d91Sopenharmony_ci State::Modules 1352add0d91Sopenharmony_ci } else { 1362add0d91Sopenharmony_ci State::Imports 1372add0d91Sopenharmony_ci } 1382add0d91Sopenharmony_ci } else if line.starts_with("const ") { 1392add0d91Sopenharmony_ci State::Constants 1402add0d91Sopenharmony_ci } else if line.starts_with("type ") && !in_impl { 1412add0d91Sopenharmony_ci State::Typedefs 1422add0d91Sopenharmony_ci } else if line.starts_with("s! {") { 1432add0d91Sopenharmony_ci s_macros += 1; 1442add0d91Sopenharmony_ci State::Structs 1452add0d91Sopenharmony_ci } else if line.starts_with("s_no_extra_traits! {") { 1462add0d91Sopenharmony_ci // multiple macros of this type are allowed 1472add0d91Sopenharmony_ci State::Structs 1482add0d91Sopenharmony_ci } else if line.starts_with("s_paren! {") { 1492add0d91Sopenharmony_ci // multiple macros of this type are allowed 1502add0d91Sopenharmony_ci State::Structs 1512add0d91Sopenharmony_ci } else if line.starts_with("f! {") { 1522add0d91Sopenharmony_ci f_macros += 1; 1532add0d91Sopenharmony_ci State::FunctionDefinitions 1542add0d91Sopenharmony_ci } else if line.starts_with("extern ") && !orig_line.starts_with(" ") { 1552add0d91Sopenharmony_ci State::Functions 1562add0d91Sopenharmony_ci } else if line.starts_with("mod ") { 1572add0d91Sopenharmony_ci State::Modules 1582add0d91Sopenharmony_ci } else { 1592add0d91Sopenharmony_ci continue; 1602add0d91Sopenharmony_ci }; 1612add0d91Sopenharmony_ci 1622add0d91Sopenharmony_ci if state as usize > line_state as usize { 1632add0d91Sopenharmony_ci err.error( 1642add0d91Sopenharmony_ci path, 1652add0d91Sopenharmony_ci i, 1662add0d91Sopenharmony_ci &format!( 1672add0d91Sopenharmony_ci "{} found after {} when it belongs before", 1682add0d91Sopenharmony_ci line_state.desc(), 1692add0d91Sopenharmony_ci state.desc() 1702add0d91Sopenharmony_ci ), 1712add0d91Sopenharmony_ci ); 1722add0d91Sopenharmony_ci } 1732add0d91Sopenharmony_ci 1742add0d91Sopenharmony_ci if f_macros == 2 { 1752add0d91Sopenharmony_ci f_macros += 1; 1762add0d91Sopenharmony_ci err.error(path, i, "multiple f! macros in one module"); 1772add0d91Sopenharmony_ci } 1782add0d91Sopenharmony_ci if s_macros == 2 { 1792add0d91Sopenharmony_ci s_macros += 1; 1802add0d91Sopenharmony_ci err.error(path, i, "multiple s! macros in one module"); 1812add0d91Sopenharmony_ci } 1822add0d91Sopenharmony_ci 1832add0d91Sopenharmony_ci state = line_state; 1842add0d91Sopenharmony_ci } 1852add0d91Sopenharmony_ci} 1862add0d91Sopenharmony_ci 1872add0d91Sopenharmony_ciimpl State { 1882add0d91Sopenharmony_ci fn desc(&self) -> &str { 1892add0d91Sopenharmony_ci match *self { 1902add0d91Sopenharmony_ci State::Start => "start", 1912add0d91Sopenharmony_ci State::Imports => "import", 1922add0d91Sopenharmony_ci State::Typedefs => "typedef", 1932add0d91Sopenharmony_ci State::Structs => "struct", 1942add0d91Sopenharmony_ci State::Constants => "constant", 1952add0d91Sopenharmony_ci State::FunctionDefinitions => "function definition", 1962add0d91Sopenharmony_ci State::Functions => "extern function", 1972add0d91Sopenharmony_ci State::Modules => "module", 1982add0d91Sopenharmony_ci } 1992add0d91Sopenharmony_ci } 2002add0d91Sopenharmony_ci} 2012add0d91Sopenharmony_ci 2022add0d91Sopenharmony_ciimpl Errors { 2032add0d91Sopenharmony_ci fn error(&mut self, path: &Path, line: usize, msg: &str) { 2042add0d91Sopenharmony_ci self.errs = true; 2052add0d91Sopenharmony_ci println!("{}:{}: {}", path.display(), line + 1, msg); 2062add0d91Sopenharmony_ci } 2072add0d91Sopenharmony_ci} 208