use full_moon::ast::{
BinOp, BinOpRhs, Expression, Index, Prefix, Suffix, UnOp, Value, Var, VarExpression,
};
use full_moon::tokenizer::TokenReference;
use std::boxed::Box;
#[cfg(feature = "luau")]
use crate::formatters::luau_formatter;
use crate::formatters::{functions_formatter, table_formatter, CodeFormatter};
pub fn format_binop<'ast>(code_formatter: &CodeFormatter, binop: BinOp<'ast>) -> BinOp<'ast> {
match binop {
BinOp::And(token) => BinOp::And(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" and ").unwrap()),
),
BinOp::Caret(token) => BinOp::Caret(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" ^ ").unwrap()),
),
BinOp::GreaterThan(token) => BinOp::GreaterThan(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" > ").unwrap()),
),
BinOp::GreaterThanEqual(token) => BinOp::GreaterThanEqual(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" >= ").unwrap()),
),
BinOp::LessThan(token) => BinOp::LessThan(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" < ").unwrap()),
),
BinOp::LessThanEqual(token) => BinOp::LessThanEqual(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" <= ").unwrap()),
),
BinOp::Minus(token) => BinOp::Minus(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" - ").unwrap()),
),
BinOp::Or(token) => BinOp::Or(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" or ").unwrap()),
),
BinOp::Percent(token) => BinOp::Percent(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" % ").unwrap()),
),
BinOp::Plus(token) => BinOp::Plus(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" + ").unwrap()),
),
BinOp::Slash(token) => BinOp::Slash(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" / ").unwrap()),
),
BinOp::Star(token) => BinOp::Star(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" * ").unwrap()),
),
BinOp::TildeEqual(token) => BinOp::TildeEqual(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" ~= ").unwrap()),
),
BinOp::TwoDots(token) => BinOp::TwoDots(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" .. ").unwrap()),
),
BinOp::TwoEqual(token) => BinOp::TwoEqual(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol(" == ").unwrap()),
),
}
}
pub fn format_bin_op_rhs<'ast>(
code_formatter: &mut CodeFormatter,
bin_op_rhs: BinOpRhs<'ast>,
) -> BinOpRhs<'ast> {
BinOpRhs::new(
format_binop(code_formatter, bin_op_rhs.bin_op().to_owned()),
Box::new(format_expression(
code_formatter,
bin_op_rhs.rhs().to_owned(),
)),
)
}
pub fn format_expression<'ast>(
code_formatter: &mut CodeFormatter,
expression: Expression<'ast>,
) -> Expression<'ast> {
match expression {
Expression::Value {
value,
binop,
#[cfg(feature = "luau")]
as_assertion,
} => Expression::Value {
value: Box::new(format_value(code_formatter, *value)),
binop: match binop {
Some(value) => Some(format_bin_op_rhs(code_formatter, value)),
None => None,
},
#[cfg(feature = "luau")]
as_assertion: match as_assertion {
Some(assertion) => Some(luau_formatter::format_as_assertion(
code_formatter,
assertion,
)),
None => None,
},
},
Expression::Parentheses {
contained,
expression,
} => Expression::Parentheses {
contained: code_formatter.format_contained_span(contained),
expression: Box::new(format_expression(code_formatter, *expression)),
},
Expression::UnaryOperator { unop, expression } => Expression::UnaryOperator {
unop: format_unop(code_formatter, unop),
expression: Box::new(format_expression(code_formatter, *expression)),
},
}
}
pub fn format_index<'ast>(code_formatter: &mut CodeFormatter, index: Index<'ast>) -> Index<'ast> {
match index {
Index::Brackets {
brackets,
expression,
} => Index::Brackets {
brackets: code_formatter.format_contained_span(brackets),
expression: format_expression(code_formatter, expression),
},
Index::Dot { dot, name } => Index::Dot {
dot: code_formatter.format_token_reference(dot),
name: code_formatter.format_token_reference(name),
},
}
}
pub fn format_prefix<'ast>(
code_formatter: &mut CodeFormatter,
prefix: Prefix<'ast>,
) -> Prefix<'ast> {
match prefix {
Prefix::Expression(expression) => {
Prefix::Expression(format_expression(code_formatter, expression))
}
Prefix::Name(token_reference) => {
Prefix::Name(code_formatter.format_token_reference(token_reference))
}
}
}
pub fn format_suffix<'ast>(
code_formatter: &mut CodeFormatter,
suffix: Suffix<'ast>,
) -> Suffix<'ast> {
match suffix {
Suffix::Call(call) => Suffix::Call(functions_formatter::format_call(code_formatter, call)),
Suffix::Index(index) => Suffix::Index(format_index(code_formatter, index)),
}
}
pub fn format_value<'ast>(code_formatter: &mut CodeFormatter, value: Value<'ast>) -> Value<'ast> {
match value {
Value::Function((token_reference, function_body)) => {
Value::Function(functions_formatter::format_anonymous_function(
code_formatter,
token_reference,
function_body,
))
}
Value::FunctionCall(function_call) => Value::FunctionCall(
functions_formatter::format_function_call(code_formatter, function_call),
),
Value::Number(token_reference) => {
Value::Number(code_formatter.format_token_reference(token_reference))
}
Value::ParseExpression(expression) => {
Value::ParseExpression(format_expression(code_formatter, expression))
}
Value::String(token_reference) => {
Value::String(code_formatter.format_token_reference(token_reference))
}
Value::Symbol(token_reference) => {
Value::Symbol(code_formatter.format_token_reference(token_reference))
}
Value::TableConstructor(table_constructor) => Value::TableConstructor(
table_formatter::format_table_constructor(code_formatter, table_constructor),
),
Value::Var(var) => Value::Var(format_var(code_formatter, var)),
}
}
pub fn format_var<'ast>(code_formatter: &mut CodeFormatter, var: Var<'ast>) -> Var<'ast> {
match var {
Var::Name(token_reference) => {
Var::Name(code_formatter.format_token_reference(token_reference))
}
Var::Expression(var_expression) => {
Var::Expression(format_var_expression(code_formatter, var_expression))
}
}
}
pub fn format_var_expression<'ast>(
code_formatter: &mut CodeFormatter,
var_expression: VarExpression<'ast>,
) -> VarExpression<'ast> {
let formatted_prefix = format_prefix(code_formatter, var_expression.prefix().to_owned());
let formatted_suffixes = var_expression
.iter_suffixes()
.map(|x| format_suffix(code_formatter, x.to_owned()))
.collect();
var_expression
.with_prefix(formatted_prefix)
.with_suffixes(formatted_suffixes)
}
pub fn format_unop<'ast>(code_formatter: &CodeFormatter, unop: UnOp<'ast>) -> UnOp<'ast> {
match unop {
UnOp::Minus(token) => UnOp::Minus(
code_formatter.format_symbol(token.into_owned(), TokenReference::symbol("-").unwrap()),
),
UnOp::Not(token) => UnOp::Not(
code_formatter
.format_symbol(token.into_owned(), TokenReference::symbol("not ").unwrap()),
),
UnOp::Hash(token) => UnOp::Hash(
code_formatter.format_symbol(token.into_owned(), TokenReference::symbol("#").unwrap()),
),
}
}