@@ -6,7 +6,7 @@ use nu_protocol::{
66} ;
77use rstest:: rstest;
88
9- use mock:: { Alias , AttrEcho , Def , Let , Mut , ToCustom } ;
9+ use mock:: { Alias , AttrEcho , Const , Def , IfMocked , Let , Mut , ToCustom } ;
1010
1111fn test_int (
1212 test_tag : & str , // name of sub-test
@@ -784,6 +784,38 @@ pub fn parse_attributes_external_alias() {
784784 assert ! ( parse_error. contains( "Encountered error during parse-time evaluation" ) ) ;
785785}
786786
787+ #[ test]
788+ pub fn parse_if_in_const_expression ( ) {
789+ // https://github.com/nushell/nushell/issues/15321
790+ let engine_state = EngineState :: new ( ) ;
791+ let mut working_set = StateWorkingSet :: new ( & engine_state) ;
792+
793+ working_set. add_decl ( Box :: new ( Const ) ) ;
794+ working_set. add_decl ( Box :: new ( Def ) ) ;
795+ working_set. add_decl ( Box :: new ( IfMocked ) ) ;
796+
797+ let source = b"const foo = if t" ;
798+ let _ = parse ( & mut working_set, None , source, false ) ;
799+
800+ assert ! ( !working_set. parse_errors. is_empty( ) ) ;
801+ let ParseError :: MissingPositional ( error, _, _) = & working_set. parse_errors [ 0 ] else {
802+ panic ! ( "Expected MissingPositional" ) ;
803+ } ;
804+
805+ assert ! ( error. contains( "cond" ) ) ;
806+
807+ working_set. parse_errors = Vec :: new ( ) ;
808+ let source = b"def a [n= (if ]" ;
809+ let _ = parse ( & mut working_set, None , source, false ) ;
810+
811+ assert ! ( !working_set. parse_errors. is_empty( ) ) ;
812+ let ParseError :: UnexpectedEof ( error, _) = & working_set. parse_errors [ 0 ] else {
813+ panic ! ( "Expected UnexpectedEof" ) ;
814+ } ;
815+
816+ assert ! ( error. contains( ")" ) ) ;
817+ }
818+
787819fn test_external_call ( input : & str , tag : & str , f : impl FnOnce ( & Expression , & [ ExternalArgument ] ) ) {
788820 let engine_state = EngineState :: new ( ) ;
789821 let mut working_set = StateWorkingSet :: new ( & engine_state) ;
@@ -1969,6 +2001,51 @@ mod mock {
19692001 engine:: Call , Category , IntoPipelineData , PipelineData , ShellError , Type , Value ,
19702002 } ;
19712003
2004+ #[ derive( Clone ) ]
2005+ pub struct Const ;
2006+
2007+ impl Command for Const {
2008+ fn name ( & self ) -> & str {
2009+ "const"
2010+ }
2011+
2012+ fn description ( & self ) -> & str {
2013+ "Create a parse-time constant."
2014+ }
2015+
2016+ fn signature ( & self ) -> nu_protocol:: Signature {
2017+ Signature :: build ( "const" )
2018+ . input_output_types ( vec ! [ ( Type :: Nothing , Type :: Nothing ) ] )
2019+ . allow_variants_without_examples ( true )
2020+ . required ( "const_name" , SyntaxShape :: VarWithOptType , "Constant name." )
2021+ . required (
2022+ "initial_value" ,
2023+ SyntaxShape :: Keyword ( b"=" . to_vec ( ) , Box :: new ( SyntaxShape :: MathExpression ) ) ,
2024+ "Equals sign followed by constant value." ,
2025+ )
2026+ . category ( Category :: Core )
2027+ }
2028+
2029+ fn run (
2030+ & self ,
2031+ _engine_state : & EngineState ,
2032+ _stack : & mut Stack ,
2033+ _call : & Call ,
2034+ _input : PipelineData ,
2035+ ) -> Result < PipelineData , ShellError > {
2036+ todo ! ( )
2037+ }
2038+
2039+ fn run_const (
2040+ & self ,
2041+ _working_set : & StateWorkingSet ,
2042+ _call : & Call ,
2043+ _input : PipelineData ,
2044+ ) -> Result < PipelineData , ShellError > {
2045+ Ok ( PipelineData :: empty ( ) )
2046+ }
2047+ }
2048+
19722049 #[ derive( Clone ) ]
19732050 pub struct Let ;
19742051
@@ -2422,6 +2499,19 @@ mod mock {
24222499 ) -> Result < PipelineData , ShellError > {
24232500 todo ! ( )
24242501 }
2502+
2503+ fn is_const ( & self ) -> bool {
2504+ true
2505+ }
2506+
2507+ fn run_const (
2508+ & self ,
2509+ _working_set : & StateWorkingSet ,
2510+ _call : & Call ,
2511+ _input : PipelineData ,
2512+ ) -> Result < PipelineData , ShellError > {
2513+ panic ! ( "Should not be called!" )
2514+ }
24252515 }
24262516}
24272517
0 commit comments