Skip to content

Commit 9b3c732

Browse files
Docs: Link inline settings when not part of options section (#10499)
## Summary Some contributors have referenced settings in their documentation without adding the settings to an options section, this has lead to some rendering issues (#10427). This PR addresses this looking for potential inline links to settings, cross-checking them with the options sections, and then linking them anyway if they are not found. Resolves #10427. ## Test Plan Manually verified that the correct modifications were made and no docs were broken.
1 parent caa1450 commit 9b3c732

File tree

1 file changed

+22
-4
lines changed

1 file changed

+22
-4
lines changed

crates/ruff_dev/src/generate_docs.rs

+22-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Generate Markdown documentation for applicable rules.
22
#![allow(clippy::print_stdout, clippy::print_stderr)]
33

4+
use std::collections::HashSet;
45
use std::fs;
56
use std::path::PathBuf;
67

@@ -97,20 +98,22 @@ pub(crate) fn main(args: &Args) -> Result<()> {
9798
fn process_documentation(documentation: &str, out: &mut String, rule_name: &str) {
9899
let mut in_options = false;
99100
let mut after = String::new();
101+
let mut referenced_options = HashSet::new();
100102

101103
// HACK: This is an ugly regex hack that's necessary because mkdocs uses
102104
// a non-CommonMark-compliant Markdown parser, which doesn't support code
103105
// tags in link definitions
104106
// (see https://github.com/Python-Markdown/markdown/issues/280).
105-
let documentation = Regex::new(r"\[`([^`]*?)`]($|[^\[\(])")
106-
.unwrap()
107-
.replace_all(documentation, |caps: &Captures| {
107+
let documentation = Regex::new(r"\[`([^`]*?)`]($|[^\[(])").unwrap().replace_all(
108+
documentation,
109+
|caps: &Captures| {
108110
format!(
109111
"[`{option}`][{option}]{sep}",
110112
option = &caps[1],
111113
sep = &caps[2]
112114
)
113-
});
115+
},
116+
);
114117

115118
for line in documentation.split_inclusive('\n') {
116119
if line.starts_with("## ") {
@@ -134,13 +137,28 @@ fn process_documentation(documentation: &str, out: &mut String, rule_name: &str)
134137
let anchor = option.replace('.', "_");
135138
out.push_str(&format!("- [`{option}`][{option}]\n"));
136139
after.push_str(&format!("[{option}]: ../settings.md#{anchor}\n"));
140+
referenced_options.insert(option);
137141

138142
continue;
139143
}
140144
}
141145

142146
out.push_str(line);
143147
}
148+
149+
let re = Regex::new(r"\[`([^`]*?)`]\[(.*?)]").unwrap();
150+
for (_, [option, _]) in re.captures_iter(&documentation).map(|c| c.extract()) {
151+
if let Some(OptionEntry::Field(field)) = Options::metadata().find(option) {
152+
if referenced_options.insert(option) {
153+
let anchor = option.replace('.', "_");
154+
after.push_str(&format!("[{option}]: ../settings.md#{anchor}\n"));
155+
}
156+
if field.deprecated.is_some() {
157+
eprintln!("Rule {rule_name} references deprecated option {option}.");
158+
}
159+
}
160+
}
161+
144162
if !after.is_empty() {
145163
out.push('\n');
146164
out.push('\n');

0 commit comments

Comments
 (0)