about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-10 11:58:22 +0000
committerbors <bors@rust-lang.org>2024-03-10 11:58:22 +0000
commitcdb775cab50311de54ccf3a07b331cc56b0da436 (patch)
tree61b9445089119b702bf56860884ff871dfd6b893 /src/tools
parent3521a2f2f317cb978063842485c7d1bc86ec82b6 (diff)
parent9d03046a8185dfa103a47ba41f1d70438b407375 (diff)
downloadrust-cdb775cab50311de54ccf3a07b331cc56b0da436.tar.gz
rust-cdb775cab50311de54ccf3a07b331cc56b0da436.zip
Auto merge of #122283 - matthiaskrgr:rollup-w3sau3u, r=matthiaskrgr
Rollup of 14 pull requests

Successful merges:

 - #112136 (Add std::ffi::c_str module)
 - #113525 (Dynamically size sigaltstk in std)
 - #121567 (Avoid some interning in bootstrap)
 - #121642 (Update a test to support Symbol Mangling V0)
 - #121685 (Fixing shellcheck comments on lvi test script)
 - #121860 (Add a tidy check that checks whether the fluent slugs only appear once)
 - #121942 (std::rand: enable getrandom for dragonflybsd too.)
 - #122125 (Revert back to Git-for-Windows for MinGW CI builds)
 - #122221 (match lowering: define a convenient struct)
 - #122244 (fix: LocalWaker memory leak and some stability attributes)
 - #122251 (Add test to check unused_lifetimes don't duplicate "parameter is never used" error)
 - #122264 (add myself to rotation)
 - #122269 (doc/rustc: Move loongarch64-unknown-linux-musl to Tier 3)
 - #122271 (Fix legacy numeric constant diag items)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/tidy/src/fluent_alphabetical.rs58
-rw-r--r--src/tools/tidy/src/fluent_used.rs43
-rw-r--r--src/tools/tidy/src/lib.rs1
3 files changed, 96 insertions, 6 deletions
diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs
index 67b745373f0..9803b6eab2d 100644
--- a/src/tools/tidy/src/fluent_alphabetical.rs
+++ b/src/tools/tidy/src/fluent_alphabetical.rs
@@ -1,6 +1,7 @@
 //! Checks that all Flunt files have messages in alphabetical order
 
 use crate::walk::{filter_dirs, walk};
+use std::collections::HashMap;
 use std::{fs::OpenOptions, io::Write, path::Path};
 
 use regex::Regex;
@@ -13,11 +14,27 @@ fn filter_fluent(path: &Path) -> bool {
     if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true }
 }
 
