]>
Commit | Line | Data |
---|---|---|
923072b8 FG |
1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | ||
3 | use super::utils::{show_error, TestResult}; | |
4 | use std::ffi::OsStr; | |
5 | use std::path::Path; | |
6 | ||
7 | fn to_correct_name(s: &str) -> String { | |
8 | let mut out = String::with_capacity(s.len()); | |
9 | ||
10 | for c in s.chars() { | |
11 | if c.is_uppercase() { | |
12 | if !out.is_empty() { | |
13 | out.push('_'); | |
14 | } | |
15 | out.push_str(c.to_lowercase().to_string().as_str()); | |
16 | } else { | |
17 | out.push(c); | |
18 | } | |
19 | } | |
20 | out | |
21 | } | |
22 | ||
23 | fn check_md_doc_path(p: &Path, md_line: &str, ty_line: &str) -> bool { | |
487cf647 | 24 | let parts = md_line.split('/').collect::<Vec<_>>(); |
923072b8 | 25 | if let Some(md_name) = parts.last().and_then(|n| n.split(".md").next()) { |
487cf647 | 26 | if let Some(name) = ty_line.split_whitespace().filter(|s| !s.is_empty()).nth(2) { |
923072b8 FG |
27 | if let Some(name) = name |
28 | .split('<') | |
29 | .next() | |
30 | .and_then(|n| n.split('{').next()) | |
31 | .and_then(|n| n.split('(').next()) | |
32 | .and_then(|n| n.split(';').next()) | |
33 | { | |
34 | let correct = to_correct_name(name); | |
35 | if correct.as_str() == md_name { | |
36 | return true; | |
37 | } | |
38 | show_error( | |
39 | p, | |
40 | &format!( | |
add651ee | 41 | "Invalid markdown file name `{md_name}`, should have been `{correct}`", |
923072b8 FG |
42 | ), |
43 | ); | |
44 | return false; | |
45 | } | |
46 | } | |
487cf647 | 47 | show_error(p, &format!("Cannot extract type name from `{ty_line}`")); |
923072b8 | 48 | } else { |
487cf647 | 49 | show_error(p, &format!("Cannot extract md name from `{md_line}`")); |
923072b8 | 50 | } |
487cf647 | 51 | false |
923072b8 FG |
52 | } |
53 | ||
54 | fn check_doc_comments_before(p: &Path, lines: &[&str], start: usize) -> bool { | |
55 | let mut found_docs = false; | |
56 | ||
57 | for pos in (0..start).rev() { | |
58 | let trimmed = lines[pos].trim(); | |
59 | if trimmed.starts_with("///") { | |
60 | if !lines[start].trim().starts_with("pub enum ThreadStatus {") { | |
61 | show_error( | |
62 | p, | |
63 | &format!( | |
64 | "Types should use common documentation by using `#[doc = include_str!(` \ | |
65 | and by putting the markdown file in the `md_doc` folder instead of `{}`", | |
66 | &lines[pos], | |
67 | ), | |
68 | ); | |
69 | return false; | |
70 | } | |
71 | return true; | |
72 | } else if trimmed.starts_with("#[doc = include_str!(") { | |
73 | found_docs = true; | |
74 | if !check_md_doc_path(p, trimmed, lines[start]) { | |
75 | return false; | |
76 | } | |
77 | } else if !trimmed.starts_with("#[") && !trimmed.starts_with("//") { | |
78 | break; | |
79 | } | |
80 | } | |
81 | if !found_docs { | |
82 | show_error( | |
83 | p, | |
84 | &format!( | |
85 | "Missing documentation for public item: `{}` (if it's not supposed to be a public \ | |
86 | item, use `pub(crate)` instead)", | |
87 | lines[start], | |
88 | ), | |
89 | ); | |
90 | return false; | |
91 | } | |
92 | true | |
93 | } | |
94 | ||
95 | pub fn check_docs(content: &str, p: &Path) -> TestResult { | |
96 | let mut res = TestResult { | |
97 | nb_tests: 0, | |
98 | nb_errors: 0, | |
99 | }; | |
100 | ||
101 | // No need to check if we are in the `src` folder or if we are in a `ffi.rs` file. | |
102 | if p.parent().unwrap().file_name().unwrap() == OsStr::new("src") | |
103 | || p.file_name().unwrap() == OsStr::new("ffi.rs") | |
104 | { | |
105 | return res; | |
106 | } | |
107 | let lines = content.lines().collect::<Vec<_>>(); | |
108 | ||
109 | for pos in 1..lines.len() { | |
110 | let line = lines[pos]; | |
111 | let trimmed = line.trim(); | |
112 | if trimmed.starts_with("//!") { | |
113 | show_error(p, "There shouln't be inner doc comments (`//!`)"); | |
114 | res.nb_tests += 1; | |
115 | res.nb_errors += 1; | |
116 | continue; | |
117 | } else if !line.starts_with("pub fn ") | |
118 | && !trimmed.starts_with("pub struct ") | |
119 | && !trimmed.starts_with("pub enum ") | |
120 | { | |
121 | continue; | |
122 | } | |
123 | res.nb_tests += 1; | |
124 | if !check_doc_comments_before(p, &lines, pos) { | |
125 | res.nb_errors += 1; | |
126 | } | |
127 | } | |
128 | res | |
129 | } |