@@ -242,20 +242,9 @@ where
242242 show_warnings : bool ,
243243 visibility : Visibility ,
244244 rust_edition : RustEdition ,
245- lexer_path : Option < PathBuf > ,
246- // We want lifetimes that imply the callback can't capture the header or the grammar.
247- inspect_callback : Option <
248- Box <
249- dyn for < ' y > Fn (
250- & ' y mut Header ,
251- RecoveryKind ,
252- & ' y YaccGrammar < LexerTypesT :: StorageT > ,
253- & ' y StateTable < LexerTypesT :: StorageT > ,
254- & ' y StateGraph < LexerTypesT :: StorageT > ,
255- Option < PathBuf > ,
256- ) -> Result < ( ) , Box < dyn Error > > ,
257- > ,
258- > ,
245+ // test function for inspecting private state
246+ #[ cfg( test) ]
247+ inspect_callback : Option < Box < dyn Fn ( RecoveryKind ) -> Result < ( ) , Box < dyn Error > > > > ,
259248 phantom : PhantomData < LexerTypesT > ,
260249}
261250
@@ -300,8 +289,8 @@ where
300289 show_warnings : true ,
301290 visibility : Visibility :: Private ,
302291 rust_edition : RustEdition :: Rust2021 ,
292+ #[ cfg( test) ]
303293 inspect_callback : None ,
304- lexer_path : None ,
305294 phantom : PhantomData ,
306295 }
307296 }
@@ -432,25 +421,10 @@ where
432421 self
433422 }
434423
435- /// Sets the path to the lexer sources this is for usage from within callbacks only, and
436- /// not used during the build process.
437- pub fn lexer_path ( mut self , lexer_path : PathBuf ) -> Self {
438- self . lexer_path = Some ( lexer_path) ;
439- self
440- }
441-
442- pub fn inspect (
424+ #[ cfg( test) ]
425+ pub fn inspect_recoverer (
443426 mut self ,
444- cb : Box <
445- dyn for <' h , ' y > Fn (
446- & ' h mut Header ,
447- RecoveryKind ,
448- & ' y YaccGrammar < StorageT > ,
449- & ' y StateTable < StorageT > ,
450- & ' y StateGraph < StorageT > ,
451- Option < PathBuf > ,
452- ) -> Result < ( ) , Box < dyn Error > > ,
453- > ,
427+ cb : Box < dyn for <' h , ' y > Fn ( RecoveryKind ) -> Result < ( ) , Box < dyn Error > > > ,
454428 ) -> Self {
455429 self . inspect_callback = Some ( cb) ;
456430 self
@@ -652,6 +626,24 @@ where
652626 }
653627 } ;
654628
629+ #[ cfg( test) ]
630+ if let Some ( cb) = & self . inspect_callback {
631+ cb ( self . recoverer . expect ( "has a default value" ) ) ?;
632+ }
633+
634+ let unused_keys = header. unused ( ) ;
635+ if !unused_keys. is_empty ( ) {
636+ return Err ( format ! ( "Unused keys in header: {}" , unused_keys. join( ", " ) ) . into ( ) ) ;
637+ }
638+ let missing_keys = header. missing ( ) ;
639+ if !missing_keys. is_empty ( ) {
640+ return Err ( format ! (
641+ "Required values were missing from the header: {}" ,
642+ unused_keys. join( ", " )
643+ )
644+ . into ( ) ) ;
645+ }
646+
655647 let rule_ids = grm
656648 . tokens_map ( )
657649 . iter ( )
@@ -721,31 +713,6 @@ where
721713 fs:: remove_file ( outp) . ok ( ) ;
722714
723715 let ( sgraph, stable) = from_yacc ( & grm, Minimiser :: Pager ) ?;
724-
725- if let Some ( cb) = & self . inspect_callback {
726- cb (
727- & mut header,
728- self . recoverer . expect ( "has a default value" ) ,
729- & grm,
730- & stable,
731- & sgraph,
732- self . lexer_path . clone ( ) ,
733- ) ?;
734- }
735-
736- let unused_keys = header. unused ( ) ;
737- if !unused_keys. is_empty ( ) {
738- return Err ( format ! ( "Unused keys in header: {}" , unused_keys. join( ", " ) ) . into ( ) ) ;
739- }
740- let missing_keys = header. missing ( ) ;
741- if !missing_keys. is_empty ( ) {
742- return Err ( format ! (
743- "Required values were missing from the header: {}" ,
744- unused_keys. join( ", " )
745- )
746- . into ( ) ) ;
747- }
748-
749716 if self . error_on_conflicts {
750717 if let Some ( c) = stable. conflicts ( ) {
751718 match ( grm. expect ( ) , grm. expectrr ( ) ) {
@@ -872,8 +839,8 @@ where
872839 show_warnings : self . show_warnings ,
873840 visibility : self . visibility . clone ( ) ,
874841 rust_edition : self . rust_edition ,
842+ #[ cfg( test) ]
875843 inspect_callback : None ,
876- lexer_path : self . lexer_path . clone ( ) ,
877844 phantom : PhantomData ,
878845 } ;
879846 Ok ( cl. build ( ) ?. rule_ids )
@@ -962,14 +929,12 @@ where
962929 show_warnings,
963930 visibility,
964931 rust_edition,
965- inspect_callback : _ ,
966- lexer_path ,
932+ # [ cfg ( test ) ]
933+ inspect_callback : _ ,
967934 phantom : _,
968935 } = self ;
969936 let build_time = env ! ( "VERGEN_BUILD_TIMESTAMP" ) ;
970937 let grammar_path = grammar_path. as_ref ( ) . unwrap ( ) . to_string_lossy ( ) ;
971- let empty_path = PathBuf :: new ( ) ;
972- let lexer_path = lexer_path. as_ref ( ) . unwrap_or ( & empty_path) . to_string_lossy ( ) ;
973938 let mod_name = QuoteOption ( mod_name. as_deref ( ) ) ;
974939 let visibility = visibility. to_variant_tokens ( ) ;
975940 let rust_edition = rust_edition. to_variant_tokens ( ) ;
@@ -996,7 +961,6 @@ where
996961 RUST_EDITION = #rust_edition
997962 RULE_IDS_MAP = [ #( #rule_map, ) * ]
998963 VISIBILITY = #visibility
999- LEX_PATH = #lexer_path
1000964 } ;
1001965 let cache_info_str = cache_info. to_string ( ) ;
1002966 quote ! ( #cache_info_str)
@@ -1655,4 +1619,75 @@ C : 'a';"
16551619 }
16561620 }
16571621 }
1622+
1623+ #[ cfg( test) ]
1624+ #[ test]
1625+ fn test_recoverer_header ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
1626+ use crate :: RecoveryKind as RK ;
1627+ #[ rustfmt:: skip]
1628+ let recovery_kinds = [
1629+ // Builder, Header setting, Expected result.
1630+ // ----------- ------------------ -------------------
1631+ ( Some ( RK :: None ) , Some ( RK :: None ) , Some ( RK :: None ) ) ,
1632+ ( Some ( RK :: None ) , Some ( RK :: CPCTPlus ) , Some ( RK :: None ) ) ,
1633+ ( Some ( RK :: CPCTPlus ) , Some ( RK :: CPCTPlus ) , Some ( RK :: CPCTPlus ) ) ,
1634+ ( Some ( RK :: CPCTPlus ) , Some ( RK :: None ) , Some ( RK :: CPCTPlus ) ) ,
1635+ ( None , Some ( RK :: CPCTPlus ) , Some ( RK :: CPCTPlus ) ) ,
1636+ ( None , Some ( RK :: None ) , Some ( RK :: None ) ) ,
1637+ ( None , None , Some ( RK :: CPCTPlus ) ) ,
1638+ ( Some ( RK :: None ) , None , Some ( RK :: None ) ) ,
1639+ ( Some ( RK :: CPCTPlus ) , None , Some ( RK :: CPCTPlus ) ) ,
1640+ ] ;
1641+
1642+ for ( i, ( builder_arg, header_arg, expected_rk) ) in
1643+ recovery_kinds. iter ( ) . cloned ( ) . enumerate ( )
1644+ {
1645+ let y_src = if let Some ( header_arg) = header_arg {
1646+ format ! (
1647+ "\
1648+ %grmtools{{yacckind: Original(NoAction), recoverer: {}}} \
1649+ %% \
1650+ start: ; \
1651+ ",
1652+ match header_arg {
1653+ RK :: None => "RecoveryKind::None" ,
1654+ RK :: CPCTPlus => "RecoveryKind::CPCTPlus" ,
1655+ }
1656+ )
1657+ } else {
1658+ r#"
1659+ %grmtools{yacckind: Original(NoAction)}
1660+ %%
1661+ Start: ;
1662+ "#
1663+ . to_string ( )
1664+ } ;
1665+ let out_dir = std:: env:: var ( "OUT_DIR" ) . unwrap ( ) ;
1666+ let y_path = format ! ( "{out_dir}/recoverykind_test_{i}.y" ) ;
1667+ let y_out_path = format ! ( "{y_path}.rs" ) ;
1668+ std:: fs:: File :: create ( y_path. clone ( ) ) . unwrap ( ) ;
1669+ std:: fs:: write ( y_path. clone ( ) , y_src) . unwrap ( ) ;
1670+ let mut cp_builder = CTParserBuilder :: < TestLexerTypes > :: new ( ) ;
1671+ cp_builder = cp_builder
1672+ . output_path ( y_out_path. clone ( ) )
1673+ . grammar_path ( y_path. clone ( ) ) ;
1674+ cp_builder = if let Some ( builder_arg) = builder_arg {
1675+ cp_builder. recoverer ( builder_arg)
1676+ } else {
1677+ cp_builder
1678+ }
1679+ . inspect_recoverer ( Box :: new ( move |rk| {
1680+ if matches ! (
1681+ ( rk, expected_rk) ,
1682+ ( RK :: None , Some ( RK :: None ) ) | ( RK :: CPCTPlus , Some ( RK :: CPCTPlus ) )
1683+ ) {
1684+ Ok ( ( ) )
1685+ } else {
1686+ panic ! ( "Unexpected recovery kind" )
1687+ }
1688+ } ) ) ;
1689+ cp_builder. build ( ) ?;
1690+ }
1691+ Ok ( ( ) )
1692+ }
16581693}
0 commit comments