use super::TokenArgument;
use df_ls_diagnostics::{hash_map, DMExtraInfo, DiagnosticsInfo};
use df_ls_lexical_analysis::{Node, TreeCursor};
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Token {
pub node: Option<Node>,
pub(crate) name: Option<TokenName>,
pub(crate) arguments: Vec<Argument>,
pub current_argument_index: usize,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TokenName {
pub node: Node,
pub value: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Argument {
pub node: Node,
pub value: TokenArgument,
}
impl Token {
pub fn get_token_name(&self) -> Result<&TokenName, ()> {
match &self.name {
Some(v) => Ok(v),
None => Err(()),
}
}
pub fn get_argument(&self, index: usize) -> Result<&Argument, ()> {
match self.arguments.get(index) {
Some(v) => Ok(v),
None => Err(()),
}
}
pub fn get_current_arg(&self) -> Result<&Argument, ()> {
match self.arguments.get(self.current_argument_index) {
Some(v) => Ok(v),
None => Err(()),
}
}
pub fn get_current_arg_opt(&self) -> Option<&Argument> {
self.arguments.get(self.current_argument_index)
}
pub fn get_previous_arg_opt(&self) -> Option<&Argument> {
if self.current_argument_index < 1 {
return None;
}
self.arguments.get(self.current_argument_index - 1)
}
pub fn get_last_arg_opt(&self) -> Option<&Argument> {
self.arguments.last()
}
pub fn checked_get_token_name(
&self,
source: &str,
diagnostics: &mut DiagnosticsInfo,
add_diagnostics_on_err: bool,
) -> Result<TokenName, ()> {
self.check_token_name(source, diagnostics, add_diagnostics_on_err)?;
self.get_token_name().cloned()
}
pub fn checked_get_current_arg(
&self,
_source: &str,
diagnostics: &mut DiagnosticsInfo,
add_diagnostics_on_err: bool,
) -> Result<Argument, ()> {
match self.arguments.get(self.current_argument_index) {
Some(arg) => Ok(arg.clone()),
None => {
if add_diagnostics_on_err {
diagnostics.add_message(
DMExtraInfo {
range: self.node.as_ref().unwrap().get_range(),
message_template_data: hash_map! {
"expected_parameters_num" => (self.current_argument_index+1).to_string(),
"found_parameters_num" => self.arguments.len().to_string(),
},
},
"wrong_arg_number",
);
}
Err(())
}
}
}
pub fn consume_argument(&mut self) {
self.current_argument_index += 1;
}
pub fn check_as_required_argument(
&self,
_source: &str,
diagnostics: &mut DiagnosticsInfo,
add_diagnostics_on_err: bool,
) -> Result<(), ()> {
if self.get_current_arg_opt().is_some() {
Ok(())
} else if add_diagnostics_on_err {
diagnostics.add_message(
DMExtraInfo {
range: self.node.as_ref().unwrap().get_range(),
message_template_data: hash_map! {
"expected_parameters_num" => format!("at least {}", self.current_argument_index+1),
"found_parameters_num" => self.arguments.len().to_string(),
},
},
"wrong_arg_number",
);
Err(())
} else {
Err(())
}
}
pub fn check_all_arg_consumed(
&self,
_source: &str,
diagnostics: &mut DiagnosticsInfo,
add_diagnostics_on_err: bool,
) -> Result<(), ()> {
if self.current_argument_index == self.arguments.len() {
Ok(())
} else if add_diagnostics_on_err {
log::error!("err in check_all_arg_consumed");
diagnostics.add_message(
DMExtraInfo {
range: self.node.as_ref().unwrap().get_range(),
message_template_data: hash_map! {
"expected_parameters_num" => self.current_argument_index.to_string(),
"found_parameters_num" => self.arguments.len().to_string(),
},
},
"wrong_arg_number",
);
Err(())
} else {
Err(())
}
}
pub fn check_token_name(
&self,
_source: &str,
diagnostics: &mut DiagnosticsInfo,
add_diagnostics_on_err: bool,
) -> Result<(), ()> {
let token_name = if let Some(token_name) = &self.name {
token_name
} else {
if add_diagnostics_on_err {
diagnostics.add_message(
DMExtraInfo::new(self.node.as_ref().unwrap().get_range()),
"missing_token_name",
);
}
return Err(());
};
if token_name.value.is_empty() {
if add_diagnostics_on_err {
diagnostics.add_message(
DMExtraInfo::new(self.node.as_ref().unwrap().get_range()),
"missing_token_name",
);
}
return Err(());
}
Ok(())
}
pub fn consume_token(cursor: &mut TreeCursor) -> Result<(), ()> {
match cursor.goto_next_sibling() {
true => Ok(()),
false => Err(()),
}
}
}
impl From<TokenName> for Argument {
fn from(item: TokenName) -> Self {
Argument {
node: item.node,
value: TokenArgument::TVReference(item.value),
}
}
}
impl From<&TokenName> for Argument {
fn from(item: &TokenName) -> Self {
Argument {
node: item.node.clone(),
value: TokenArgument::TVReference(item.value.clone()),
}
}
}