diff options
Diffstat (limited to 'third_party/libc/ci/style.rs')
-rw-r--r-- | third_party/libc/ci/style.rs | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/third_party/libc/ci/style.rs b/third_party/libc/ci/style.rs new file mode 100644 index 0000000..32e4ba7 --- /dev/null +++ b/third_party/libc/ci/style.rs | |||
@@ -0,0 +1,204 @@ | |||
1 | //! Simple script to verify the coding style of this library | ||
2 | //! | ||
3 | //! ## How to run | ||
4 | //! | ||
5 | //! The first argument to this script is the directory to run on, so running | ||
6 | //! this script should be as simple as: | ||
7 | //! | ||
8 | //! ```notrust | ||
9 | //! rustc ci/style.rs | ||
10 | //! ./style src | ||
11 | //! ``` | ||
12 | //! | ||
13 | //! ## Guidelines | ||
14 | //! | ||
15 | //! The current style is: | ||
16 | //! | ||
17 | //! * No trailing whitespace | ||
18 | //! * No tabs | ||
19 | //! * 80-character lines | ||
20 | //! * `extern` instead of `extern "C"` | ||
21 | //! * Specific module layout: | ||
22 | //! 1. use directives | ||
23 | //! 2. typedefs | ||
24 | //! 3. structs | ||
25 | //! 4. constants | ||
26 | //! 5. f! { ... } functions | ||
27 | //! 6. extern functions | ||
28 | //! 7. modules + pub use | ||
29 | //! | ||
30 | //! Things not verified: | ||
31 | //! | ||
32 | //! * alignment | ||
33 | //! * 4-space tabs | ||
34 | //! * leading colons on paths | ||
35 | |||
36 | use std::env; | ||
37 | use std::fs; | ||
38 | use std::io::prelude::*; | ||
39 | use std::path::Path; | ||
40 | |||
41 | macro_rules! t { | ||
42 | ($e:expr) => (match $e { | ||
43 | Ok(e) => e, | ||
44 | Err(e) => panic!("{} failed with {}", stringify!($e), e), | ||
45 | }) | ||
46 | } | ||
47 | |||
48 | fn main() { | ||
49 | let arg = env::args().skip(1).next().unwrap_or(".".to_string()); | ||
50 | |||
51 | let mut errors = Errors { errs: false }; | ||
52 | walk(Path::new(&arg), &mut errors); | ||
53 | |||
54 | if errors.errs { | ||
55 | panic!("found some lint errors"); | ||
56 | } else { | ||
57 | println!("good style!"); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | fn walk(path: &Path, err: &mut Errors) { | ||
62 | for entry in t!(path.read_dir()).map(|e| t!(e)) { | ||
63 | let path = entry.path(); | ||
64 | if t!(entry.file_type()).is_dir() { | ||
65 | walk(&path, err); | ||
66 | continue | ||
67 | } | ||
68 | |||
69 | let name = entry.file_name().into_string().unwrap(); | ||
70 | match &name[..] { | ||
71 | n if !n.ends_with(".rs") => continue, | ||
72 | |||
73 | "dox.rs" | | ||
74 | "lib.rs" | | ||
75 | "macros.rs" => continue, | ||
76 | |||
77 | _ => {} | ||
78 | } | ||
79 | |||
80 | let mut contents = String::new(); | ||
81 | t!(t!(fs::File::open(&path)).read_to_string(&mut contents)); | ||
82 | |||
83 | check_style(&contents, &path, err); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | struct Errors { | ||
88 | errs: bool, | ||
89 | } | ||
90 | |||
91 | #[derive(Clone, Copy, PartialEq)] | ||
92 | enum State { | ||
93 | Start, | ||
94 | Imports, | ||
95 | Typedefs, | ||
96 | Structs, | ||
97 | Constants, | ||
98 | FunctionDefinitions, | ||
99 | Functions, | ||
100 | Modules, | ||
101 | } | ||
102 | |||
103 | fn check_style(file: &str, path: &Path, err: &mut Errors) { | ||
104 | let mut state = State::Start; | ||
105 | let mut s_macros = 0; | ||
106 | let mut f_macros = 0; | ||
107 | let mut prev_blank = false; | ||
108 | |||
109 | for (i, line) in file.lines().enumerate() { | ||
110 | if line == "" { | ||
111 | if prev_blank { | ||
112 | err.error(path, i, "double blank line"); | ||
113 | } | ||
114 | prev_blank = true; | ||
115 | } else { | ||
116 | prev_blank = false; | ||
117 | } | ||
118 | if line != line.trim_right() { | ||
119 | err.error(path, i, "trailing whitespace"); | ||
120 | } | ||
121 | if line.contains("\t") { | ||
122 | err.error(path, i, "tab character"); | ||
123 | } | ||
124 | if line.len() > 80 { | ||
125 | err.error(path, i, "line longer than 80 chars"); | ||
126 | } | ||
127 | if line.contains("extern \"C\"") { | ||
128 | err.error(path, i, "use `extern` instead of `extern \"C\""); | ||
129 | } | ||
130 | if line.contains("#[cfg(") && !line.contains(" if ") { | ||
131 | if state != State::Structs { | ||
132 | err.error(path, i, "use cfg_if! and submodules \ | ||
133 | instead of #[cfg]"); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | let line = line.trim_left(); | ||
138 | let is_pub = line.starts_with("pub "); | ||
139 | let line = if is_pub {&line[4..]} else {line}; | ||
140 | |||
141 | let line_state = if line.starts_with("use ") { | ||
142 | if is_pub { | ||
143 | State::Modules | ||
144 | } else { | ||
145 | State::Imports | ||
146 | } | ||
147 | } else if line.starts_with("const ") { | ||
148 | State::Constants | ||
149 | } else if line.starts_with("type ") { | ||
150 | State::Typedefs | ||
151 | } else if line.starts_with("s! {") { | ||
152 | s_macros += 1; | ||
153 | State::Structs | ||
154 | } else if line.starts_with("f! {") { | ||
155 | f_macros += 1; | ||
156 | State::FunctionDefinitions | ||
157 | } else if line.starts_with("extern ") { | ||
158 | State::Functions | ||
159 | } else if line.starts_with("mod ") { | ||
160 | State::Modules | ||
161 | } else { | ||
162 | continue | ||
163 | }; | ||
164 | |||
165 | if state as usize > line_state as usize { | ||
166 | err.error(path, i, &format!("{} found after {} when \ | ||
167 | it belongs before", | ||
168 | line_state.desc(), state.desc())); | ||
169 | } | ||
170 | |||
171 | if f_macros == 2 { | ||
172 | f_macros += 1; | ||
173 | err.error(path, i, "multiple f! macros in one module"); | ||
174 | } | ||
175 | if s_macros == 2 { | ||
176 | s_macros += 1; | ||
177 | err.error(path, i, "multiple s! macros in one module"); | ||
178 | } | ||
179 | |||
180 | state = line_state; | ||
181 | } | ||
182 | } | ||
183 | |||
184 | impl State { | ||
185 | fn desc(&self) -> &str { | ||
186 | match *self { | ||
187 | State::Start => "start", | ||
188 | State::Imports => "import", | ||
189 | State::Typedefs => "typedef", | ||
190 | State::Structs => "struct", | ||
191 | State::Constants => "constant", | ||
192 | State::FunctionDefinitions => "function definition", | ||
193 | State::Functions => "extern function", | ||
194 | State::Modules => "module", | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | |||
199 | impl Errors { | ||
200 | fn error(&mut self, path: &Path, line: usize, msg: &str) { | ||
201 | self.errs = true; | ||
202 | println!("{}:{} - {}", path.display(), line + 1, msg); | ||
203 | } | ||
204 | } | ||