-fn check_alphabetic(filename: &str, fluent: &str, bad: &mut bool) {
+fn check_alphabetic(
+    filename: &str,
+    fluent: &str,
+    bad: &mut bool,
+    all_defined_msgs: &mut HashMap<String, String>,
+) {
     let mut matches = MESSAGE.captures_iter(fluent).peekable();
     while let Some(m) = matches.next() {
+        let name = m.get(1).unwrap();
+        if let Some(defined_filename) = all_defined_msgs.get(name.as_str()) {
+            tidy_error!(
+                bad,
+                "{filename}: message `{}` is already defined in {}",
+                name.as_str(),
+                defined_filename,
+            );
+        }
+
+        all_defined_msgs.insert(name.as_str().to_owned(), filename.to_owned());
+
         if let Some(next) = matches.peek() {
-            let name = m.get(1).unwrap();
             let next = next.get(1).unwrap();
             if name.as_str() > next.as_str() {
                 tidy_error!(
@@ -34,13 +51,29 @@ run `./x.py test tidy --bless` to sort the file correctly",
     }
 }
 
-fn sort_messages(fluent: &str) -> String {
+fn sort_messages(
+    filename: &str,
+    fluent: &str,
+    bad: &mut bool,
+    all_defined_msgs: &mut HashMap<String, String>,
+) -> String {
     let mut chunks = vec![];
     let mut cur = String::new();
     for line in fluent.lines() {
-        if MESSAGE.is_match(line) {
+        if let Some(name) = MESSAGE.find(line) {
+            if let Some(defined_filename) = all_defined_msgs.get(name.as_str()) {
+                tidy_error!(
+                    bad,
+                    "{filename}: message `{}` is already defined in {}",
+                    name.as_str(),
+                    defined_filename,
+                );
+            }
+
+            all_defined_msgs.insert(name.as_str().to_owned(), filename.to_owned());
             chunks.push(std::mem::take(&mut cur));
         }
+
         cur += line;
         cur.push('\n');
     }
@@ -53,20 +86,33 @@ fn sort_messages(fluent: &str) -> String {
 }
 
 pub fn check(path: &Path, bless: bool, bad: &mut bool) {
+    let mut all_defined_msgs = HashMap::new();
     walk(
         path,
         |path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)),
         &mut |ent, contents| {
             if bless {
-                let sorted = sort_messages(contents);
+                let sorted = sort_messages(
+                    ent.path().to_str().unwrap(),
+                    contents,
+                    bad,
+                    &mut all_defined_msgs,
+                );
                 if sorted != contents {
                     let mut f =
                         OpenOptions::new().write(true).truncate(true).open(ent.path()).unwrap();
                     f.write(sorted.as_bytes()).unwrap();
                 }
             } else {
-                check_alphabetic(ent.path().to_str().unwrap(), contents, bad);
+                check_alphabetic(
+                    ent.path().to_str().unwrap(),
+                    contents,
+                    bad,
+                    &mut all_defined_msgs,
+                );
             }
         },
     );
+
+    crate::fluent_used::check(path, all_defined_msgs, bad);
 }
diff --git a/src/tools/tidy/src/fluent_used.rs b/src/tools/tidy/src/fluent_used.rs
new file mode 100644
index 00000000000..b73e79cb38d
--- /dev/null
+++ b/src/tools/tidy/src/fluent_used.rs
@@ -0,0 +1,43 @@
+//! Checks that all Fluent messages appear at least twice
+
+use crate::walk::{filter_dirs, walk};
+use regex::Regex;
+use std::collections::HashMap;
+use std::path::Path;
+
+lazy_static::lazy_static! {
+    static ref WORD: Regex = Regex::new(r"\w+").unwrap();
+}
+
+fn filter_used_messages(
+    contents: &str,
+    msgs_not_appeared_yet: &mut HashMap<String, String>,
+    msgs_appeared_only_once: &mut HashMap<String, String>,
+) {
+    // we don't just check messages never appear in Rust files,
+    // because messages can be used as parts of other fluent messages in Fluent files,
+    // so we do checking messages appear only once in all Rust and Fluent files.
+    let mut matches = WORD.find_iter(contents);
+    while let Some(name) = matches.next() {
+        if let Some((name, filename)) = msgs_not_appeared_yet.remove_entry(name.as_str()) {
+            // if one msg appears for the first time,
+            // remove it from `msgs_not_appeared_yet` and insert it into `msgs_appeared_only_once`.
+            msgs_appeared_only_once.insert(name, filename);
+        } else {
+            // if one msg appears for the second time,
+            // remove it from `msgs_appeared_only_once`.
+            msgs_appeared_only_once.remove(name.as_str());
+        }
+    }
+}
+
+pub fn check(path: &Path, mut all_defined_msgs: HashMap<String, String>, bad: &mut bool) {
+    let mut msgs_appear_only_once = HashMap::new();
+    walk(path, |path, _| filter_dirs(path), &mut |_, contents| {
+        filter_used_messages(contents, &mut all_defined_msgs, &mut msgs_appear_only_once);
+    });
+
+    for (name, filename) in msgs_appear_only_once {
+        tidy_error!(bad, "{filename}: message `{}` is not used", name,);
+    }
+}
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 6f3ade0ab58..670b7eb2be9 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -65,6 +65,7 @@ pub mod ext_tool_checks;
 pub mod extdeps;
 pub mod features;
 pub mod fluent_alphabetical;
+mod fluent_used;
 pub(crate) mod iter_header;
 pub mod mir_opt_tests;
 pub mod pal;