diff options
-rw-r--r-- | xtask/tests/tidy-tests/cli.rs | 25 | ||||
-rw-r--r-- | xtask/tests/tidy-tests/docs.rs | 106 | ||||
-rw-r--r-- | xtask/tests/tidy-tests/main.rs | 145 |
3 files changed, 145 insertions, 131 deletions
diff --git a/xtask/tests/tidy-tests/cli.rs b/xtask/tests/tidy-tests/cli.rs index f9ca45292..f5b00a8b8 100644 --- a/xtask/tests/tidy-tests/cli.rs +++ b/xtask/tests/tidy-tests/cli.rs | |||
@@ -1,7 +1,6 @@ | |||
1 | use walkdir::WalkDir; | ||
2 | use xtask::{ | 1 | use xtask::{ |
3 | codegen::{self, Mode}, | 2 | codegen::{self, Mode}, |
4 | project_root, run_rustfmt, | 3 | run_rustfmt, |
5 | }; | 4 | }; |
6 | 5 | ||
7 | #[test] | 6 | #[test] |
@@ -31,25 +30,3 @@ fn check_code_formatting() { | |||
31 | panic!("{}. Please format the code by running `cargo format`", error); | 30 | panic!("{}. Please format the code by running `cargo format`", error); |
32 | } | 31 | } |
33 | } | 32 | } |
34 | |||
35 | #[test] | ||
36 | fn no_todo() { | ||
37 | WalkDir::new(project_root().join("crates")).into_iter().for_each(|e| { | ||
38 | let e = e.unwrap(); | ||
39 | if e.path().extension().map(|it| it != "rs").unwrap_or(true) { | ||
40 | return; | ||
41 | } | ||
42 | if e.path().ends_with("tests/cli.rs") { | ||
43 | return; | ||
44 | } | ||
45 | let text = std::fs::read_to_string(e.path()).unwrap(); | ||
46 | if text.contains("TODO") || text.contains("TOOD") || text.contains("todo!") { | ||
47 | panic!( | ||
48 | "\nTODO markers should not be committed to the master branch,\n\ | ||
49 | use FIXME instead\n\ | ||
50 | {}\n", | ||
51 | e.path().display(), | ||
52 | ) | ||
53 | } | ||
54 | }) | ||
55 | } | ||
diff --git a/xtask/tests/tidy-tests/docs.rs b/xtask/tests/tidy-tests/docs.rs deleted file mode 100644 index 62c4f8441..000000000 --- a/xtask/tests/tidy-tests/docs.rs +++ /dev/null | |||
@@ -1,106 +0,0 @@ | |||
1 | use std::{collections::HashMap, fs, io::prelude::*, io::BufReader, path::Path}; | ||
2 | |||
3 | use anyhow::Context; | ||
4 | use walkdir::{DirEntry, WalkDir}; | ||
5 | use xtask::project_root; | ||
6 | |||
7 | fn is_exclude_dir(p: &Path) -> bool { | ||
8 | // Test hopefully don't really need comments, and for assists we already | ||
9 | // have special comments which are source of doc tests and user docs. | ||
10 | let exclude_dirs = ["tests", "test_data", "handlers"]; | ||
11 | let mut cur_path = p; | ||
12 | while let Some(path) = cur_path.parent() { | ||
13 | if exclude_dirs.iter().any(|dir| path.ends_with(dir)) { | ||
14 | return true; | ||
15 | } | ||
16 | cur_path = path; | ||
17 | } | ||
18 | |||
19 | false | ||
20 | } | ||
21 | |||
22 | fn is_exclude_file(d: &DirEntry) -> bool { | ||
23 | let file_names = ["tests.rs"]; | ||
24 | |||
25 | d.file_name().to_str().map(|f_n| file_names.iter().any(|name| *name == f_n)).unwrap_or(false) | ||
26 | } | ||
27 | |||
28 | fn is_hidden(entry: &DirEntry) -> bool { | ||
29 | entry.file_name().to_str().map(|s| s.starts_with('.')).unwrap_or(false) | ||
30 | } | ||
31 | |||
32 | #[test] | ||
33 | fn no_docs_comments() { | ||
34 | let crates = project_root().join("crates"); | ||
35 | let iter = WalkDir::new(crates); | ||
36 | let mut missing_docs = Vec::new(); | ||
37 | let mut contains_fixme = Vec::new(); | ||
38 | for f in iter.into_iter().filter_entry(|e| !is_hidden(e)) { | ||
39 | let f = f.unwrap(); | ||
40 | if f.file_type().is_dir() { | ||
41 | continue; | ||
42 | } | ||
43 | if f.path().extension().map(|it| it != "rs").unwrap_or(false) { | ||
44 | continue; | ||
45 | } | ||
46 | if is_exclude_dir(f.path()) { | ||
47 | continue; | ||
48 | } | ||
49 | if is_exclude_file(&f) { | ||
50 | continue; | ||
51 | } | ||
52 | let mut reader = BufReader::new(fs::File::open(f.path()).unwrap()); | ||
53 | let mut line = String::new(); | ||
54 | reader | ||
55 | .read_line(&mut line) | ||
56 | .with_context(|| format!("Failed to read {}", f.path().display())) | ||
57 | .unwrap(); | ||
58 | |||
59 | if line.starts_with("//!") { | ||
60 | if line.contains("FIXME") { | ||
61 | contains_fixme.push(f.path().to_path_buf()) | ||
62 | } | ||
63 | } else { | ||
64 | missing_docs.push(f.path().display().to_string()); | ||
65 | } | ||
66 | } | ||
67 | if !missing_docs.is_empty() { | ||
68 | panic!( | ||
69 | "\nMissing docs strings\n\n\ | ||
70 | modules:\n{}\n\n", | ||
71 | missing_docs.join("\n") | ||
72 | ) | ||
73 | } | ||
74 | |||
75 | let whitelist = [ | ||
76 | "ra_db", | ||
77 | "ra_hir", | ||
78 | "ra_hir_expand", | ||
79 | "ra_ide", | ||
80 | "ra_mbe", | ||
81 | "ra_parser", | ||
82 | "ra_prof", | ||
83 | "ra_project_model", | ||
84 | "ra_syntax", | ||
85 | "ra_text_edit", | ||
86 | "ra_tt", | ||
87 | "ra_hir_ty", | ||
88 | ]; | ||
89 | |||
90 | let mut has_fixmes = whitelist.iter().map(|it| (*it, false)).collect::<HashMap<&str, bool>>(); | ||
91 | 'outer: for path in contains_fixme { | ||
92 | for krate in whitelist.iter() { | ||
93 | if path.components().any(|it| it.as_os_str() == *krate) { | ||
94 | has_fixmes.insert(krate, true); | ||
95 | continue 'outer; | ||
96 | } | ||
97 | } | ||
98 | panic!("FIXME doc in a fully-documented crate: {}", path.display()) | ||
99 | } | ||
100 | |||
101 | for (krate, has_fixme) in has_fixmes.iter() { | ||
102 | if !has_fixme { | ||
103 | panic!("crate {} is fully documented, remove it from the white list", krate) | ||
104 | } | ||
105 | } | ||
106 | } | ||
diff --git a/xtask/tests/tidy-tests/main.rs b/xtask/tests/tidy-tests/main.rs index 56d1318d6..2d2d88bec 100644 --- a/xtask/tests/tidy-tests/main.rs +++ b/xtask/tests/tidy-tests/main.rs | |||
@@ -1,2 +1,145 @@ | |||
1 | mod cli; | 1 | mod cli; |
2 | mod docs; | 2 | |
3 | use std::{ | ||
4 | collections::HashMap, | ||
5 | path::{Path, PathBuf}, | ||
6 | }; | ||
7 | |||
8 | use walkdir::{DirEntry, WalkDir}; | ||
9 | use xtask::{not_bash::fs2, project_root}; | ||
10 | |||
11 | #[test] | ||
12 | fn rust_files_are_tidy() { | ||
13 | let mut tidy_docs = TidyDocs::default(); | ||
14 | for path in rust_files() { | ||
15 | let text = fs2::read_to_string(&path).unwrap(); | ||
16 | check_todo(&path, &text); | ||
17 | tidy_docs.visit(&path, &text); | ||
18 | } | ||
19 | tidy_docs.finish(); | ||
20 | } | ||
21 | |||
22 | fn check_todo(path: &Path, text: &str) { | ||
23 | if path.ends_with("tests/cli.rs") { | ||
24 | return; | ||
25 | } | ||
26 | if text.contains("TODO") || text.contains("TOOD") || text.contains("todo!") { | ||
27 | panic!( | ||
28 | "\nTODO markers should not be committed to the master branch,\n\ | ||
29 | use FIXME instead\n\ | ||
30 | {}\n", | ||
31 | path.display(), | ||
32 | ) | ||
33 | } | ||
34 | } | ||
35 | |||
36 | #[derive(Default)] | ||
37 | struct TidyDocs { | ||
38 | missing_docs: Vec<String>, | ||
39 | contains_fixme: Vec<PathBuf>, | ||
40 | } | ||
41 | |||
42 | impl TidyDocs { | ||
43 | fn visit(&mut self, path: &Path, text: &str) { | ||
44 | if is_exclude_dir(path) || is_exclude_file(path) { | ||
45 | return; | ||
46 | } | ||
47 | |||
48 | let first_line = match text.lines().next() { | ||
49 | Some(it) => it, | ||
50 | None => return, | ||
51 | }; | ||
52 | |||
53 | if first_line.starts_with("//!") { | ||
54 | if first_line.contains("FIXME") { | ||
55 | self.contains_fixme.push(path.to_path_buf()) | ||
56 | } | ||
57 | } else { | ||
58 | self.missing_docs.push(path.display().to_string()); | ||
59 | } | ||
60 | |||
61 | fn is_exclude_dir(p: &Path) -> bool { | ||
62 | // Test hopefully don't really need comments, and for assists we already | ||
63 | // have special comments which are source of doc tests and user docs. | ||
64 | let exclude_dirs = ["tests", "test_data", "handlers"]; | ||
65 | let mut cur_path = p; | ||
66 | while let Some(path) = cur_path.parent() { | ||
67 | if exclude_dirs.iter().any(|dir| path.ends_with(dir)) { | ||
68 | return true; | ||
69 | } | ||
70 | cur_path = path; | ||
71 | } | ||
72 | |||
73 | false | ||
74 | } | ||
75 | |||
76 | fn is_exclude_file(d: &Path) -> bool { | ||
77 | let file_names = ["tests.rs"]; | ||
78 | |||
79 | d.file_name() | ||
80 | .unwrap_or_default() | ||
81 | .to_str() | ||
82 | .map(|f_n| file_names.iter().any(|name| *name == f_n)) | ||
83 | .unwrap_or(false) | ||
84 | } | ||
85 | } | ||
86 | |||
87 | fn finish(self) { | ||
88 | if !self.missing_docs.is_empty() { | ||
89 | panic!( | ||
90 | "\nMissing docs strings\n\n\ | ||
91 | modules:\n{}\n\n", | ||
92 | self.missing_docs.join("\n") | ||
93 | ) | ||
94 | } | ||
95 | |||
96 | let whitelist = [ | ||
97 | "ra_db", | ||
98 | "ra_hir", | ||
99 | "ra_hir_expand", | ||
100 | "ra_ide", | ||
101 | "ra_mbe", | ||
102 | "ra_parser", | ||
103 | "ra_prof", | ||
104 | "ra_project_model", | ||
105 | "ra_syntax", | ||
106 | "ra_text_edit", | ||
107 | "ra_tt", | ||
108 | "ra_hir_ty", | ||
109 | ]; | ||
110 | |||
111 | let mut has_fixmes = | ||
112 | whitelist.iter().map(|it| (*it, false)).collect::<HashMap<&str, bool>>(); | ||
113 | 'outer: for path in self.contains_fixme { | ||
114 | for krate in whitelist.iter() { | ||
115 | if path.components().any(|it| it.as_os_str() == *krate) { | ||
116 | has_fixmes.insert(krate, true); | ||
117 | continue 'outer; | ||
118 | } | ||
119 | } | ||
120 | panic!("FIXME doc in a fully-documented crate: {}", path.display()) | ||
121 | } | ||
122 | |||
123 | for (krate, has_fixme) in has_fixmes.iter() { | ||
124 | if !has_fixme { | ||
125 | panic!("crate {} is fully documented, remove it from the white list", krate) | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | } | ||
130 | |||
131 | fn rust_files() -> impl Iterator<Item = PathBuf> { | ||
132 | let crates = project_root().join("crates"); | ||
133 | let iter = WalkDir::new(crates); | ||
134 | return iter | ||
135 | .into_iter() | ||
136 | .filter_entry(|e| !is_hidden(e)) | ||
137 | .map(|e| e.unwrap()) | ||
138 | .filter(|e| !e.file_type().is_dir()) | ||
139 | .map(|e| e.into_path()) | ||
140 | .filter(|path| path.extension().map(|it| it == "rs").unwrap_or(false)); | ||
141 | |||
142 | fn is_hidden(entry: &DirEntry) -> bool { | ||
143 | entry.file_name().to_str().map(|s| s.starts_with('.')).unwrap_or(false) | ||
144 | } | ||
145 | } | ||