11//! Checks that all Flunt files have messages in alphabetical order
22
33use crate :: walk:: { filter_dirs, walk} ;
4+ use std:: collections:: HashMap ;
45use std:: { fs:: OpenOptions , io:: Write , path:: Path } ;
56
67use regex:: Regex ;
@@ -13,11 +14,27 @@ fn filter_fluent(path: &Path) -> bool {
1314 if let Some ( ext) = path. extension ( ) { ext. to_str ( ) != Some ( "ftl" ) } else { true }
1415}
1516
16- fn check_alphabetic ( filename : & str , fluent : & str , bad : & mut bool ) {
17+ fn check_alphabetic (
18+ filename : & str ,
19+ fluent : & str ,
20+ bad : & mut bool ,
21+ all_defined_msgs : & mut HashMap < String , String > ,
22+ ) {
1723 let mut matches = MESSAGE . captures_iter ( fluent) . peekable ( ) ;
1824 while let Some ( m) = matches. next ( ) {
25+ let name = m. get ( 1 ) . unwrap ( ) ;
26+ if let Some ( defined_filename) = all_defined_msgs. get ( name. as_str ( ) ) {
27+ tidy_error ! (
28+ bad,
29+ "{filename}: message `{}` is already defined in {}" ,
30+ name. as_str( ) ,
31+ defined_filename,
32+ ) ;
33+ }
34+
35+ all_defined_msgs. insert ( name. as_str ( ) . to_owned ( ) , filename. to_owned ( ) ) ;
36+
1937 if let Some ( next) = matches. peek ( ) {
20- let name = m. get ( 1 ) . unwrap ( ) ;
2138 let next = next. get ( 1 ) . unwrap ( ) ;
2239 if name. as_str ( ) > next. as_str ( ) {
2340 tidy_error ! (
@@ -34,13 +51,29 @@ run `./x.py test tidy --bless` to sort the file correctly",
3451 }
3552}
3653
37- fn sort_messages ( fluent : & str ) -> String {
54+ fn sort_messages (
55+ filename : & str ,
56+ fluent : & str ,
57+ bad : & mut bool ,
58+ all_defined_msgs : & mut HashMap < String , String > ,
59+ ) -> String {
3860 let mut chunks = vec ! [ ] ;
3961 let mut cur = String :: new ( ) ;
4062 for line in fluent. lines ( ) {
41- if MESSAGE . is_match ( line) {
63+ if let Some ( name) = MESSAGE . find ( line) {
64+ if let Some ( defined_filename) = all_defined_msgs. get ( name. as_str ( ) ) {
65+ tidy_error ! (
66+ bad,
67+ "{filename}: message `{}` is already defined in {}" ,
68+ name. as_str( ) ,
69+ defined_filename,
70+ ) ;
71+ }
72+
73+ all_defined_msgs. insert ( name. as_str ( ) . to_owned ( ) , filename. to_owned ( ) ) ;
4274 chunks. push ( std:: mem:: take ( & mut cur) ) ;
4375 }
76+
4477 cur += line;
4578 cur. push ( '\n' ) ;
4679 }
@@ -53,20 +86,33 @@ fn sort_messages(fluent: &str) -> String {
5386}
5487
5588pub fn check ( path : & Path , bless : bool , bad : & mut bool ) {
89+ let mut all_defined_msgs = HashMap :: new ( ) ;
5690 walk (
5791 path,
5892 |path, is_dir| filter_dirs ( path) || ( !is_dir && filter_fluent ( path) ) ,
5993 & mut |ent, contents| {
6094 if bless {
61- let sorted = sort_messages ( contents) ;
95+ let sorted = sort_messages (
96+ ent. path ( ) . to_str ( ) . unwrap ( ) ,
97+ contents,
98+ bad,
99+ & mut all_defined_msgs,
100+ ) ;
62101 if sorted != contents {
63102 let mut f =
64103 OpenOptions :: new ( ) . write ( true ) . truncate ( true ) . open ( ent. path ( ) ) . unwrap ( ) ;
65104 f. write ( sorted. as_bytes ( ) ) . unwrap ( ) ;
66105 }
67106 } else {
68- check_alphabetic ( ent. path ( ) . to_str ( ) . unwrap ( ) , contents, bad) ;
107+ check_alphabetic (
108+ ent. path ( ) . to_str ( ) . unwrap ( ) ,
109+ contents,
110+ bad,
111+ & mut all_defined_msgs,
112+ ) ;
69113 }
70114 } ,
71115 ) ;
116+
117+ crate :: fluent_used:: check ( path, all_defined_msgs, bad) ;
72118}
0 commit comments