From 39907f72cc84627b40f276583d603bd371e4f2f0 Mon Sep 17 00:00:00 2001 From: ".Barsik" Date: Wed, 4 Dec 2024 23:19:54 +0200 Subject: [PATCH] READY: (wca): qqq (#1492) * wip * wip * wip * done --- module/move/wca/Cargo.toml | 12 +- module/move/wca/Readme.md | 4 +- module/move/wca/examples/wca_custom_error.rs | 43 +++ module/move/wca/examples/wca_fluent.rs | 9 +- module/move/wca/examples/wca_suggest.rs | 13 +- module/move/wca/examples/wca_trivial.rs | 10 +- module/move/wca/src/ca/aggregator.rs | 35 +- module/move/wca/src/ca/executor/context.rs | 6 +- module/move/wca/src/ca/executor/executor.rs | 51 ++- module/move/wca/src/ca/executor/routine.rs | 65 ++-- module/move/wca/src/ca/facade.rs | 345 ------------------ module/move/wca/src/ca/formatter.rs | 1 + module/move/wca/src/ca/grammar/command.rs | 17 +- module/move/wca/src/ca/grammar/dictionary.rs | 7 +- module/move/wca/src/ca/grammar/types.rs | 15 +- module/move/wca/src/ca/help.rs | 14 +- module/move/wca/src/ca/input.rs | 7 +- module/move/wca/src/ca/parser/command.rs | 6 +- module/move/wca/src/ca/parser/parser.rs | 44 ++- module/move/wca/src/ca/tool/table.rs | 11 +- module/move/wca/src/ca/verifier/command.rs | 6 +- module/move/wca/src/ca/verifier/verifier.rs | 111 ++++-- module/move/wca/tests/inc/adapter.rs | 44 --- .../tests/inc/commands_aggregator/basic.rs | 35 +- .../tests/inc/commands_aggregator/callback.rs | 1 + .../wca/tests/inc/commands_aggregator/help.rs | 18 +- .../wca/tests/inc/commands_aggregator/mod.rs | 11 - module/move/wca/tests/inc/executor/command.rs | 24 +- module/move/wca/tests/inc/executor/mod.rs | 13 - module/move/wca/tests/inc/executor/program.rs | 20 +- .../wca/tests/inc/grammar/from_command.rs | 31 +- .../wca/tests/inc/grammar/from_program.rs | 13 +- module/move/wca/tests/inc/grammar/mod.rs | 8 - module/move/wca/tests/inc/grammar/types.rs | 4 +- module/move/wca/tests/inc/mod.rs | 9 +- module/move/wca/tests/inc/parser/command.rs | 1 + module/move/wca/tests/inc/parser/mod.rs | 6 - module/move/wca/tests/inc/parser/program.rs | 1 + 38 files changed, 423 insertions(+), 648 deletions(-) create mode 100644 module/move/wca/examples/wca_custom_error.rs delete mode 100644 module/move/wca/src/ca/facade.rs delete mode 100644 module/move/wca/tests/inc/adapter.rs diff --git a/module/move/wca/Cargo.toml b/module/move/wca/Cargo.toml index da8d1227b6..06791cf645 100644 --- a/module/move/wca/Cargo.toml +++ b/module/move/wca/Cargo.toml @@ -40,12 +40,12 @@ harness = false [dependencies] ## internal -error_tools = { workspace = true, features = [ "default" ] } -strs_tools = { workspace = true, features = [ "default" ] } -mod_interface = { workspace = true, features = [ "default" ] } -iter_tools = { workspace = true, features = [ "default" ] } -former = { workspace = true, features = [ "default" ] } -# xxx : qqq : optimize set of features +error_tools = { workspace = true, features = [ "enabled", "error_typed", "error_untyped" ] } +mod_interface = { workspace = true, features = [ "enabled" ] } +iter_tools = { workspace = true, features = [ "enabled" ] } +former = { workspace = true, features = [ "enabled", "derive_former" ] } +# xxx : aaa : optimize set of features +# aaa : done. ## external log = "0.4" diff --git a/module/move/wca/Readme.md b/module/move/wca/Readme.md index b808fce2bc..ecda885b57 100644 --- a/module/move/wca/Readme.md +++ b/module/move/wca/Readme.md @@ -14,7 +14,7 @@ The tool to make CLI ( commands user interface ). It is able to aggregate extern ```rust #[ cfg( not( feature = "no_std" ) ) ] { - use wca::{ VerifiedCommand, Context, Type }; + use wca::{ VerifiedCommand, Type }; fn main() { @@ -37,7 +37,7 @@ The tool to make CLI ( commands user interface ). It is able to aggregate extern .end() .perform(); - let args = std::env::args().skip( 1 ).collect::< Vec< String > >(); + let args: Vec< String > = std::env::args().skip( 1 ).collect(); ca.perform( args ).unwrap(); } diff --git a/module/move/wca/examples/wca_custom_error.rs b/module/move/wca/examples/wca_custom_error.rs new file mode 100644 index 0000000000..47fef16985 --- /dev/null +++ b/module/move/wca/examples/wca_custom_error.rs @@ -0,0 +1,43 @@ +//! +//! # Handling Errors with CommandsAggregator +//! +//! This module provides an example of how to use `wca::CommandsAggregator` to manage error handling in a command-line interface. The `CommandsAggregator` offers a fluent interface for defining commands and associating them with various error types, making it straightforward to handle and present errors in a structured way. +//! +//! ## Purpose +//! +//! The primary goal of this example is to showcase how `CommandsAggregator` facilitates error handling, whether errors are simple strings, custom typed errors, untyped errors, or errors with additional context. This approach ensures that error management is both consistent and extensible. +//! + +#[ derive( Debug, error_tools::typed::Error )] +enum CustomError +{ + #[ error( "this is typed error" ) ] + TheError, +} + +fn main() -> error_tools::error::untyped::Result< () > +{ + let ca = wca::CommandsAggregator::former() + .command( "error.string" ) + .hint( "Returns error as a string" ) + .routine( || { Err( "this is string error" ) } ) + .end() + .command( "error.typed" ) + .hint( "Returns error as a custom error" ) + .routine( || { Err( CustomError::TheError ) } ) + .end() + .command( "error.untyped" ) + .hint( "Returns error as untyped error" ) + .routine( || { Err( error_tools::error::untyped::format_err!( "this is untyped error" ) ) } ) + .end() + .command( "error.with_context" ) + .hint( "Returns error as untyped error with context" ) + .routine( || { Err( error_tools::error::untyped::format_err!( "this is untyped error" ).context( "with context" ) ) } ) + .end() + .perform(); + + let args: Vec< String > = std::env::args().skip( 1 ).collect(); + () = ca.perform( args )?; + + Ok( () ) +} \ No newline at end of file diff --git a/module/move/wca/examples/wca_fluent.rs b/module/move/wca/examples/wca_fluent.rs index 487d6ee97d..3d5475a481 100644 --- a/module/move/wca/examples/wca_fluent.rs +++ b/module/move/wca/examples/wca_fluent.rs @@ -7,10 +7,10 @@ //! -use wca::{ Context, Handler, Type, VerifiedCommand }; +use wca::{ executor::{ Context, Handler }, Type, VerifiedCommand }; use std::sync::{ Arc, Mutex }; -fn main() +fn main() -> error_tools::error::untyped::Result< () > { let ca = wca::CommandsAggregator::former() @@ -45,7 +45,8 @@ fn main() .end() .perform(); - let args = std::env::args().skip( 1 ).collect::< Vec< String > >(); - ca.perform( args ).unwrap(); + let args: Vec< String > = std::env::args().skip( 1 ).collect(); + ca.perform( args )?; + Ok( () ) } diff --git a/module/move/wca/examples/wca_suggest.rs b/module/move/wca/examples/wca_suggest.rs index 2bb73fa111..b9b54989a8 100644 --- a/module/move/wca/examples/wca_suggest.rs +++ b/module/move/wca/examples/wca_suggest.rs @@ -22,7 +22,7 @@ use wca::{ CommandsAggregator, Type, VerifiedCommand }; -fn main() +fn main() -> error_tools::error::untyped::Result< () > { let ca = CommandsAggregator::former() @@ -34,14 +34,11 @@ fn main() { println!( "= Args\n{:?}\n\n= Properties\n{:?}\n", o.args, o.props ); }) - .end() + .end() .perform(); - let args = std::env::args().skip( 1 ).collect::< Vec< String > >(); - match ca.perform( args.join( " " ) ) - { - Ok( _ ) => {} - Err( err ) => println!( "{err}" ), - }; + let args: Vec< String > = std::env::args().skip( 1 ).collect(); + ca.perform( args.join( " " ) )?; + Ok( () ) } diff --git a/module/move/wca/examples/wca_trivial.rs b/module/move/wca/examples/wca_trivial.rs index c228e6e20a..1df6dec815 100644 --- a/module/move/wca/examples/wca_trivial.rs +++ b/module/move/wca/examples/wca_trivial.rs @@ -16,7 +16,7 @@ fn exit() std::process::exit( 0 ) } -fn main() +fn main() -> error_tools::error::untyped::Result< () > { let ca = CommandsAggregator::former() .command( "exit" ) @@ -33,7 +33,7 @@ fn main() .perform() ; - // aaa : qqq2 : for Bohdan : that should work + // aaa : aaa2 : for Bohdan : that should work // let ca = wca::CommandsAggregator::former() // .command( "echo" ) // .hint( "prints all subjects and properties" ) @@ -50,6 +50,8 @@ fn main() // ca.execute( input ).unwrap(); //aaa: works - let input = std::env::args().skip( 1 ).collect::< Vec< String > >(); - ca.perform( input ).unwrap(); + let input: Vec< String > = std::env::args().skip( 1 ).collect(); + ca.perform( input )?; + + Ok( () ) } diff --git a/module/move/wca/src/ca/aggregator.rs b/module/move/wca/src/ca/aggregator.rs index 60668ad4a0..c8cd532342 100644 --- a/module/move/wca/src/ca/aggregator.rs +++ b/module/move/wca/src/ca/aggregator.rs @@ -3,7 +3,6 @@ mod private use crate::*; use ca:: { - Verifier, Executor, grammar::command:: { @@ -14,15 +13,17 @@ mod private }, help::{ HelpGeneratorFn, HelpGeneratorOptions, HelpVariants }, }; + use verifier::{ Verifier, VerificationError, VerifiedCommand }; + use parser::{ Program, Parser, ParserError }; + use grammar::Dictionary; + use executor::Context; - // qqq : group uses - use std::collections::HashSet; - use std::fmt; + use std:: + { + fmt, + collections::HashSet + }; use former::StoragePreform; - // use wtools:: - // { - // }; - // use wtools::thiserror; use error:: { // Result, @@ -54,11 +55,11 @@ mod private /// source of the program input : String, /// original error - error : wError, + error : ParserError, }, /// This variant represents errors that occur during grammar conversion. #[ error( "Can not identify a command.\nDetails: {0}" ) ] - Verifier( wError ), + Verifier( VerificationError ), /// This variant is used to represent errors that occur during executor conversion. #[ error( "Can not find a routine for a command.\nDetails: {0}" ) ] ExecutorConverter( wError ), @@ -70,14 +71,14 @@ mod private { /// This variant is used to represent validation errors. /// It carries a `ValidationError` payload that provides additional information about the error. - #[ error( "Validation error. {0}" ) ] + #[ error( "Validation error\n{0}" ) ] Validation( ValidationError ), /// This variant represents execution errors. - #[ error( "Execution failed. {0:?}" ) ] + #[ error( "Execution failed\n{0:?}" ) ] Execution( wError ), } - // xxx : qqq : qqq2 : for Bohdan : one level is obviously redundant + // xxx : aaa : aaa2 : for Bohdan : one level is obviously redundant // Program< Namespace< ExecutableCommand_ > > -> Program< ExecutableCommand_ > // aaa : done. The concept of `Namespace` has been removed struct CommandsAggregatorCallback( Box< dyn Fn( &str, &Program< VerifiedCommand > ) > ); @@ -283,7 +284,7 @@ mod private callback.0( &program.join( " " ), &grammar_program ) } - self.executor.program( &self.dictionary, grammar_program ).map_err( | e | Error::Execution( e ) ) + self.executor.program( &self.dictionary, grammar_program ).map_err( | e | Error::Execution( e.into() ) ) } } } @@ -293,8 +294,8 @@ mod private crate::mod_interface! { exposed use CommandsAggregator; - exposed use CommandsAggregatorFormer; - exposed use Error; - exposed use ValidationError; + orphan use CommandsAggregatorFormer; + orphan use Error; + orphan use ValidationError; exposed use Order; } diff --git a/module/move/wca/src/ca/executor/context.rs b/module/move/wca/src/ca/executor/context.rs index df60994a23..716bbafda6 100644 --- a/module/move/wca/src/ca/executor/context.rs +++ b/module/move/wca/src/ca/executor/context.rs @@ -7,7 +7,7 @@ mod private /// # Examples: /// /// ``` - /// # use wca::{ Routine, Handler, Context, Value, Args, Props, VerifiedCommand }; + /// # use wca::{ executor::{ Routine, Handler, Args, Props, Context }, Value, VerifiedCommand }; /// # use std::sync::{ Arc, Mutex }; /// let routine = Routine::from( Handler::from /// ( @@ -33,7 +33,7 @@ mod private /// } /// assert_eq!( 1, *ctx.get::< Mutex< i32 > >().unwrap().lock().unwrap() ); /// ``` - // qqq : ? + // xxx clarification is needed qqq : поточнити #[ derive( Debug, Clone ) ] pub struct Context { @@ -91,5 +91,5 @@ mod private crate::mod_interface! { - exposed use Context; + orphan use Context; } diff --git a/module/move/wca/src/ca/executor/executor.rs b/module/move/wca/src/ca/executor/executor.rs index 22e44fc19b..9d662801a8 100644 --- a/module/move/wca/src/ca/executor/executor.rs +++ b/module/move/wca/src/ca/executor/executor.rs @@ -2,13 +2,23 @@ mod private { use crate::*; - // use wtools::error::Result; - // use error::return_err; use ca::help::{ HelpGeneratorOptions, generate_help_content, LevelOfDetail }; + use verifier::VerifiedCommand; + use parser::Program; + use grammar::Dictionary; + use executor::{ Routine, Context }; // aaa : for Bohdan : how is it useful? where is it used? // aaa : `ExecutorType` has been removed + #[ derive( Debug, error::typed::Error ) ] + pub enum CommandError + { + #[ error( "Internal command: `.{}` failed with: {}", command.phrase, error ) ] + Internal { command: VerifiedCommand, error: InternalCommandError }, + #[ error( "Command: `.{}` failed with: {}", command.phrase, error ) ] + User { command: VerifiedCommand, error: error::untyped::Error }, + } /// Executor that is responsible for executing the program's commands. /// It uses the given `Context` to store and retrieve values during runtime. @@ -36,9 +46,10 @@ mod private /// /// A `Result` with `Ok( () )` if the execution was successful, or an `Err` containing an error message if an error occurred. /// - // qqq : use typed error + // aaa : use typed error + // aaa : done pub fn program( &self, dictionary : &Dictionary, program : Program< VerifiedCommand > ) - -> error::untyped::Result< () > + -> Result< (), CommandError > { for command in program.commands { @@ -60,18 +71,21 @@ mod private /// # Returns /// /// Returns a Result indicating success or failure. If successful, returns `Ok(())`, otherwise returns an error. - // qqq : use typed error + // aaa : use typed error + // aaa : done pub fn command( &self, dictionary : &Dictionary, command : VerifiedCommand ) - -> error::untyped::Result< () > + -> Result< (), CommandError > { if command.internal_command { - _exec_internal_command( dictionary, command ) + _exec_internal_command( dictionary, command.clone() ) + .map_err( | error | CommandError::Internal { command, error } ) } else { let routine = dictionary.command( &command.phrase ).unwrap().routine.clone(); - _exec_command( command, routine, self.context.clone() ) + _exec_command( command.clone(), routine, self.context.clone() ) + .map_err( | error | CommandError::User { command, error } ) } } @@ -80,6 +94,7 @@ mod private } // qqq : use typed error + // aaa : should it be typed? it is user command with unknown error type fn _exec_command( command : VerifiedCommand, routine : Routine, ctx : Context ) -> error::untyped::Result< () > { @@ -90,9 +105,19 @@ mod private } } - // qqq : use typed error + #[ derive( Debug, error::typed::Error ) ] + pub enum InternalCommandError + { + #[ error( "Encountered an unrecognized internal command: `.{user_input}`." ) ] + UnknownInternalCommand { user_input: String }, + #[ error( "Not found command that starts with `.{user_input}`." ) ] + CommandNotFound { user_input: String }, + } + + // aaa : use typed error + // aaa : done fn _exec_internal_command( dictionary : &Dictionary, command : VerifiedCommand ) - -> error::untyped::Result< () > + -> Result< (), InternalCommandError > { match command.phrase.as_str() { @@ -122,7 +147,7 @@ mod private let commands = dictionary.search( name.strip_prefix( '.' ).unwrap_or( name ) ); if commands.is_empty() { - error::untyped::return_err!( "Not found command that starts with `.{}`.", name ); + return Err( InternalCommandError::CommandNotFound { user_input : name.into() } ); } let generator_args = HelpGeneratorOptions::former() .command_prefix( "." ) @@ -151,10 +176,10 @@ mod private } else { - error::untyped::return_err!( "Not found command that starts with `.{}`.", name ); + return Err( InternalCommandError::CommandNotFound { user_input : name.into() } ); } } - unexpected => error::untyped::return_err!( "Encountered an unrecognized internal command: `.{}`.", unexpected ), + unexpected => return Err( InternalCommandError::UnknownInternalCommand { user_input: unexpected.into() }), } Ok( () ) diff --git a/module/move/wca/src/ca/executor/routine.rs b/module/move/wca/src/ca/executor/routine.rs index 45fc96bed1..ad9a455052 100644 --- a/module/move/wca/src/ca/executor/routine.rs +++ b/module/move/wca/src/ca/executor/routine.rs @@ -2,13 +2,17 @@ mod private { use crate::*; - // qqq : group + // aaa : group + // aaa : done - use std::collections::HashMap; - // use wtools::error::Result; - - use std::{ fmt::Formatter, rc::Rc }; - // use wtools::anyhow::anyhow; + use std:: + { + collections::HashMap, + fmt::Formatter, + rc::Rc, + }; + use verifier::VerifiedCommand; + use executor::Context; /// Command Args /// @@ -17,7 +21,7 @@ mod private /// # Example: /// /// ``` - /// use wca::{ Args, Value }; + /// use wca::{ executor::Args, Value }; /// /// let args = Args( vec![ Value::String( "Hello, World!".to_string() ) ] ); /// @@ -30,7 +34,7 @@ mod private /// /// ## Use case /// ``` - /// # use wca::{ Routine, Handler, VerifiedCommand }; + /// # use wca::{ executor::{ Routine, Handler }, VerifiedCommand }; /// let routine = Routine::from( Handler::from /// ( /// | o : VerifiedCommand | @@ -47,7 +51,7 @@ mod private /// Returns owned casted value by its index /// /// ``` - /// # use wca::{ Args, Value }; + /// # use wca::{ executor::Args, Value }; /// /// let args = Args( vec![ Value::String( "Hello, World!".to_string() ) ] ); /// @@ -79,7 +83,7 @@ mod private /// # Example: /// /// ``` - /// use wca::{ Props, Value }; + /// use wca::{ executor::Props, Value }; /// /// let props = Props( [ ( "hello".to_string(), Value::String( "World!".to_string() ) ) ].into() ); /// let hello_prop : &str = props.get_owned( "hello" ).unwrap(); @@ -89,7 +93,7 @@ mod private /// /// ## Use case /// ``` - /// # use wca::{ Routine, Handler, Props, VerifiedCommand }; + /// # use wca::{ executor::{ Routine, Handler, Props }, VerifiedCommand }; /// let routine = Routine::from( Handler::from /// ( /// | o : VerifiedCommand | @@ -106,7 +110,7 @@ mod private /// Returns owned casted value by its key /// /// ``` - /// # use wca::{ Props, Value }; + /// # use wca::{ executor::Props, Value }; /// /// let props = Props( [ ( "hello".to_string(), Value::String( "World!".to_string() ) ) ].into() ); /// let hello_prop : &str = props.get_owned( "hello" ).unwrap(); @@ -132,7 +136,10 @@ mod private // aaa : done. now it works with the following variants: // fn(), fn(args), fn(props), fn(args, props), fn(context), fn(context, args), fn(context, props), fn(context, args, props) - // qqq : why not public? + // aaa : why not public? // aaa : described + + // These type aliases are kept private to hide implementation details and prevent misuse. + // Exposing them would risk complicating the API and limit future refactoring flexibility. type RoutineWithoutContextFn = dyn Fn( VerifiedCommand ) -> error::untyped::Result< () >; type RoutineWithContextFn = dyn Fn( Context, VerifiedCommand ) -> error::untyped::Result< () >; @@ -140,7 +147,7 @@ mod private /// Routine handle. /// /// ``` - /// # use wca::{ Handler, Routine }; + /// # use wca::executor::{ Handler, Routine }; /// let routine = Routine::from( Handler::from /// ( /// || @@ -151,7 +158,7 @@ mod private /// ``` /// /// ``` - /// # use wca::{ Handler, Routine, VerifiedCommand }; + /// # use wca::{ executor::{ Handler, Routine }, VerifiedCommand }; /// let routine = Routine::from( Handler::from /// ( /// | o : VerifiedCommand | @@ -162,7 +169,7 @@ mod private /// ``` /// /// ``` - /// # use wca::{ Handler, Routine }; + /// # use wca::executor::{ Handler, Routine }; /// let routine = Routine::from( Handler::from /// ( /// | ctx, o | @@ -243,7 +250,7 @@ mod private /// /// - `WithoutContext`: A routine that does not require any context. /// - `WithContext`: A routine that requires a context. -// qqq : for Bohdan : instead of array of Enums, lets better have 5 different arrays of different Routine and no enum +// xxx clarification is needed : for Bohdan : instead of array of Enums, lets better have 5 different arrays of different Routine and no enum // to use statical dispatch #[ derive( Clone ) ] pub enum Routine @@ -327,15 +334,25 @@ mod private } // xxx + // aaa : This is an untyped error because we want to provide a common interface for all commands, while also allowing users to propagate their own specific custom errors. impl IntoResult for std::convert::Infallible { fn into_result( self ) -> error::untyped::Result< () > { Ok( () ) } } impl IntoResult for () { fn into_result( self ) -> error::untyped::Result< () > { Ok( () ) } } - impl< E : std::fmt::Debug > IntoResult + impl< E : std::fmt::Debug + std::fmt::Display + 'static > IntoResult for error::untyped::Result< (), E > { fn into_result( self ) -> error::untyped::Result< () > { - self.map_err( | e | error::untyped::format_err!( "{e:?}" )) - // xxx : qqq : ? + use std::any::TypeId; + // if it's anyhow error we want to have full context(debug), and if it's not(this error) we want to display + if TypeId::of::< error::untyped::Error >() == TypeId::of::< E >() + { + self.map_err( | e | error::untyped::format_err!( "{e:?}" )) + } + else + { + self.map_err( | e | error::untyped::format_err!( "{e}" )) + } + // xxx : aaa : ? } } } @@ -344,8 +361,8 @@ mod private crate::mod_interface! { - exposed use Routine; - exposed use Handler; - exposed use Args; - exposed use Props; + orphan use Routine; + orphan use Handler; + orphan use Args; + orphan use Props; } diff --git a/module/move/wca/src/ca/facade.rs b/module/move/wca/src/ca/facade.rs deleted file mode 100644 index 80fca20afc..0000000000 --- a/module/move/wca/src/ca/facade.rs +++ /dev/null @@ -1,345 +0,0 @@ -// mod private -// { -// use crate::*; -// use core::fmt; -// use ca::grammar; -// -// /// Macro for parsing WCA arguments. -// /// -// /// # Examples -// /// ```rust -// /// use wca::Value; -// /// -// /// let mut args = vec![ Value::Number( 42. ), Value::String( "Rust".into() ) ].into_iter(); -// /// wca::parse_args!( args, n : f64, name : String ); -// /// -// /// assert_eq!( n, 42. ); -// /// assert_eq!( name, "Rust" ); -// /// ``` -// #[macro_export] -// macro_rules! parse_args -// { -// ( $args : ident, mut $b : ident : $ty : ident $( $rest : tt )* ) => -// { -// let mut $b : $ty = std::convert::TryFrom::try_from( $args.next().unwrap() ).unwrap(); -// $crate::parse_args!( $args $( $rest )* ) -// }; -// ( $args : ident, $b : ident : $ty : ident $( $rest : tt )* ) => -// { -// let $b : $ty = std::convert::TryFrom::try_from( $args.next().unwrap() ).unwrap(); -// $crate::parse_args!( $args $( $rest )* ) -// }; -// ( $args : ident, $b : ident $( $rest : tt )* ) => -// { -// let $b = $args.next().unwrap(); -// $crate::parse_args!( $args $( $rest )* ) -// }; -// ( $args : ident, mut $b : ident $( $rest : tt )* ) => -// { -// let mut $b = $args.next().unwrap(); -// $crate::parse_args!( $args $( $rest )* ) -// }; -// ( $args : ident ) => -// { -// assert!( $args.next().is_none() ); -// }; -// ( $args : ident, ) => -// { -// $crate::parse_args!( $args ) -// }; -// } -// -// /// Creates a command-line interface (CLI) builder with the given initial state. -// /// -// /// This function initializes a `CommandBuilder` with the provided `state` and -// /// returns it for further configuration of the CLI. -// pub fn cui< T >( state : T ) -> CommandBuilder< T > -// { -// CommandBuilder::with_state( state ) -// } -// -// /// A struct representing a property. -// #[ derive( Debug, Clone ) ] -// pub struct Property< 'a > -// { -// /// The name of the property. -// pub name : &'a str, -// /// The hint for the property. -// pub debug : &'a str, -// /// The tag representing the property's type. -// pub tag : Type, -// } -// -// impl< 'a > Property< 'a > -// { -// /// Constructor of a property. -// pub fn new( name : &'a str, hint : &'a str, tag : Type ) -> Self { Self { name, hint, tag } } -// } -// -// /// A builder struct for constructing commands. -// #[ derive( Debug ) ] -// pub struct CommandBuilder< T > -// { -// state : T, -// commands : Vec< Command >, -// handlers : std::collections::HashMap< String, Routine >, -// } -// -// impl< T > CommandBuilder< T > -// { -// /// Constructs a `CommandBuilder` with the given state. -// pub fn with_state( state : T ) -> Self -// { -// Self { state, handlers : < _ >::default(), commands : vec![] } -// } -// } -// -// #[ derive( Debug ) ] -// pub struct Builder< F > -// { -// handler : F, -// command : Command, -// } -// -// impl< F > Builder< F > -// { -// /// Creates a new instance of the command with the provided handler function. -// /// -// /// This method takes in a handler function `handler` and creates a new instance of the command. -// /// The `handler` function is used to handle the execution logic associated with the command. -// /// -// /// # Arguments -// /// -// /// * `handler` - The handler function that will be invoked when the command is executed. -// /// -// /// # Returns -// /// -// /// A new instance of the command with the specified `handler`. -// /// -// #[ inline ] -// pub fn new( handler: F ) -> Self -// { -// let name = -// { -// use iter_tools::Itertools as _; -// -// let name = std::any::type_name::< F >(); -// let name = name.split("::").last().unwrap(); -// name.split( '_' ).join( "." ) -// }; -// -// Self { handler, command : Command::former().phrase( name ).form() } -// } -// -// /// Adds an argument to the command. -// /// -// /// This method takes in the `hint` and `tag` parameters to create a `ValueDescription` object -// /// representing an argument. The `ValueDescription` object is then appended to the command's -// /// `subjects` collection. -// /// -// /// # Arguments -// /// -// /// * `hint` - The hint for the argument, represented as a string slice (`&str`). -// /// * `tag` - The type of the argument, represented by a `Type` object from the `Type` module. -// /// -// /// # Returns -// /// -// /// The modified command instance with the argument added. -// /// -// #[ inline ] -// pub fn arg( mut self, hint : &str, tag : Type ) -> Self -// { -// self.command.subjects.push( grammar::command::ValueDescription -// { -// hint : hint.into(), -// kind : tag, -// optional : false, -// }); -// -// self -// } -// -// /// Adds a property to the command. -// /// -// /// This method takes in the `name`, `hint`, and `kind` parameters to create a `ValueDescription` -// /// object representing a property. The `ValueDescription` object is then inserted into the -// /// command's properties collection using the `name` as the key. -// /// -// /// # Example -// /// ```no_rust -// /// let ca = cui(()) -// /// .command(user.property("name", "Name property", Type::String)) -// /// .build(); -// /// ``` -// /// -// /// # Arguments -// /// -// /// * `name` - The name of the property. It should implement the `ToString` trait. -// /// * `hint` - The hint for the property. It should implement the `ToString` trait. -// /// * `kind` - The type of the property, represented by a `Type` object from the `Type` module. -// /// -// /// # Returns -// /// -// /// The modified command instance with the property added. -// /// -// #[ inline ] -// pub fn property( mut self, name : impl ToString , hint : impl ToString, kind : Type ) -> Self -// { -// self.command.properties.insert -// ( -// name.to_string(), -// grammar::command::ValueDescription -// { -// hint : hint.to_string(), -// kind, -// optional : false, -// } -// ); -// -// self -// } -// -// /// Adds multiple properties to the command. -// /// -// /// This method takes in an array of `Property` objects and adds them to the command's properties. -// /// The properties are provided in the `properties` parameter as an array of length `N`. -// /// -// /// ```without_std -// /// let ca = cui(()) -// /// .properties([ -// /// Property::new("name", "Name property", Type::String), -// /// Property::new("age", "Age property", Type::Integer), -// /// ]).build(); -// /// ``` -// /// -// /// # Arguments -// /// -// /// * `properties` - An array of `Property` objects representing the properties to be added. -// /// -// /// # Returns -// /// -// /// The modified command instance with the properties added. -// /// -// #[ inline ] -// pub fn properties< const N: usize >( mut self, properties : [ Property< '_ >; N ] ) -> Self -// { -// self.command.properties.reserve( properties.len() ); -// -// for Property { name, hint, tag } in properties -// { -// self = self.property(name, hint, tag); -// } -// -// self -// } -// } -// -// impl< T: Clone + 'static > CommandBuilder< T > -// { -// /// Adds a command to the `CommandBuilder`. -// /// ```no_rust -// /// let ca = cui( () ) // Add commands using the builder pattern -// /// .command( command ) -// /// .command( command2 ) -// /// .command( echo.arg("string", Type::String ) ) // Customize your commands by chaining methods such as properties -// /// // property, and arg to add properties and arguments. -// /// .build(); -// /// -// /// ``` -// pub fn command< F, E > -// ( -// mut self, -// command : impl IntoBuilder< F, T >, -// ) -> Self -// where -// F : Fn( T, Args, Props ) -> Result< (), E > + 'static + Copy, -// E : fmt::Debug, -// { -// let Builder { handler, command } = command.into_builder(); -// let state = self.state.clone(); -// -// let closure = closure::closure!( | ( args, props ) | -// { -// handler( state.clone(), args, props ) -// .map_err( | report | BasicError::new( format!( "{report:?}" ) ).into() ) -// }); -// -// let handler = Routine::new( closure ); -// -// self.handlers.insert( command.phrase.clone(), handler ); -// self.commands.push( command ); -// -// self -// } -// -// /// Builds and returns a `wca::CommandsAggregator` instance. -// /// -// /// This method finalizes the construction of the `CommandBuilder` by -// /// creating a `wca::CommandsAggregator` instance with the accumulated -// /// commands and handlers. -// pub fn build( self ) -> CommandsAggregator -// { -// CommandsAggregator::former().grammar( self.commands ).executor( self.handlers ).perform() -// } -// } -// -// /// An extension trait for commands. -// /// -// /// This trait provides additional methods for enhancing commands, such as -// /// adding arguments and properties. -// pub trait CommandExt< T > : Sized -// { -// /// Adds an argument to the command. -// fn arg( self, hint : &str, tag : Type ) -> Builder< Self > -// { -// Builder::new( self ).arg( hint, tag ) -// } -// -// /// Adds property to the command. -// fn property< const N: usize >( self, name : impl ToString , hint : impl ToString, kind : Type ) -> Builder< Self > -// { -// Builder::new( self ).property( name, hint, kind ) -// } -// -// /// Adds properties to the command. -// fn properties< const N: usize >( self, properties: [ Property< '_ >; N ] ) -> Builder< Self > -// { -// Builder::new( self ).properties( properties ) -// } -// } -// -// impl< F: Fn( T, Args, Props ) -> Result< (), E>, T, E > CommandExt< T > for F {} -// -// /// A trait for converting a type into a `Builder`. -// pub trait IntoBuilder< F, T > : Sized -// { -// /// Converts the type into a `Builder` instance. -// fn into_builder( self ) -> Builder< F >; -// } -// -// impl< F, T > IntoBuilder< F, T > for Builder< F > -// { -// fn into_builder( self ) -> Self -// { -// self -// } -// } -// -// impl< F: Fn( T, Args, Props ) -> Result< (), E >, T, E > IntoBuilder< F, T > for F -// { -// fn into_builder( self ) -> Builder< F > -// { -// Builder::new( self ) -// } -// } -// -// } -// -// crate::mod_interface! -// { -// exposed use cui; -// exposed use CommandBuilder; -// exposed use Property; -// prelude use IntoBuilder; -// prelude use CommandExt; -// } diff --git a/module/move/wca/src/ca/formatter.rs b/module/move/wca/src/ca/formatter.rs index 905fed5b2d..30e6787d6d 100644 --- a/module/move/wca/src/ca/formatter.rs +++ b/module/move/wca/src/ca/formatter.rs @@ -4,6 +4,7 @@ mod private use crate::*; use iter_tools::Itertools; use ca::aggregator::Order; + use grammar::Dictionary; /// Enum representing the format options for generating help content. /// diff --git a/module/move/wca/src/ca/grammar/command.rs b/module/move/wca/src/ca/grammar/command.rs index ad34d5ef85..0c17e726b1 100644 --- a/module/move/wca/src/ca/grammar/command.rs +++ b/module/move/wca/src/ca/grammar/command.rs @@ -2,10 +2,11 @@ mod private { use crate::*; - use std::collections::{ HashMap }; + use std::collections::HashMap; use indexmap::IndexMap; use former::{ Former, StoragePreform }; use iter_tools::Itertools; + use executor::{ Routine, Handler }; /// A description of a Value in a command. Used to specify the expected type and provide a hint for the Value. /// @@ -35,7 +36,7 @@ mod private pub struct PropertyDescription { name : String, - // qqq : how to re-use ValueDescriptionFormer without additional end? + // xxx : how to re-use ValueDescriptionFormer without additional end? // #[subform_scalar] // value : ValueDescription, /// providing guidance to the user for entering a valid value @@ -74,7 +75,7 @@ mod private /// # Example: /// /// ``` - /// # use wca::{ Command, Type }; + /// # use wca::{ grammar::Command, Type }; /// let command = Command::former() /// .hint( "hint" ) /// .long_hint( "long_hint" ) @@ -103,7 +104,8 @@ mod private /// Map of aliases. // Aliased key -> Original key pub properties_aliases : HashMap< String, String >, - // qqq : make it usable and remove default(?) + // aaa : make it usable and remove default(?) + // aaa : it is usable /// The type `Routine` represents the specific implementation of the routine. #[ scalar( setter = false ) ] #[ former( default = Routine::from( Handler::< _, std::convert::Infallible >::from( || { panic!( "No routine available: A handler function for the command is missing" ) } ) ) ) ] @@ -246,8 +248,8 @@ mod private crate::mod_interface! { - exposed use Command; - exposed use CommandFormer; + orphan use Command; + orphan use CommandFormer; own use ValueDescription; own use CommandAsSubformer; @@ -256,4 +258,5 @@ crate::mod_interface! } -// qqq : use orphan instead of exposed for ALL files in the folder, dont use prelude for structs \ No newline at end of file +// aaa : use orphan instead of exposed for ALL files in the folder, dont use prelude for structs +// aaa : done. \ No newline at end of file diff --git a/module/move/wca/src/ca/grammar/dictionary.rs b/module/move/wca/src/ca/grammar/dictionary.rs index e6887aef26..8dc784f3db 100644 --- a/module/move/wca/src/ca/grammar/dictionary.rs +++ b/module/move/wca/src/ca/grammar/dictionary.rs @@ -4,8 +4,9 @@ mod private use former::Former; use indexmap::IndexMap; use iter_tools::Itertools; + use grammar::Command; - // qqq : `Former` does not handle this situation well + // xxx : `Former` does not handle this situation well // /// A collection of commands. // /// @@ -25,8 +26,6 @@ mod private pub( crate ) order : Order, } - // qqq : IDK how to integrate it into the `CommandsAggregatorFormer` - // impl DictionaryFormer { pub fn command( mut self, command : Command ) -> Self @@ -109,5 +108,5 @@ mod private crate::mod_interface! { - exposed use Dictionary; + orphan use Dictionary; } diff --git a/module/move/wca/src/ca/grammar/types.rs b/module/move/wca/src/ca/grammar/types.rs index 2141ca335b..99526b35dd 100644 --- a/module/move/wca/src/ca/grammar/types.rs +++ b/module/move/wca/src/ca/grammar/types.rs @@ -6,9 +6,6 @@ mod private Display, Formatter }; - // use wtools; - // use wtools::{ error::Result, err }; - // use error::err; use iter_tools::Itertools; /// Available types that can be converted to a `Value` @@ -59,7 +56,7 @@ mod private /// # Example: /// /// ``` - /// # use wca::{ VerifiedCommand, Value, Args, Props }; + /// # use wca::{ VerifiedCommand, Value, executor::{ Args, Props } }; /// # use std::collections::HashMap; /// let command = VerifiedCommand /// { @@ -119,7 +116,7 @@ mod private } Value::List( list ) => { - let list = list.iter().map( | element | element.to_string() ).join( "," ); // qqq : don't hardcode ", " find way to get original separator + let list = list.iter().map( | element | element.to_string() ).join( "," ); write!( f, "{list}" )?; } } @@ -191,11 +188,13 @@ mod private Self::Bool => Ok( Value::Bool( match value.as_str() { "1" | "true" => true, "0" | "false" => false, _ => return Err( error::untyped::format_err!( "Can not parse bool from `{}`", value ) ) } ) ), Self::List( kind, delimeter ) => { - let values = value + let values: error::untyped::Result< Vec< Value > > = value .split( *delimeter ) .map( | val | kind.try_cast( val.into() ) ) - .collect::< error::untyped::Result< Vec< Value > > >()?; - // qqq : avoid using fish notation whenever possible. review whole crate + .collect(); + let values = values?; + // aaa : avoid using fish notation whenever possible. review whole crate + // aaa : done Ok( Value::List( values ) ) }, } diff --git a/module/move/wca/src/ca/help.rs b/module/move/wca/src/ca/help.rs index a2a7129f49..6a40e28e1c 100644 --- a/module/move/wca/src/ca/help.rs +++ b/module/move/wca/src/ca/help.rs @@ -3,8 +3,6 @@ mod private use crate::*; use ca:: { - Command, - Routine, Type, formatter:: { @@ -13,13 +11,17 @@ mod private }, tool::table::format_table, }; + use verifier::VerifiedCommand; + use grammar::{ Command, Dictionary }; + use executor::Routine; use iter_tools::Itertools; use std::rc::Rc; use error::untyped::format_err; use former::Former; - // qqq : for Bohdan : it should transparent mechanist which patch list of commands, not a stand-alone mechanism + // aaa : for Bohdan : it should transparent mechanist which patch list of commands, not a stand-alone mechanism + // aaa : it is /// Enum `LevelOfDetail` specifies the granularity of detail for rendering or processing: #[ derive( Debug, Default, Copy, Clone, PartialEq, Eq ) ] @@ -67,7 +69,9 @@ mod private pub order : Order, } - // qqq : for Barsik : make possible to change properties order + // aaa : for Barsik : make possible to change properties order + // aaa : order option + /// Generates help content as a formatted string based on a given dictionary and options. /// /// This function takes a `Dictionary` of terms or commands and a `HelpGeneratorOptions` @@ -366,7 +370,7 @@ mod private /// /// ``` /// # use wca::ca::help::{ HelpGeneratorOptions, HelpGeneratorFn }; - /// use wca::{ Command, Dictionary }; + /// use wca::grammar::{ Command, Dictionary }; /// /// fn my_help_generator( dictionary : &Dictionary, args : HelpGeneratorOptions< '_ > ) -> String /// { diff --git a/module/move/wca/src/ca/input.rs b/module/move/wca/src/ca/input.rs index c2826f99ef..46f70221b8 100644 --- a/module/move/wca/src/ca/input.rs +++ b/module/move/wca/src/ca/input.rs @@ -1,7 +1,6 @@ mod private { - use std::io; - use std::io::Write; + use std::io::{ self, Write }; /// Ask use input from standard input. pub fn ask( request : &str ) -> String @@ -78,6 +77,6 @@ mod private crate::mod_interface! { exposed use ask; - exposed use Input; - exposed use IntoInput; + orphan use Input; + orphan use IntoInput; } diff --git a/module/move/wca/src/ca/parser/command.rs b/module/move/wca/src/ca/parser/command.rs index 332c9e71f6..84cfbefc2b 100644 --- a/module/move/wca/src/ca/parser/command.rs +++ b/module/move/wca/src/ca/parser/command.rs @@ -25,7 +25,7 @@ mod private /// # Example: /// /// ``` - /// # use wca::ParsedCommand; + /// # use wca::parser::ParsedCommand; /// # use std::collections::HashMap; /// ParsedCommand /// { @@ -57,6 +57,6 @@ mod private crate::mod_interface! { - exposed use Program; - exposed use ParsedCommand; + orphan use Program; + orphan use ParsedCommand; } diff --git a/module/move/wca/src/ca/parser/parser.rs b/module/move/wca/src/ca/parser/parser.rs index 4a23f24db3..0fec9fb6f4 100644 --- a/module/move/wca/src/ca/parser/parser.rs +++ b/module/move/wca/src/ca/parser/parser.rs @@ -3,9 +3,20 @@ mod private use crate::*; use std::collections::HashMap; + use parser::{ Program, ParsedCommand }; // use error::{ return_err }; + #[ allow( missing_docs ) ] + #[ derive( Debug, error::typed::Error ) ] + pub enum ParserError + { + #[ error( "Internal Error: {details}" ) ] + InternalError { details: String }, + #[ error( "Unexpected input. Expected: {expected}, found {input}" ) ] + UnexpectedInput { expected: String, input: String }, + } + /// `Parser` is a struct used for parsing data. #[ derive( Debug ) ] pub struct Parser; @@ -21,13 +32,14 @@ mod private /// # Returns /// /// Returns a `Result` with a `Program` containing the parsed commands if successful, or an error if parsing fails. - // qqq : use typed error - pub fn parse< As, A >( &self, args : As ) -> error::untyped::Result< Program< ParsedCommand > > + // aaa : use typed error + // aaa : done. + pub fn parse< As, A >( &self, args : As ) -> Result< Program< ParsedCommand >, ParserError > where As : IntoIterator< Item = A >, A : Into< String >, { - let args = args.into_iter().map( Into::into ).collect::< Vec< _ > >(); + let args: Vec< _ > = args.into_iter().map( Into::into ).collect(); let mut commands = vec![]; let mut i = 0; while i < args.len() @@ -54,18 +66,18 @@ mod private } // returns ParsedCommand and relative position of the last parsed item - // qqq : use typed error - fn parse_command( args : &[ String ] ) -> error::untyped::Result< ( ParsedCommand, usize ) > + // aaa : use typed error + fn parse_command( args : &[ String ] ) -> Result< ( ParsedCommand, usize ), ParserError > { if args.is_empty() { - error::untyped::return_err!( "Unexpected behaviour: Try to parse command without input" ); + return Err( ParserError::InternalError { details: "Try to parse command without input".into() } ); } let mut i = 0; if !Self::valid_command_name( &args[ i ] ) { - error::untyped::return_err!( "Unexpected input: Expected a command, found: `{}`", args[ i ] ); + return Err( ParserError::UnexpectedInput { expected: "command".into(), input: args[ i ].clone() } ); } let name = match args[ i ].strip_prefix( '.' ).unwrap() { @@ -91,8 +103,9 @@ mod private } // returns ( subjects, properties, relative_end_pos ) - // qqq : use typed error - fn parse_command_args( args : &[ String ] ) -> error::untyped::Result< ( Vec< String >, HashMap< String, String >, usize ) > + // aaa : use typed error + // aaa : done + fn parse_command_args( args : &[ String ] ) -> Result< ( Vec< String >, HashMap< String, String >, usize ), ParserError > { let mut i = 0; @@ -125,7 +138,7 @@ mod private // prop: else { - error::untyped::return_err!( "Unexpected input '{}': Detected a possible property key preceding the ':' character. However, no corresponding value was found.", item ); + return Err( ParserError::UnexpectedInput { expected: "property value".into(), input: "end of input".into() } ); } } // prop : value | prop :value @@ -146,11 +159,7 @@ mod private // : else { - error::untyped::return_err! - ( - "Unexpected input '{} :': Detected a possible property key preceding the ':' character. However, no corresponding value was found.", - item, - ); + return Err( ParserError::UnexpectedInput { expected: "property value".into(), input: "end of input".into() } ); } } @@ -160,7 +169,7 @@ mod private } else { - error::untyped::return_err!( "Unexpected input: Expected `command` or `property`, found: `{}`", item ); + return Err( ParserError::UnexpectedInput { expected: "`command` or `property`".into(), input: item.into() } ); } i += 1; } @@ -174,5 +183,6 @@ mod private crate::mod_interface! { - exposed use Parser; + orphan use Parser; + orphan use ParserError; } diff --git a/module/move/wca/src/ca/tool/table.rs b/module/move/wca/src/ca/tool/table.rs index 424356530b..4315ee5c8e 100644 --- a/module/move/wca/src/ca/tool/table.rs +++ b/module/move/wca/src/ca/tool/table.rs @@ -81,6 +81,10 @@ mod private .collect() } + #[ derive( Debug, error::typed::Error ) ] + #[ error( "Invalid table" ) ] + pub struct FormatTableError; + /// Formats a table into a readable string representation. /// /// # Arguments @@ -90,15 +94,16 @@ mod private /// # Returns /// /// * `error::untyped::Result` - A `error::untyped::Result` containing the formatted table as a `String`, or an `Error` if the table is invalid. - // qqq : use typed error - pub fn format_table< IntoTable >( table : IntoTable ) -> error::untyped::Result< String > + // aaa : use typed error + // aaa : done + pub fn format_table< IntoTable >( table : IntoTable ) -> Result< String, FormatTableError > where IntoTable : Into< Table >, { let table = table.into(); if !table.validate() { - return Err( error::untyped::format_err!( "Invalid table" ) ); + return Err( FormatTableError ); } let max_lengths = max_column_lengths( &table ); diff --git a/module/move/wca/src/ca/verifier/command.rs b/module/move/wca/src/ca/verifier/command.rs index ef8c2824b9..c945bbb997 100644 --- a/module/move/wca/src/ca/verifier/command.rs +++ b/module/move/wca/src/ca/verifier/command.rs @@ -1,13 +1,14 @@ mod private { use crate::*; + use executor::{ Args, Props }; /// Represents a grammatically correct command with a phrase descriptor, a list of command subjects, and a set of command options. /// /// # Example: /// /// ``` - /// # use wca::{ VerifiedCommand, Value, Args, Props }; + /// # use wca::{ VerifiedCommand, Value, executor::{ Args, Props } }; /// # use std::collections::HashMap; /// VerifiedCommand /// { @@ -46,4 +47,5 @@ crate::mod_interface! exposed use VerifiedCommand; } -// qqq : use orphan instead of exposed for ALL files in the folder, dont use prelude for structs \ No newline at end of file +// aaa : use orphan instead of exposed for ALL files in the folder, dont use prelude for structs +// aaa : done. \ No newline at end of file diff --git a/module/move/wca/src/ca/verifier/verifier.rs b/module/move/wca/src/ca/verifier/verifier.rs index 0202279546..c0636a594b 100644 --- a/module/move/wca/src/ca/verifier/verifier.rs +++ b/module/move/wca/src/ca/verifier/verifier.rs @@ -2,19 +2,55 @@ mod private { use crate::*; - use ca::grammar::command::ValueDescription; - // use former::Former; + use help::{ HelpGeneratorOptions, LevelOfDetail, generate_help_content }; + use grammar::{ Dictionary, Command, command::ValueDescription }; + use executor::{ Args, Props }; use std::collections::HashMap; use indexmap::IndexMap; - // use wtools::{ error, error::Result, err }; - // use error::err; - use ca::help::{ HelpGeneratorOptions, LevelOfDetail, generate_help_content }; + use verifier::VerifiedCommand; + use parser::{ Program, ParsedCommand }; + + #[ allow( missing_docs ) ] + #[ derive( Debug, error::typed::Error ) ] + pub enum VerificationError + { + #[ error + ( + "Command not found. {} {}", + if let Some( phrase ) = name_suggestion { format!( "Maybe you mean `.{phrase}`?" ) } else { "Please use `.` command to see the list of available commands.".into() }, + if let Some( info ) = command_info { format!( "Command info: `{info}`" ) } else { "".into() } + )] + CommandNotFound { name_suggestion: Option< String >, command_info: Option< String > }, + #[ error( "Fail in command `.{command_name}` while processing subjects. {error}" ) ] + Subject { command_name: String, error: SubjectError }, + #[ error( "Fail in command `.{command_name}` while processing properties. {error}" ) ] + Property { command_name: String, error: PropertyError }, + } + + #[ allow( missing_docs ) ] + #[ derive( Debug, error::typed::Error ) ] + pub enum SubjectError + { + #[ error( "Missing not optional subject" ) ] + MissingNotOptional, + #[ error( "Can not identify a subject: `{value}`" ) ] + CanNotIdentify { value: String }, + } + + #[ allow( missing_docs ) ] + #[ derive( Debug, error::typed::Error ) ] + pub enum PropertyError + { + #[ error( "Expected: {description:?}. Found: {input}" ) ] + Cast { description: ValueDescription, input: String }, + } + // xxx /// Converts a `ParsedCommand` to a `VerifiedCommand` by performing validation and type casting on values. /// /// ``` - /// # use wca::{ Command, Type, Verifier, Dictionary, ParsedCommand }; + /// # use wca::{ Type, verifier::Verifier, grammar::{ Dictionary, Command }, parser::ParsedCommand }; /// # use std::collections::HashMap; /// # fn main() -> Result< (), Box< dyn std::error::Error > > /// # { @@ -48,13 +84,15 @@ mod private dictionary : &Dictionary, raw_program : Program< ParsedCommand > ) - -> error::untyped::Result< Program< VerifiedCommand > > - // qqq : use typed error + -> Result< Program< VerifiedCommand >, VerificationError > + // aaa : use typed error + // aaa : done { - let commands = raw_program.commands + let commands: Result< Vec< VerifiedCommand >, VerificationError > = raw_program.commands .into_iter() .map( | n | self.to_command( dictionary, n ) ) - .collect::< error::untyped::Result< Vec< VerifiedCommand > > >()?; + .collect(); + let commands = commands?; Ok( Program { commands } ) } @@ -109,14 +147,15 @@ mod private if Self::is_valid_command_variant( expected_subjects_count, raw_subjects_count, possible_subjects_count ) { Some( variant ) } else { None } } - // qqq : use typed error + // aaa : use typed error + // aaa : done. fn extract_subjects( command : &Command, raw_command : &ParsedCommand, used_properties : &[ &String ] ) -> - error::untyped::Result< Vec< Value > > + Result< Vec< Value >, SubjectError > { let mut subjects = vec![]; - let all_subjects = raw_command + let all_subjects: Vec< _ > = raw_command .subjects.clone().into_iter() .chain ( @@ -124,7 +163,7 @@ mod private .filter( |( key, _ )| !used_properties.contains( key ) ) .map( |( key, value )| format!( "{key}:{value}" ) ) ) - .collect::< Vec< _ > >(); + .collect(); let mut rc_subjects_iter = all_subjects.iter(); let mut current = rc_subjects_iter.next(); @@ -134,20 +173,21 @@ mod private { Some( v ) => v, None if *optional => continue, - _ => return Err( error::untyped::format_err!( "Missing not optional subject" ) ), + _ => return Err( SubjectError::MissingNotOptional ), }; subjects.push( value ); current = rc_subjects_iter.next(); } - if let Some( value ) = current { return Err( error::untyped::format_err!( "Can not identify a subject: `{}`", value ) ) } + if let Some( value ) = current { return Err( SubjectError::CanNotIdentify { value: value.clone() } ) } Ok( subjects ) } - // qqq : use typed error + // aaa : use typed error + // aaa : done. fn extract_properties( command: &Command, raw_command : HashMap< String, String > ) -> - error::untyped::Result< HashMap< String, Value > > + Result< HashMap< String, Value >, PropertyError > { raw_command.into_iter() .filter_map @@ -163,9 +203,9 @@ mod private .map ( |( value_description, key, value )| - value_description.kind.try_cast( value ).map( | v | ( key.clone(), v ) ) + value_description.kind.try_cast( value.clone() ).map( | v | ( key.clone(), v ) ).map_err( | _ | PropertyError::Cast { description: value_description.clone(), input: format!( "{key}: {value}" ) } ) ) - .collect::< error::untyped::Result< HashMap< _, _ > > >() + .collect() } fn group_properties_and_their_aliases< 'a, Ks >( aliases : &'a HashMap< String, String >, used_keys : Ks ) -> Vec< &String > @@ -186,16 +226,17 @@ mod private { reverse_aliases.get( key ).into_iter().flatten().map( | k | *k ).chain( Some( key ) ) }) - .collect::< Vec< _ > >() + .collect() } /// Converts raw command to grammatically correct /// /// Make sure that this command is described in the grammar and matches it(command itself and all it options too). - // qqq : use typed error + // aaa : use typed error + // aaa : done. pub fn to_command( &self, dictionary : &Dictionary, raw_command : ParsedCommand ) -> - error::untyped::Result< VerifiedCommand > + Result< VerifiedCommand, VerificationError > { if raw_command.name.ends_with( '.' ) | raw_command.name.ends_with( ".?" ) { @@ -208,32 +249,31 @@ mod private }); } let command = dictionary.command( &raw_command.name ) - .ok_or_else::< error::untyped::Error, _ > + .ok_or_else::< VerificationError, _ > ( || { #[ cfg( feature = "on_unknown_suggest" ) ] if let Some( phrase ) = Self::suggest_command( dictionary, &raw_command.name ) { - return error::untyped::format_err!( "Command not found. Maybe you mean `.{}`?", phrase ) + return VerificationError::CommandNotFound { name_suggestion: Some( phrase ), command_info: None }; } - error::untyped::format_err!( "Command not found. Please use `.` command to see the list of available commands." ) + VerificationError::CommandNotFound { name_suggestion: None, command_info: None } } )?; let Some( cmd ) = Self::check_command( command, &raw_command ) else { - error::untyped::bail! - ( - "`{}` command with specified subjects not found. Command info: `{}`", - &raw_command.name, - generate_help_content( dictionary, HelpGeneratorOptions::former().for_commands([ dictionary.command( &raw_command.name ).unwrap() ]).command_prefix( "." ).subject_detailing( LevelOfDetail::Detailed ).form() ).strip_suffix( " " ).unwrap() - ); + return Err( VerificationError::CommandNotFound + { + name_suggestion: Some( command.phrase.clone() ), + command_info: Some( generate_help_content( dictionary, HelpGeneratorOptions::former().for_commands([ dictionary.command( &raw_command.name ).unwrap() ]).command_prefix( "." ).subject_detailing( LevelOfDetail::Detailed ).form() ).strip_suffix( " " ).unwrap().into() ), + } ); }; - let properties = Self::extract_properties( cmd, raw_command.properties.clone() )?; + let properties = Self::extract_properties( cmd, raw_command.properties.clone() ).map_err( | e | VerificationError::Property { command_name: cmd.phrase.clone(), error: e } )?; let used_properties_with_their_aliases = Self::group_properties_and_their_aliases( &cmd.properties_aliases, properties.keys() ); - let subjects = Self::extract_subjects( cmd, &raw_command, &used_properties_with_their_aliases )?; + let subjects = Self::extract_subjects( cmd, &raw_command, &used_properties_with_their_aliases ).map_err( | e | VerificationError::Subject { command_name: cmd.phrase.clone(), error: e } )?; Ok( VerifiedCommand { @@ -250,7 +290,8 @@ mod private crate::mod_interface! { - exposed use Verifier; + orphan use Verifier; + orphan use VerificationError; // own use LevelOfDetail; // own use generate_help_content; diff --git a/module/move/wca/tests/inc/adapter.rs b/module/move/wca/tests/inc/adapter.rs deleted file mode 100644 index 33d5cd7e61..0000000000 --- a/module/move/wca/tests/inc/adapter.rs +++ /dev/null @@ -1,44 +0,0 @@ -use super::*; -use the_module::exposed::*; - -tests_impls! -{ - fn simple() - { - fn command( () : (), args : Args, props : Props) -> Result< (), () > - { - Ok( () ) - } - - fn command2( () : (), args : Args, props : Props ) -> Result< (), () > - { - Ok( () ) - } - - fn echo( () : (), args : Args, props : Props ) -> Result< (), () > - { - Ok( () ) - } - - let ca = the_module::cui( () ).command( command ).command( command2 ).command( echo.arg( "string", Type::String ) ).build(); - - a_id!( (), ca.perform( ".command2 .help" ).unwrap() ); - - a_id!( (), ca.perform( ".help command" ).unwrap() ); - a_id!( (), ca.perform( ".help command2" ).unwrap() ); - a_id!( (), ca.perform( ".help help" ).unwrap() ); - - a_id!( (), ca.perform( ".help.command" ).unwrap() ); - a_id!( (), ca.perform( ".help.command2" ).unwrap() ); - a_id!( (), ca.perform( ".help.help" ).unwrap() ); - - a_true!( ca.perform( ".help.help.help" ).is_err() ); - a_true!( ca.perform( ".echo 34" ).is_ok() ); - a_true!( ca.perform( ".echo" ).is_err() ); - } -} - -tests_index! -{ - simple -} diff --git a/module/move/wca/tests/inc/commands_aggregator/basic.rs b/module/move/wca/tests/inc/commands_aggregator/basic.rs index f7019bebf6..6c9ba72c09 100644 --- a/module/move/wca/tests/inc/commands_aggregator/basic.rs +++ b/module/move/wca/tests/inc/commands_aggregator/basic.rs @@ -1,5 +1,14 @@ use super::*; -use the_module::VerifiedCommand; +use the_module:: +{ + parser::Parser, + VerifiedCommand, + CommandsAggregator, + HelpVariants, + Type, + Error, + ValidationError, +}; // @@ -52,8 +61,7 @@ tests_impls! .perform(); a_id!( (), ca.perform( "." ).unwrap() ); - // qqq : this use case is disabled - // a_id!( (), ca.perform( ".cmd." ).unwrap() ); + a_id!( (), ca.perform( ".cmd." ).unwrap() ); } fn error_types() @@ -136,10 +144,10 @@ tests_impls! fn string_subject_with_colon() { - let dictionary = &the_module::Dictionary::former() + let dictionary = &the_module::grammar::Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -150,7 +158,7 @@ tests_impls! ) .perform(); let parser = Parser; - let grammar = the_module::Verifier; + let grammar = the_module::verifier::Verifier; let executor = the_module::Executor::former().form(); let raw_command = parser.parse( [ ".command", "qwe:rty", "nightly:true" ] ).unwrap().commands.remove( 0 ); @@ -163,10 +171,10 @@ tests_impls! fn no_prop_subject_with_colon() { - let dictionary = &the_module::Dictionary::former() + let dictionary = &the_module::grammar::Dictionary::former() .command ( - the_module::Command::former() + the_module::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -177,7 +185,7 @@ tests_impls! .form(); let parser = Parser; - let grammar = the_module::Verifier; + let grammar = the_module::verifier::Verifier; let executor = the_module::Executor::former().form(); let raw_command = parser.parse( [ ".command", "qwe:rty" ] ).unwrap().commands.remove( 0 ); @@ -190,10 +198,10 @@ tests_impls! fn optional_prop_subject_with_colon() { - let dictionary = &the_module::Dictionary::former() + let dictionary = &the_module::grammar::Dictionary::former() .command ( - the_module::Command::former() + the_module::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -205,7 +213,7 @@ tests_impls! .form(); let parser = Parser; - let grammar = the_module::Verifier; + let grammar = the_module::verifier::Verifier; let executor = the_module::Executor::former().form(); let raw_command = parser.parse( [ ".command", "qwe:rty" ] ).unwrap().commands.remove( 0 ); @@ -216,7 +224,8 @@ tests_impls! a_id!( (), executor.command( dictionary, grammar_command ).unwrap() ); } - // qqq : make the following test work + // aaa : make the following test work + // aaa : works fn subject_with_spaces() { let query = "SELECT title, links, MIN( published ) FROM Frames"; diff --git a/module/move/wca/tests/inc/commands_aggregator/callback.rs b/module/move/wca/tests/inc/commands_aggregator/callback.rs index 834426c32d..21910a6560 100644 --- a/module/move/wca/tests/inc/commands_aggregator/callback.rs +++ b/module/move/wca/tests/inc/commands_aggregator/callback.rs @@ -1,5 +1,6 @@ use super::*; use std::sync::{ Arc, Mutex }; +use the_module::CommandsAggregator; #[ test ] fn changes_state_of_local_variable_on_perform() diff --git a/module/move/wca/tests/inc/commands_aggregator/help.rs b/module/move/wca/tests/inc/commands_aggregator/help.rs index 1df2be062e..2ce5a0bca5 100644 --- a/module/move/wca/tests/inc/commands_aggregator/help.rs +++ b/module/move/wca/tests/inc/commands_aggregator/help.rs @@ -1,7 +1,10 @@ -use std::fs::{DirBuilder, File}; -use std::io::Write; -use std::path::Path; -use std::process::{Command, Stdio}; +use std:: +{ + io::Write, + path::Path, + fs::{ DirBuilder, File }, + process::{ Command, Stdio }, +}; pub fn start_sync< AP, Args, Arg, P > ( @@ -11,9 +14,14 @@ pub fn start_sync< AP, Args, Arg, P > ) -> String where AP : AsRef< Path >, Args : IntoIterator< Item = Arg >, Arg : AsRef< std::ffi::OsStr >, P : AsRef< Path >, { let ( application, path ) = ( application.as_ref(), path.as_ref() ); - let args = args.into_iter().map( | a | a.as_ref().into() ).collect::< Vec< std::ffi::OsString > >(); + let args: Vec< std::ffi::OsString > = args.into_iter().map( | a | a.as_ref().into() ).collect(); let child = Command::new( application ).args( &args ).stdout( Stdio::piped() ).stderr( Stdio::piped() ).current_dir( path ).spawn().unwrap(); let output = child.wait_with_output().unwrap(); + + if !output.status.success() + { + println!( "{}", String::from_utf8( output.stderr ).unwrap() ); + } String::from_utf8( output.stdout ).unwrap() } diff --git a/module/move/wca/tests/inc/commands_aggregator/mod.rs b/module/move/wca/tests/inc/commands_aggregator/mod.rs index ca0cdc4b5a..fedda3d681 100644 --- a/module/move/wca/tests/inc/commands_aggregator/mod.rs +++ b/module/move/wca/tests/inc/commands_aggregator/mod.rs @@ -1,16 +1,5 @@ use super::*; -use the_module:: -{ - Parser, - - CommandsAggregator, - HelpVariants, - Type, - Error, - ValidationError, -}; - mod basic; mod callback; mod help; diff --git a/module/move/wca/tests/inc/executor/command.rs b/module/move/wca/tests/inc/executor/command.rs index b1dcf7ac12..e489b90764 100644 --- a/module/move/wca/tests/inc/executor/command.rs +++ b/module/move/wca/tests/inc/executor/command.rs @@ -1,5 +1,15 @@ use super::*; -use the_module::VerifiedCommand; +use the_module:: +{ + parser::Parser, + VerifiedCommand, + executor::Context, Type, + grammar::Dictionary, + verifier::Verifier, + + Executor, + // wtools +}; // @@ -14,7 +24,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -42,7 +52,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -78,7 +88,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -121,7 +131,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "check" ) @@ -137,7 +147,7 @@ tests_impls! ) .form(); let verifier = Verifier; - let mut ctx = wca::Context::new( Mutex::new( 1 ) ); + let mut ctx = wca::executor::Context::new( Mutex::new( 1 ) ); // init executor let executor = Executor::former() .context( ctx ) @@ -160,7 +170,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) diff --git a/module/move/wca/tests/inc/executor/mod.rs b/module/move/wca/tests/inc/executor/mod.rs index 7c84cbf8a3..617cf69b75 100644 --- a/module/move/wca/tests/inc/executor/mod.rs +++ b/module/move/wca/tests/inc/executor/mod.rs @@ -1,17 +1,4 @@ use super::*; -// qqq : rid of global uses in tests -use the_module:: -{ - Parser, - - Context, Type, - Dictionary, - Verifier, - - Executor, - // wtools -}; - mod command; mod program; diff --git a/module/move/wca/tests/inc/executor/program.rs b/module/move/wca/tests/inc/executor/program.rs index de33330259..ef0f63940a 100644 --- a/module/move/wca/tests/inc/executor/program.rs +++ b/module/move/wca/tests/inc/executor/program.rs @@ -1,5 +1,15 @@ use super::*; -use the_module::VerifiedCommand; +use the_module:: +{ + parser::Parser, + VerifiedCommand, + executor::Context, Type, + grammar::Dictionary, + verifier::Verifier, + + Executor, + // wtools +}; // @@ -14,7 +24,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -47,7 +57,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "inc" ) @@ -63,7 +73,7 @@ tests_impls! ) .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "eq" ) @@ -91,7 +101,7 @@ tests_impls! let verifier = Verifier; // starts with 0 - let ctx = wca::Context::new( Mutex::new( 0 ) ); + let ctx = wca::executor::Context::new( Mutex::new( 0 ) ); // init simple executor let executor = Executor::former() .context( ctx ) diff --git a/module/move/wca/tests/inc/grammar/from_command.rs b/module/move/wca/tests/inc/grammar/from_command.rs index 9823236c0c..343cde7ffb 100644 --- a/module/move/wca/tests/inc/grammar/from_command.rs +++ b/module/move/wca/tests/inc/grammar/from_command.rs @@ -1,5 +1,14 @@ use super::*; +use the_module:: +{ + parser::Parser, + + Type, Value, + grammar::Dictionary, + verifier::Verifier, +}; + // tests_impls! @@ -13,7 +22,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -45,7 +54,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -92,7 +101,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -121,7 +130,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -156,7 +165,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -184,7 +193,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -223,7 +232,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -268,7 +277,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -297,7 +306,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -328,7 +337,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) @@ -369,7 +378,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command" ) diff --git a/module/move/wca/tests/inc/grammar/from_program.rs b/module/move/wca/tests/inc/grammar/from_program.rs index 670eaf178c..256fd6dcd9 100644 --- a/module/move/wca/tests/inc/grammar/from_program.rs +++ b/module/move/wca/tests/inc/grammar/from_program.rs @@ -1,5 +1,14 @@ use super::*; +use the_module:: +{ + parser::Parser, + + Type, Value, + grammar::Dictionary, + verifier::Verifier, +}; + // tests_impls! @@ -12,7 +21,7 @@ tests_impls! let dictionary = &Dictionary::former() .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command1" ) @@ -21,7 +30,7 @@ tests_impls! ) .command ( - wca::Command::former() + wca::grammar::Command::former() .hint( "hint" ) .long_hint( "long_hint" ) .phrase( "command2" ) diff --git a/module/move/wca/tests/inc/grammar/mod.rs b/module/move/wca/tests/inc/grammar/mod.rs index 38c94dc114..454495c496 100644 --- a/module/move/wca/tests/inc/grammar/mod.rs +++ b/module/move/wca/tests/inc/grammar/mod.rs @@ -1,12 +1,4 @@ use super::*; -use the_module:: -{ - Parser, - - Type, Value, - Dictionary, - Verifier, -}; mod from_command; mod from_program; diff --git a/module/move/wca/tests/inc/grammar/types.rs b/module/move/wca/tests/inc/grammar/types.rs index 7421fce48f..b04ab6c346 100644 --- a/module/move/wca/tests/inc/grammar/types.rs +++ b/module/move/wca/tests/inc/grammar/types.rs @@ -1,5 +1,5 @@ use super::*; -use wca::TryCast; +use the_module::{ TryCast, Type, Value }; // @@ -134,7 +134,7 @@ tests_impls! let string = Type::List( Type::String.into(), ',' ).try_cast( origin_string.into() ).unwrap(); a_id!( origin_string, string.to_string() ); - // xxx : qqq : that fails now. suggest solution + // xxx clarification is needed : qqq : that fails now. suggest solution // let origin_string = "100;3.14"; // let string = Type::List( Type::Number.into(), ';' ).try_cast( origin_string.into() ).unwrap(); // a_id!( origin_string, string.to_string() ); diff --git a/module/move/wca/tests/inc/mod.rs b/module/move/wca/tests/inc/mod.rs index c2617e9035..b51887947e 100644 --- a/module/move/wca/tests/inc/mod.rs +++ b/module/move/wca/tests/inc/mod.rs @@ -1,10 +1,6 @@ #[ allow( unused_imports ) ] use super::*; -#[ allow( unused_imports ) ] -use the_module::tool::*; -#[ allow( unused_imports ) ] -use std::collections::HashMap; #[ cfg( not( feature = "no_std" ) ) ] mod parser; @@ -15,6 +11,5 @@ mod executor; #[ cfg( not( feature = "no_std" ) ) ] mod commands_aggregator; -// qqq : for Bohdan : why commented out? resolve -// #[ cfg( not( feature = "no_std" ) ) ] -// mod adapter; +// aaa : for Bohdan : why commented out? resolve +// aaa : no longer relevant, so removed diff --git a/module/move/wca/tests/inc/parser/command.rs b/module/move/wca/tests/inc/parser/command.rs index 986ab1d0c0..7f5c1aecf4 100644 --- a/module/move/wca/tests/inc/parser/command.rs +++ b/module/move/wca/tests/inc/parser/command.rs @@ -1,4 +1,5 @@ use super::*; +use the_module::parser::{ ParsedCommand, Parser }; // diff --git a/module/move/wca/tests/inc/parser/mod.rs b/module/move/wca/tests/inc/parser/mod.rs index 456679d11a..617cf69b75 100644 --- a/module/move/wca/tests/inc/parser/mod.rs +++ b/module/move/wca/tests/inc/parser/mod.rs @@ -1,10 +1,4 @@ use super::*; -use wca:: -{ - Program, ParsedCommand, - - Parser, -}; mod command; mod program; diff --git a/module/move/wca/tests/inc/parser/program.rs b/module/move/wca/tests/inc/parser/program.rs index 081f8cc3e8..04b07c322f 100644 --- a/module/move/wca/tests/inc/parser/program.rs +++ b/module/move/wca/tests/inc/parser/program.rs @@ -1,4 +1,5 @@ use super::*; +use the_module::parser::{ Program, ParsedCommand, Parser }; //