@@ -17,13 +17,28 @@ use pest::unicode::unicode_property_names;
1717use pest_meta:: ast:: * ;
1818use pest_meta:: optimizer:: * ;
1919
20- pub fn generate (
20+ #[ derive( Debug ) ]
21+ pub ( crate ) struct DocComment < ' a > {
22+ pub ( crate ) grammar_docs : Vec < & ' a str > ,
23+ pub ( crate ) line_docs : Vec < Vec < & ' a str > > ,
24+ pub ( crate ) rules : Vec < Rule > ,
25+ }
26+
27+ impl DocComment < ' _ > {
28+ fn line_docs_for_rule ( & self , rule_name : & str ) -> Option < String > {
29+ let idx = self . rules . iter ( ) . position ( |r| r. name == rule_name) ?;
30+
31+ self . line_docs . get ( idx) . map ( |comments| comments. join ( "\n " ) )
32+ }
33+ }
34+
35+ pub ( crate ) fn generate (
2136 name : Ident ,
2237 generics : & Generics ,
2338 path : Option < PathBuf > ,
2439 rules : Vec < OptimizedRule > ,
2540 defaults : Vec < & str > ,
26- grammar_docs : Vec < & str > ,
41+ doc_comment : & DocComment < ' _ > ,
2742 include_grammar : bool ,
2843) -> TokenStream {
2944 let uses_eoi = defaults. iter ( ) . any ( |name| * name == "EOI" ) ;
@@ -37,7 +52,7 @@ pub fn generate(
3752 } else {
3853 quote ! ( )
3954 } ;
40- let rule_enum = generate_enum ( & rules, grammar_docs , uses_eoi) ;
55+ let rule_enum = generate_enum ( & rules, doc_comment , uses_eoi) ;
4156 let patterns = generate_patterns ( & rules, uses_eoi) ;
4257 let skip = generate_skip ( & rules) ;
4358
@@ -182,23 +197,29 @@ fn generate_include(name: &Ident, path: &str) -> TokenStream {
182197 }
183198}
184199
185- fn generate_enum ( rules : & [ OptimizedRule ] , grammar_docs : Vec < & str > , uses_eoi : bool ) -> TokenStream {
200+ fn generate_enum (
201+ rules : & [ OptimizedRule ] ,
202+ doc_comment : & DocComment < ' _ > ,
203+ uses_eoi : bool ,
204+ ) -> TokenStream {
186205 let rules = rules. iter ( ) . map ( |rule| {
187206 let rule_name = format_ident ! ( "r#{}" , rule. name) ;
188- if rule. comments . is_empty ( ) {
207+
208+ let comments = doc_comment. line_docs_for_rule ( & rule. name ) ;
209+ let comments = comments. unwrap_or_else ( || "" . to_owned ( ) ) ;
210+ if comments. is_empty ( ) {
189211 quote ! {
190212 #rule_name
191213 }
192214 } else {
193- let comments = rule. comments . join ( "\n " ) ;
194215 quote ! {
195216 #[ doc = #comments]
196217 #rule_name
197218 }
198219 }
199220 } ) ;
200221
201- let grammar_docs = grammar_docs. join ( "\n " ) ;
222+ let grammar_docs = doc_comment . grammar_docs . join ( "\n " ) ;
202223 if uses_eoi {
203224 quote ! {
204225 #[ doc = #grammar_docs]
@@ -686,11 +707,20 @@ mod tests {
686707 name: "f" . to_owned( ) ,
687708 ty: RuleType :: Normal ,
688709 expr: OptimizedExpr :: Ident ( "g" . to_owned( ) ) ,
689- comments: vec![ "This is rule comment" . to_owned( ) ] ,
690710 } ] ;
691711
712+ let doc_comment = & DocComment {
713+ grammar_docs : vec ! [ "Rule doc" , "hello" ] ,
714+ line_docs : vec ! [ vec![ "This is rule comment" ] ] ,
715+ rules : vec ! [ Rule {
716+ name: "f" . to_owned( ) ,
717+ ty: RuleType :: Normal ,
718+ expr: Expr :: Ident ( "g" . to_owned( ) ) ,
719+ } ] ,
720+ } ;
721+
692722 assert_eq ! (
693- generate_enum( & rules, vec! [ "Rule doc" , "hello" ] , false ) . to_string( ) ,
723+ generate_enum( & rules, doc_comment , false ) . to_string( ) ,
694724 quote! {
695725 #[ doc = "Rule doc\n hello" ]
696726 #[ allow( dead_code, non_camel_case_types, clippy:: upper_case_acronyms) ]
@@ -988,24 +1018,39 @@ mod tests {
9881018 name: "a" . to_owned( ) ,
9891019 ty: RuleType :: Silent ,
9901020 expr: OptimizedExpr :: Str ( "b" . to_owned( ) ) ,
991- comments: vec![ ] ,
9921021 } ,
9931022 OptimizedRule {
9941023 name: "if" . to_owned( ) ,
9951024 ty: RuleType :: Silent ,
9961025 expr: OptimizedExpr :: Ident ( "a" . to_owned( ) ) ,
997- comments: vec![ "If statement" . to_owned( ) ] ,
9981026 } ,
9991027 ] ;
10001028
1029+ let doc_comment = & DocComment {
1030+ line_docs : vec ! [ vec![ ] , vec![ "If statement" ] ] ,
1031+ grammar_docs : vec ! [ "This is Rule doc" , "This is second line" ] ,
1032+ rules : vec ! [
1033+ Rule {
1034+ name: "a" . to_owned( ) ,
1035+ ty: RuleType :: Silent ,
1036+ expr: Expr :: Str ( "b" . to_owned( ) ) ,
1037+ } ,
1038+ Rule {
1039+ name: "if" . to_owned( ) ,
1040+ ty: RuleType :: Silent ,
1041+ expr: Expr :: Str ( "b" . to_owned( ) ) ,
1042+ } ,
1043+ ] ,
1044+ } ;
1045+
10011046 let defaults = vec ! [ "ANY" ] ;
10021047 let result = result_type ( ) ;
10031048 let box_ty = box_type ( ) ;
10041049 let mut current_dir = std:: env:: current_dir ( ) . expect ( "Unable to get current directory" ) ;
10051050 current_dir. push ( "test.pest" ) ;
10061051 let test_path = current_dir. to_str ( ) . expect ( "path contains invalid unicode" ) ;
10071052 assert_eq ! (
1008- generate( name, & generics, Some ( PathBuf :: from( "test.pest" ) ) , rules, defaults, vec! [ "This is Rule doc" , "This is second line" ] , true ) . to_string( ) ,
1053+ generate( name, & generics, Some ( PathBuf :: from( "test.pest" ) ) , rules, defaults, doc_comment , true ) . to_string( ) ,
10091054 quote! {
10101055 #[ allow( non_upper_case_globals) ]
10111056 const _PEST_GRAMMAR_MyParser: & ' static str = include_str!( #test_path) ;
0 commit comments