use super::super::{Token, TokenArgument, TryFromArgumentGroup};
use super::{LoopControl, TokenDeserialize};
use df_ls_core::Choose;
use df_ls_diagnostics::{hash_map, DMExtraInfo, DiagnosticsInfo};
use df_ls_lexical_analysis::TreeCursor;
impl<T1, T2> TokenDeserialize for Choose<T1, T2>
where
T1: Default + TryFromArgumentGroup,
T2: Default + TryFromArgumentGroup,
{
fn deserialize_tokens(
cursor: &mut TreeCursor,
source: &str,
diagnostics: &mut DiagnosticsInfo,
) -> Result<Box<Self>, ()> {
let mut token = match Token::deserialize_tokens(cursor, source, diagnostics) {
Ok(token) => token,
Err(err) => {
Token::consume_token(cursor)?;
return Err(err);
}
};
Token::consume_token(cursor)?;
token.check_token_name(source, diagnostics, true)?;
let result = Self::try_from_argument_group(&mut token, source, diagnostics, true);
if result.is_ok() {
token.check_all_arg_consumed(source, diagnostics, true)?;
} else {
crate::mark_rest_of_token_as_unchecked(diagnostics, &token);
}
Ok(Box::new(result?))
}
fn deserialize_general_token(
_cursor: &mut TreeCursor,
_source: &str,
_diagnostics: &mut DiagnosticsInfo,
new_self: Box<Self>,
) -> (LoopControl, Box<Self>) {
(LoopControl::DoNothing, new_self)
}
fn get_vec_loopcontrol() -> LoopControl {
LoopControl::DoNothing
}
fn get_allowed_tokens() -> Option<Vec<String>> {
None
}
}
impl<T1, T2> TryFromArgumentGroup for Choose<T1, T2>
where
T1: TryFromArgumentGroup,
T2: TryFromArgumentGroup,
{
fn try_from_argument_group(
token: &mut Token,
source: &str,
diagnostics: &mut DiagnosticsInfo,
add_diagnostics_on_err: bool,
) -> Result<Self, ()> {
let mut token_clone1 = token.clone();
let mut token_clone2 = token.clone();
let option1 = T1::try_from_argument_group(&mut token_clone1, source, diagnostics, false);
let option2 = T2::try_from_argument_group(&mut token_clone2, source, diagnostics, false);
if option1.is_ok() {
let result =
T1::try_from_argument_group(token, source, diagnostics, add_diagnostics_on_err)?;
Ok(Choose::Choice1(result))
} else if option2.is_ok() {
let result =
T2::try_from_argument_group(token, source, diagnostics, add_diagnostics_on_err)?;
Ok(Choose::Choice2(result))
} else {
if add_diagnostics_on_err {
let current_arg = token.get_current_arg()?;
diagnostics.add_message(
DMExtraInfo {
range: current_arg.node.get_range(),
message_template_data: hash_map! {
"expected_parameters" => "One or multiple arguments".to_owned(),
"found_parameters" => current_arg.value.argument_to_token_type_name(),
},
},
"wrong_arg_type",
);
}
token.consume_argument();
Err(())
}
}
}
impl<T1, T2> From<Choose<T1, T2>> for TokenArgument
where
TokenArgument: From<T1>,
TokenArgument: From<T2>,
{
fn from(item: Choose<T1, T2>) -> TokenArgument {
match item {
Choose::Choice1(v) => TokenArgument::from(v),
Choose::Choice2(v) => TokenArgument::from(v),
}
}
}
impl<T1, T2> From<Option<Choose<T1, T2>>> for TokenArgument
where
TokenArgument: From<T1>,
TokenArgument: From<T2>,
{
fn from(item: Option<Choose<T1, T2>>) -> TokenArgument {
match item {
Some(item) => match item {
Choose::Choice1(v) => TokenArgument::from(v),
Choose::Choice2(v) => TokenArgument::from(v),
},
None => TokenArgument::TVEmpty,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_tree_structure;
use crate::test_utils::SyntaxTestBuilder;
use df_ls_lexical_analysis::test_utils::LexerTestBuilder;
#[test]
fn test_choose_correct() {
let test_builder = SyntaxTestBuilder::from_lexer_test_builder(
LexerTestBuilder::test_source(
"header
[REF:string]
[REF:83]",
)
.add_test_lexer_diagnostics_codes(vec![])
.add_test_lexer_diagnostics_ranges(vec![]),
)
.add_test_syntax_diagnostics_codes(vec![])
.add_test_syntax_diagnostics_ranges(vec![]);
test_tree_structure!(
test_builder,
[
Choose<u8, String> => Choose::Choice2("string".to_owned()),
Choose<u8, String> => Choose::Choice1(83u8),
]
);
}
#[test]
fn test_choose_enum_correct() {
let test_builder = SyntaxTestBuilder::from_lexer_test_builder(
LexerTestBuilder::test_source(
"header
[REF:string]
[REF:83]",
)
.add_test_lexer_diagnostics_codes(vec![])
.add_test_lexer_diagnostics_ranges(vec![]),
)
.add_test_syntax_diagnostics_codes(vec![])
.add_test_syntax_diagnostics_ranges(vec![]);
test_tree_structure!(
test_builder,
[
(Choose<u8, String>,) => (Choose::Choice2("string".to_owned()),),
(Choose<u8, String>,) => (Choose::Choice1(83u8),),
]
);
}
}