df_ls_syntax_analysis 0.3.0-rc.1

A language server for Dwarf Fortress RAW files
Documentation
use super::super::{Argument, Token, TryFromArgument, TryFromArgumentGroup};
use super::{LoopControl, TokenDeserialize};
use df_ls_diagnostics::{hash_map, DMExtraInfo, DiagnosticsInfo};
use df_ls_lexical_analysis::TreeCursor;

/// Deserialize a token with following pattern: `[REF]`
impl TokenDeserialize for () {
    fn deserialize_tokens(
        cursor: &mut TreeCursor,
        source: &str,
        diagnostics: &mut DiagnosticsInfo,
    ) -> Result<Box<Self>, ()> {
        // Get arguments from token
        let token = match Token::deserialize_tokens(cursor, source, diagnostics) {
            Ok(token) => token,
            Err(err) => {
                // When token could not be parsed correctly.
                // Token could not be parsed, so we can consume it.
                // Because this will always fail.
                Token::consume_token(cursor)?;
                return Err(err);
            }
        };
        Token::consume_token(cursor)?;
        // Token Name
        token.check_token_name(source, diagnostics, true)?;
        // Does not expect any arguments except for token name
        token.check_all_arg_consumed(source, diagnostics, true)?;
        Ok(Box::new(()))
    }

    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
    }
}

// ------------------------- Convert a group of arguments to Self -----------------------

impl TryFromArgumentGroup for () {
    fn try_from_argument_group(
        token: &mut Token,
        source: &str,
        diagnostics: &mut DiagnosticsInfo,
        add_diagnostics_on_err: bool,
    ) -> Result<Self, ()> {
        let arg_opt = token.get_current_arg_opt();
        Self::try_from_argument(arg_opt, source, diagnostics, add_diagnostics_on_err)
    }
}

// -------------------------Convert one argument to Self -----------------------

impl TryFromArgument for () {
    fn try_from_argument(
        arg_opt: Option<&Argument>,
        _source: &str,
        diagnostics: &mut DiagnosticsInfo,
        add_diagnostics_on_err: bool,
    ) -> Result<Self, ()> {
        if let Some(arg) = arg_opt {
            if add_diagnostics_on_err {
                diagnostics.add_message(
                    DMExtraInfo {
                        range: arg.node.get_range(),
                        message_template_data: hash_map! {
                            "expected_parameters" => Self::expected_argument_types(),
                            "found_parameters" => arg.value.argument_to_token_type_name(),
                        },
                    },
                    "wrong_arg_type",
                );
            }
            Err(())
        } else {
            Ok(())
        }
    }

    fn expected_argument_types() -> String {
        "No arguments".to_owned()
    }
}

// Prevent having to copy post following code with little changes
// for each of the tuple amount
macro_rules! token_de_tuples {
    ( $($x:ident,)+ ) => {
        /// Deserialize a token with following pattern: `[REF:..:..:..]`
        impl<$($x),+> TokenDeserialize for ($($x,)+)
        where
            $(
                $x: Default + TryFromArgumentGroup,
            )+
        {
            fn deserialize_tokens(
                cursor: &mut TreeCursor,
                source: &str,
                diagnostics: &mut DiagnosticsInfo,
            ) -> Result<Box<Self>, ()> {
                // Check that is has no additional arguments
                let mut token = match Token::deserialize_tokens(cursor, source, diagnostics){
                    Ok(token) => token,
                    Err(err) => {
                        // When token could not be parsed correctly.
                        // Token could not be parsed, so we can consume it.
                        // Because this will always fail.
                        Token::consume_token(cursor)?;
                        return Err(err);
                    }
                };
                Token::consume_token(cursor)?;
                // Token Name
                token.check_token_name(source, diagnostics, true)?;

                // Check all next arguments
                let result =
                    Self::try_from_argument_group(&mut token, source, diagnostics, true);
                // Mark any let over arguments as unchecked.
                if result.is_err() {
                    // In case of an error, mark other arguments as unchecked.
                    crate::mark_rest_of_token_as_unchecked(diagnostics, &token);
                }
                // If error in one of the arguments is not correct
                // it might not have consumed them all.
                // So early error out, so `check_all_arg_consumed` is only checked
                // if all arguments are correct.
                let result = result?;
                token.check_all_arg_consumed(source, diagnostics, true)?;
                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
            }
        }

        // ------------------------- Convert a group of arguments to Self -----------------------

        impl<$($x),+> TryFromArgumentGroup for ($($x,)+)
        where
            $(
                $x: Default + TryFromArgumentGroup,
            )+
        {
            fn try_from_argument_group(
                mut token: &mut Token,
                source: &str,
                mut diagnostics: &mut DiagnosticsInfo,
                add_diagnostics_on_err: bool,
            ) -> Result<Self, ()> {
                // Check all next arguments
                let result = (
                    $(
                        {
                            $x::try_from_argument_group(&mut token,
                                source,
                                &mut diagnostics,
                                add_diagnostics_on_err,
                            )?
                        },
                    )+
                );
                Ok(result)
            }
        }

        // -------------------------Convert one argument to Self -----------------------
        // TryFromArgument is not used, use TryFromArgumentGroup instead
    };
}

token_de_tuples!(T1,);
token_de_tuples!(T1, T2,);
token_de_tuples!(T1, T2, T3,);
token_de_tuples!(T1, T2, T3, T4,);
token_de_tuples!(T1, T2, T3, T4, T5,);
token_de_tuples!(T1, T2, T3, T4, T5, T6,);
token_de_tuples!(T1, T2, T3, T4, T5, T6, T7,);
token_de_tuples!(T1, T2, T3, T4, T5, T6, T7, T8,);
token_de_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9,);
token_de_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,);
token_de_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,);
token_de_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,);