Skip to content

Commit 7ce7eb8

Browse files
committed
Resolve linter violations.
1 parent 958f415 commit 7ce7eb8

File tree

1 file changed

+61
-48
lines changed

1 file changed

+61
-48
lines changed

crates/oxc_linter/tests/rule_configuration_documentation_test.rs

Lines changed: 61 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,49 @@
66
77
#![cfg(feature = "ruledocs")]
88

9+
use cow_utils::CowUtils;
10+
use rustc_hash::FxHashSet;
11+
12+
// Recursively scan rule files
13+
fn scan_rules_dir(
14+
dir: &std::path::Path,
15+
base_dir: &std::path::Path,
16+
results: &mut Vec<String>,
17+
) -> std::io::Result<()> {
18+
for entry in std::fs::read_dir(dir)? {
19+
let entry = entry?;
20+
let path = entry.path();
21+
22+
if path.is_dir() {
23+
scan_rules_dir(&path, base_dir, results)?;
24+
} else if path.extension().and_then(|s| s.to_str()) == Some("rs") {
25+
let content = std::fs::read_to_string(&path)?;
26+
27+
let has_declare_lint = content.contains("declare_oxc_lint!(");
28+
let has_from_config = content.contains("fn from_configuration(");
29+
// Look for "config =" as a parameter in declare_oxc_lint macro
30+
// Use regex to be more precise
31+
let has_config_param = content.contains("declare_oxc_lint!")
32+
&& content.split("declare_oxc_lint!").any(|section| {
33+
// Check if this section (after declare_oxc_lint!) contains "config ="
34+
// before the closing of the macro (the semicolon after the paren)
35+
if let Some(macro_end) = section.find(");") {
36+
let macro_content = &section[..macro_end];
37+
macro_content.contains("config =")
38+
} else {
39+
false
40+
}
41+
});
42+
43+
if has_declare_lint && has_from_config && !has_config_param {
44+
let rel_path = path.strip_prefix(base_dir).unwrap();
45+
results.push(rel_path.to_string_lossy().to_string());
46+
}
47+
}
48+
}
49+
Ok(())
50+
}
51+
952
/// Test to ensure that all rules with `from_configuration` implementations
1053
/// also have a schema and proper documentation.
1154
///
@@ -75,7 +118,7 @@ fn test_rules_with_custom_configuration_have_schema() {
75118
"vue/define-props-declaration",
76119
];
77120

78-
let exception_set: std::collections::HashSet<&str> = exceptions.iter().copied().collect();
121+
let exception_set: FxHashSet<&str> = exceptions.iter().copied().collect();
79122

80123
// Step 1: Scan source code to find rules with from_configuration but no config =
81124
let workspace_root =
@@ -84,46 +127,6 @@ fn test_rules_with_custom_configuration_have_schema() {
84127

85128
let mut rules_with_from_config_no_schema = Vec::new();
86129

87-
// Recursively scan rule files
88-
fn scan_rules_dir(
89-
dir: &std::path::Path,
90-
base_dir: &std::path::Path,
91-
results: &mut Vec<String>,
92-
) -> std::io::Result<()> {
93-
for entry in std::fs::read_dir(dir)? {
94-
let entry = entry?;
95-
let path = entry.path();
96-
97-
if path.is_dir() {
98-
scan_rules_dir(&path, base_dir, results)?;
99-
} else if path.extension().and_then(|s| s.to_str()) == Some("rs") {
100-
let content = std::fs::read_to_string(&path)?;
101-
102-
let has_declare_lint = content.contains("declare_oxc_lint!(");
103-
let has_from_config = content.contains("fn from_configuration(");
104-
// Look for "config =" as a parameter in declare_oxc_lint macro
105-
// Use regex to be more precise
106-
let has_config_param = content.contains("declare_oxc_lint!")
107-
&& content.split("declare_oxc_lint!").any(|section| {
108-
// Check if this section (after declare_oxc_lint!) contains "config ="
109-
// before the closing of the macro (the semicolon after the paren)
110-
if let Some(macro_end) = section.find(");") {
111-
let macro_content = &section[..macro_end];
112-
macro_content.contains("config =")
113-
} else {
114-
false
115-
}
116-
});
117-
118-
if has_declare_lint && has_from_config && !has_config_param {
119-
let rel_path = path.strip_prefix(base_dir).unwrap();
120-
results.push(rel_path.to_string_lossy().to_string());
121-
}
122-
}
123-
}
124-
Ok(())
125-
}
126-
127130
scan_rules_dir(&rules_dir, &rules_dir, &mut rules_with_from_config_no_schema)
128131
.expect("Failed to scan rules directory");
129132

@@ -133,7 +136,11 @@ fn test_rules_with_custom_configuration_have_schema() {
133136
.filter_map(|path| {
134137
// Path format: "plugin/rule_file.rs" or "plugin/rule_name/mod.rs"
135138
// Always use '/' as separator regardless of OS
136-
let normalized_path = path.replace(std::path::MAIN_SEPARATOR, "/");
139+
let normalized_path = if std::path::MAIN_SEPARATOR == '/' {
140+
path.as_str()
141+
} else {
142+
&path.cow_replace(std::path::MAIN_SEPARATOR, "/")
143+
};
137144
let parts: Vec<&str> = normalized_path.split('/').collect();
138145
if parts.len() >= 2 {
139146
let plugin = parts[0];
@@ -145,8 +152,12 @@ fn test_rules_with_custom_configuration_have_schema() {
145152
parts[1]
146153
};
147154
// Convert underscores to hyphens for rule name
148-
let rule_name = rule_file.replace('_', "-");
149-
Some(format!("{}/{}", plugin, rule_name))
155+
let rule_name = if rule_file.contains('_') {
156+
rule_file.cow_replace('_', "-").into_owned()
157+
} else {
158+
rule_file.to_string()
159+
};
160+
Some(format!("{plugin}/{rule_name}"))
150161
} else {
151162
None
152163
}
@@ -184,9 +195,11 @@ fn test_rules_with_custom_configuration_have_schema() {
184195
.output()
185196
.expect("Failed to generate documentation");
186197

187-
if !output.status.success() {
188-
panic!("Failed to generate documentation:\n{}", String::from_utf8_lossy(&output.stderr));
189-
}
198+
assert!(
199+
output.status.success(),
200+
"Failed to generate documentation:\n{}",
201+
String::from_utf8_lossy(&output.stderr)
202+
);
190203

191204
// Step 3: Check generated documentation for Configuration sections
192205
for rule_name in &rules_needing_schema {
@@ -196,7 +209,7 @@ fn test_rules_with_custom_configuration_have_schema() {
196209
}
197210

198211
// Read the generated markdown file
199-
let doc_file = temp_dir.join(format!("{}.md", rule_name));
212+
let doc_file = temp_dir.join(format!("{rule_name}.md"));
200213

201214
if !doc_file.exists() {
202215
failures.push(format!(

0 commit comments

Comments
 (0)