1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
use swc_ecmascript::ast::*; use swc_ecmascript::parser::{token::{TokenAndSpan}}; use super::*; use super::super::*; use super::super::super::configuration::*; pub struct BinExprItem<'a> { pub pre_op: Option<BinExprOp<'a>>, pub post_op: Option<BinExprOp<'a>>, pub expr: Node<'a>, } #[derive(Clone)] pub struct BinExprOp<'a> { pub token: &'a TokenAndSpan, pub op: BinaryOp, } pub fn get_flattened_bin_expr<'a>(node: &'a BinExpr, context: &mut Context<'a>) -> Vec<BinExprItem<'a>> { let mut items = Vec::new(); let operator_token = BinExprOp { token: context.token_finder.get_first_operator_after(&*node.left, node.op.as_str()).unwrap(), op: node.op, }; let is_op_same_line = get_operator_position(&node, &operator_token.token, context) == OperatorPosition::SameLine; let mut handled_left = false; let mut handled_right = false; if let Expr::Bin(left_bin) = &*node.left { if is_expression_breakable(&node.op, &left_bin.op) { items.extend(get_flattened_bin_expr(left_bin, context)); if is_op_same_line { items.last_mut().unwrap().post_op = Some(operator_token.clone()); } handled_left = true; } } if !handled_left { items.push(BinExprItem { pre_op: None, post_op: if is_op_same_line { Some(operator_token.clone()) } else { None }, expr: (&*node.left).into(), }); } if let Expr::Bin(right_bin) = &*node.right { if is_expression_breakable(&node.op, &right_bin.op) { let mut right_items = get_flattened_bin_expr(right_bin, context); if !is_op_same_line { right_items.first_mut().unwrap().pre_op = Some(operator_token.clone()); } items.extend(right_items); handled_right = true; } } if !handled_right { items.push(BinExprItem { pre_op: if !is_op_same_line { Some(operator_token) } else { None }, post_op: None, expr: (&*node.right).into(), }); } return items; fn is_expression_breakable(top_op: &BinaryOp, op: &BinaryOp) -> bool { if top_op.is_add_sub() { op.is_add_sub() } else if top_op.is_mul_div() { op.is_mul_div() } else { top_op == op } } fn get_operator_position(node: &BinExpr, operator_token: &TokenAndSpan, context: &mut Context) -> OperatorPosition { match context.config.binary_expression_operator_position { OperatorPosition::NextLine => OperatorPosition::NextLine, OperatorPosition::SameLine => OperatorPosition::SameLine, OperatorPosition::Maintain => { if node.left.end_line(context) == operator_token.start_line(context) { OperatorPosition::SameLine } else { OperatorPosition::NextLine } } } } }