about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNilstrieb <48135649+Nilstrieb@users.noreply.github.com>2022-10-04 22:34:07 +0200
committerDylan DPC <dylan.dpc@gmail.com>2022-10-12 17:48:20 +0530
commit0e3867338d66a016d6e6214a18537fbb715ed752 (patch)
tree211213a55e8d86da175a2ccc642804f7d75c56ff
parente6ce5627a9e8af9ae4673a390954fffaf526e5cc (diff)
downloadrust-0e3867338d66a016d6e6214a18537fbb715ed752.tar.gz
rust-0e3867338d66a016d6e6214a18537fbb715ed752.zip
Add tidy directoy `tidy-alphabetical`
It can be used to ensure that a list of things is sorted alphabetically.
It goes off lines, but contains several heuristics to work with normal
Rust code (looking at indentation, ignoring comments and attributes).
-rw-r--r--src/tools/tidy/src/alphabetical.rs98
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs2
3 files changed, 101 insertions, 0 deletions
diff --git a/src/tools/tidy/src/alphabetical.rs b/src/tools/tidy/src/alphabetical.rs
new file mode 100644
index 00000000000..e02b2d98f42
--- /dev/null
+++ b/src/tools/tidy/src/alphabetical.rs
@@ -0,0 +1,98 @@
+//! Checks that a list of items is in alphabetical order
+//!
+//! To use, use the following annotation in the code:
+//! ```rust
+//! // tidy-alphabetical-start
+//! fn aaa() {}
+//! fn eee() {}
+//! fn z() {}
+//! // tidy-alphabetical-end
+//! ```
+//!
+//! The following lines are ignored:
+//! - Lines that are indented with more or less spaces than the first line
+//! - Lines starting with `//`, `#[`, `)`, `]`, `}` if the comment has the same indentation as
+//!   the first line
+//!
+//! If a line ends with an opening bracket, the line is ignored and the next line will have
+//! its extra indentation ignored.
+
+use std::{fmt::Display, path::Path};
+
+use crate::walk::{filter_dirs, walk};
+
+fn indentation(line: &str) -> usize {
+    line.find(|c| c != ' ').unwrap_or(0)
+}
+
+fn is_close_bracket(c: char) -> bool {
+    matches!(c, ')' | ']' | '}')
+}
+
+fn check_section<'a>(
+    file: impl Display,
+    lines: impl Iterator<Item = (usize, &'a str)>,
+    bad: &mut bool,
+) {
+    let content_lines = lines.take_while(|(_, line)| !line.contains("// tidy-alphabetical-end"));
+
+    let mut prev_line = String::new();
+    let mut first_indent = None;
+    let mut in_split_line = None;
+
+    for (line_idx, line) in content_lines {
+        let indent = first_indent.unwrap_or_else(|| {
+            let indent = indentation(line);
+            first_indent = Some(indent);
+            indent
+        });
+
+        let line = if let Some(prev_split_line) = in_split_line {
+            in_split_line = None;
+            format!("{prev_split_line}{}", line.trim_start())
+        } else {
+            line.to_string()
+        };
+
+        if indentation(&line) != indent {
+            continue;
+        }
+
+        let trimmed_line = line.trim_start_matches(' ');
+
+        if trimmed_line.starts_with("//")
+            || trimmed_line.starts_with("#[")
+            || trimmed_line.starts_with(is_close_bracket)
+        {
+            continue;
+        }
+
+        if line.trim_end().ends_with('(') {
+            in_split_line = Some(line);
+            continue;
+        }
+
+        let prev_line_trimmed_lowercase = prev_line.trim_start_matches(' ').to_lowercase();
+
+        if trimmed_line.to_lowercase() < prev_line_trimmed_lowercase {
+            tidy_error!(bad, "{file}:{}: line not in alphabetical order", line_idx + 1,);
+        }
+
+        prev_line = line;
+    }
+}
+
+const START_COMMENT: &str = "// tidy-alphabetical-start";
+
+pub fn check(path: &Path, bad: &mut bool) {
+    walk(path, &mut filter_dirs, &mut |entry, contents| {
+        let file = &entry.path().display();
+
+        let mut lines = contents.lines().enumerate();
+        while let Some((_, line)) = lines.next() {
+            if line.contains(START_COMMENT) {
+                check_section(file, &mut lines, bad);
+            }
+        }
+    });
+}
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index e82cca402e2..fc0bce58572 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -38,6 +38,7 @@ macro_rules! tidy_error {
     });
 }
 
+pub mod alphabetical;
 pub mod bins;
 pub mod debug_artifacts;
 pub mod deps;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index c1ce94f4705..8fe361c45a2 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -90,6 +90,8 @@ fn main() {
         check!(edition, &compiler_path);
         check!(edition, &library_path);
 
+        check!(alphabetical, &compiler_path);
+
         let collected = {
             while handles.len() >= concurrency.get() {
                 handles.pop_front().unwrap().join().unwrap();