Skip to content

Commit

Permalink
done
Browse files Browse the repository at this point in the history
  • Loading branch information
Barsik-sus committed Nov 18, 2024
1 parent aad89b6 commit c982e41
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 31 deletions.
4 changes: 2 additions & 2 deletions module/move/wca/src/ca/aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ mod private
},
help::{ HelpGeneratorFn, HelpGeneratorOptions, HelpVariants },
};
use verifier::{ Verifier, VerifiedCommand };
use verifier::{ Verifier, VerificationError, VerifiedCommand };
use parser::{ Program, Parser, ParserError };
use grammar::Dictionary;
use executor::Context;
Expand Down Expand Up @@ -59,7 +59,7 @@ mod private
},
/// 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 ),
Expand Down
93 changes: 64 additions & 29 deletions module/move/wca/src/ca/verifier/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,49 @@ mod private
{
use crate::*;

use ca::
{
grammar::command::ValueDescription,
help::{ HelpGeneratorOptions, LevelOfDetail, generate_help_content },
};
use grammar::{ Dictionary, Command };
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 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.
Expand Down Expand Up @@ -53,10 +84,11 @@ 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: error::untyped::Result< Vec< VerifiedCommand > > = raw_program.commands
let commands: Result< Vec< VerifiedCommand >, VerificationError > = raw_program.commands
.into_iter()
.map( | n | self.to_command( dictionary, n ) )
.collect();
Expand Down Expand Up @@ -115,10 +147,11 @@ 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![];

Expand All @@ -140,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
Expand All @@ -169,7 +203,7 @@ 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()
}
Expand Down Expand Up @@ -198,10 +232,11 @@ mod private
/// 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( ".?" )
{
Expand All @@ -214,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
{
Expand All @@ -257,6 +291,7 @@ mod private
crate::mod_interface!
{
orphan use Verifier;
orphan use VerificationError;

// own use LevelOfDetail;
// own use generate_help_content;
Expand Down

0 comments on commit c982e41

Please sign in to comment.