rbfmt 0.0.2

Ruby code formatter
Documentation
use crate::fmt;

use super::method_calls;

impl<'src> super::Parser<'src> {
    pub(super) fn parse_variable_assign(
        &mut self,
        name_loc: prism::Location,
        operator_loc: prism::Location,
        value: prism::Node,
    ) -> fmt::Node {
        let name = Self::source_lossy_at(&name_loc);
        let operator = Self::source_lossy_at(&operator_loc);
        let value = self.parse(value, None);
        let target = fmt::Node::new(fmt::Kind::Atom(fmt::Atom(name)));
        let assign = fmt::Assign::new(target, operator, value);
        fmt::Node::new(fmt::Kind::Assign(assign))
    }

    pub(super) fn parse_constant_path_assign(
        &mut self,
        const_path: prism::ConstantPathNode,
        operator_loc: prism::Location,
        value: prism::Node,
    ) -> fmt::Node {
        let target = self.parse_constant_path(const_path.parent(), const_path.child());
        let operator = Self::source_lossy_at(&operator_loc);
        let value = self.parse(value, None);
        let assign = fmt::Assign::new(target, operator, value);
        fmt::Node::new(fmt::Kind::Assign(assign))
    }

    pub(super) fn parse_call_assign(
        &mut self,
        call: &impl method_calls::CallRoot,
        operator_loc: prism::Location,
        value: prism::Node,
    ) -> fmt::Node {
        let target = self.parse_call_root(call);
        let operator = Self::source_lossy_at(&operator_loc);
        let value = self.parse(value, None);
        let assign = fmt::Assign::new(target, operator, value);
        fmt::Node::new(fmt::Kind::Assign(assign))
    }

    pub(super) fn parse_multi_assign(&mut self, node: prism::MultiWriteNode) -> fmt::Node {
        let target = self.parse_multi_assign_target(
            node.lefts(),
            node.rest(),
            node.rights(),
            node.lparen_loc(),
            node.rparen_loc(),
        );
        let operator = Self::source_lossy_at(&node.operator_loc());
        let value = self.parse(node.value(), None);
        let assign = fmt::Assign::new(target, operator, value);
        fmt::Node::new(fmt::Kind::Assign(assign))
    }

    pub(super) fn parse_multi_assign_target(
        &mut self,
        lefts: prism::NodeList,
        rest: Option<prism::Node>,
        rights: prism::NodeList,
        lparen_loc: Option<prism::Location>,
        rparen_loc: Option<prism::Location>,
    ) -> fmt::Node {
        let lparen = lparen_loc.as_ref().map(Self::source_lossy_at);
        let rparen = rparen_loc.as_ref().map(Self::source_lossy_at);
        let mut multi = fmt::MultiAssignTarget::new(lparen, rparen);

        let implicit_rest = rest
            .as_ref()
            .map_or(false, |r| matches!(r, prism::Node::ImplicitRestNode { .. }));
        multi.set_implicit_rest(implicit_rest);

        let rest_start = if implicit_rest {
            None
        } else {
            rest.as_ref().map(|r| r.location().start_offset())
        };
        let rights_first_start = rights.iter().next().map(|n| n.location().start_offset());
        let rparen_start = rparen_loc.as_ref().map(|l| l.start_offset());

        let left_trailing_end = rest_start.or(rights_first_start).or(rparen_start);
        Self::each_node_with_trailing_end(lefts.iter(), left_trailing_end, |node, trailing_end| {
            let target = self.parse(node, trailing_end);
            multi.append_target(target);
        });

        if !implicit_rest {
            if let Some(rest) = rest {
                let rest_trailing_end = rights_first_start.or(rparen_start);
                let target = self.parse(rest, rest_trailing_end);
                multi.append_target(target);
            }
        }

        Self::each_node_with_trailing_end(rights.iter(), rparen_start, |node, trailing_end| {
            let target = self.parse(node, trailing_end);
            multi.append_target(target);
        });

        if let Some(rparen_loc) = rparen_loc {
            let virtual_end = self.take_end_trivia_as_virtual_end(Some(rparen_loc.start_offset()));
            multi.set_virtual_end(virtual_end);
        }

        fmt::Node::new(fmt::Kind::MultiAssignTarget(multi))
    }
}