Skip to content

Commit

Permalink
feat: implemented formatting of conditionals
Browse files Browse the repository at this point in the history
  • Loading branch information
kpagacz committed Apr 14, 2024
1 parent cf7960d commit d54fc2e
Show file tree
Hide file tree
Showing 19 changed files with 193 additions and 40 deletions.
116 changes: 113 additions & 3 deletions formatter/src/code.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::config::FormattingConfig;

use log::trace;
use parser::ast::Expression;
use parser::ast::{Expression, IfConditional};
use tokenizer::tokens::CommentedToken;

use crate::format::{Doc, GroupDocProperties, ShouldBreak};
Expand Down Expand Up @@ -279,11 +279,121 @@ impl<'a> Code for Expression<'a> {
let body_doc = body.to_docs(config);

let keyword_plus_args_part = group!(cons!(keyword, args_with_delimiter));
group!(cons!(keyword_plus_args_part, body_doc), ShouldBreak::Yes)
group!(cons!(keyword_plus_args_part, body_doc), ShouldBreak::No)
},
Expression::IfExpression(_) => todo!()
Expression::IfExpression(if_expression) => {
let (if_conditional, else_ifs, trailing_else) = (&if_expression.if_conditional, &if_expression.else_ifs, &if_expression.trailing_else);
let mut docs = Rc::new(Doc::Nil);
let (conditional_docs, mut conditional_suffix) = if_conditional_to_docs(Rc::new(Doc::Nil), if_conditional, config);
docs = cons!(docs, conditional_docs);
// if (<potential_break>condition<potential_break>) [{]<potential_break>
// body<potential_break>
// } else if(<potential_break>...) {
// } else if(...) { ...
for else_if in else_ifs {
let (&keyword, body) = (&else_if.else_keyword, &else_if.if_conditional);
let prefix = cons!(cons!(conditional_suffix, text!(" ")), keyword.to_docs(config));
let (else_if_docs, new_suffix) = if_conditional_to_docs(prefix, body, config);
docs = cons!(docs, else_if_docs);
conditional_suffix = new_suffix;
}
if let Some(trailing_else) = trailing_else {
match trailing_else.body.as_ref() {
Expression::Term(term_expr) if term_expr.pre_delimiters.is_some() => {
let mut new_group = cons!(cons!(conditional_suffix, text!(" ")), cons!(trailing_else.else_keyword.to_docs(config), text!(" ")));
match (term_expr.pre_delimiters, term_expr.post_delimiters) {
(Some(pre_delim), Some(post_delim)) => {
if term_expr.term.is_empty() {
conditional_suffix = cons!(new_group, cons!(pre_delim.to_docs(config), post_delim.to_docs(config)));
} else {
new_group = cons!(new_group, pre_delim.to_docs(config));
new_group = group!(new_group);
new_group = cons!(new_group, nl!(" "));
let mut body_doc = join_docs(
term_expr.term.iter().map(|t| t.to_docs(config)),
Rc::new(Doc::Nil),
ShouldBreak::Yes,
config,
);
body_doc = cons!(body_doc, nl!(" "));
docs = cons!(docs, group!(cons!(new_group, body_doc)));
conditional_suffix = post_delim.to_docs(config);
}
}
_ => panic!("One of the delimiters of the term expression is None: {term_expr:?}"),
}
}
_ => {
conditional_suffix = cons!(conditional_suffix, trailing_else.body.to_docs(config));
}
}
}
docs = cons!(docs, conditional_suffix);

docs
}
}
}
}

fn if_conditional_to_docs(
prefix_docs: Rc<Doc>,
if_conditional: &IfConditional,
config: &impl FormattingConfig,
) -> (Rc<Doc>, Rc<Doc>) {
// docs to append and the suffix doc
let mut docs = group!(cons!(
cons!(
if !matches!(prefix_docs.as_ref(), Doc::Nil) {
cons!(prefix_docs, text!(" "))
} else {
prefix_docs
},
cons!(if_conditional.keyword.to_docs(config), text!(" "))
),
if_conditional.left_delimiter.to_docs(config)
));
docs = cons!(docs, nl!(""));
docs = cons!(
docs,
cons!(if_conditional.condition.to_docs(config), nl!(""))
);
let mut next_group = cons!(if_conditional.right_delimiter.to_docs(config), text!(" "));
let mut suffix = Rc::new(Doc::Nil);
match if_conditional.body.as_ref() {
Expression::Term(term_expr) if term_expr.pre_delimiters.is_some() => {
match (term_expr.pre_delimiters, term_expr.post_delimiters) {
(Some(pre_delim), Some(post_delim)) => {
if term_expr.term.is_empty() {
next_group = cons!(
next_group,
cons!(pre_delim.to_docs(config), post_delim.to_docs(config))
);
} else {
next_group = cons!(next_group, pre_delim.to_docs(config));
next_group = cons!(next_group, nl!(" "));
let mut body_doc = join_docs(
term_expr.term.iter().map(|t| t.to_docs(config)),
Rc::new(Doc::Nil),
ShouldBreak::Yes,
config,
);
body_doc = cons!(body_doc, nl!(" "));

next_group = group!(cons!(next_group, body_doc));
suffix = post_delim.to_docs(config);
}
}
_ => panic!("One of the delimiters of the term expression is None: {term_expr:?}"),
}
}
_ => {
next_group = cons!(next_group, if_conditional.body.to_docs(config));
}
}
docs = cons!(docs, next_group);
docs = cons!(docs, nl!(""));
(docs, suffix)
}

#[cfg(test)]
Expand Down
74 changes: 37 additions & 37 deletions parser/src/token_parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,57 +28,57 @@ token_parser!(lparen, LParen);
token_parser!(rparen, RParen);
token_parser!(lbrace, LBrace);
token_parser!(rbrace, RBrace);
token_parser!(lsubscript, LSubscript);
token_parser!(rsubscript, RSubscript);
// token_parser!(lsubscript, LSubscript);
// token_parser!(rsubscript, RSubscript);
token_parser!(comma, Comma);

// Reserved
token_parser!(continue_token, Continue);
token_parser!(break_token, Break);
// token_parser!(continue_token, Continue);
// token_parser!(break_token, Break);

// Compound
token_parser!(if_token, If);
token_parser!(else_token, Else);
token_parser!(while_token, While);
token_parser!(for_token, For);
token_parser!(repeat, Repeat);
token_parser!(in_token, In);
// token_parser!(while_token, While);
// token_parser!(for_token, For);
// token_parser!(repeat, Repeat);
// token_parser!(in_token, In);
token_parser!(function, Function);
token_parser!(lambda, Lambda);
// token_parser!(lambda, Lambda);

// Binary operators
token_parser!(lassign, LAssign);
token_parser!(rassign, RAssign);
token_parser!(old_assign, OldAssign);
token_parser!(equal, Equal);
token_parser!(not_equal, NotEqual);
token_parser!(lower_than, LowerThan);
token_parser!(greater_than, GreaterThan);
token_parser!(lower_equal, LowerEqual);
token_parser!(greater_equal, GreaterEqual);
token_parser!(power, Power);
token_parser!(divide, Divide);
token_parser!(multiply, Multiply);
token_parser!(minus, Minus);
token_parser!(plus, Plus);
token_parser!(help, Help);
token_parser!(and, And);
token_parser!(vectorized_and, VectorizedAnd);
token_parser!(or, Or);
token_parser!(vectorized_or, VectorizedOr);
token_parser!(dollar, Dollar);
token_parser!(pipe, Pipe);
token_parser!(modulo, Modulo);
token_parser!(ns_get, NsGet);
token_parser!(ns_get_int, NsGetInt);
token_parser!(colon, Colon);
// token_parser!(lassign, LAssign);
// token_parser!(rassign, RAssign);
// token_parser!(old_assign, OldAssign);
// token_parser!(equal, Equal);
// token_parser!(not_equal, NotEqual);
// token_parser!(lower_than, LowerThan);
// token_parser!(greater_than, GreaterThan);
// token_parser!(lower_equal, LowerEqual);
// token_parser!(greater_equal, GreaterEqual);
// token_parser!(power, Power);
// token_parser!(divide, Divide);
// token_parser!(multiply, Multiply);
// token_parser!(minus, Minus);
// token_parser!(plus, Plus);
// token_parser!(help, Help);
// token_parser!(and, And);
// token_parser!(vectorized_and, VectorizedAnd);
// token_parser!(or, Or);
// token_parser!(vectorized_or, VectorizedOr);
// token_parser!(dollar, Dollar);
// token_parser!(pipe, Pipe);
// token_parser!(modulo, Modulo);
// token_parser!(ns_get, NsGet);
// token_parser!(ns_get_int, NsGetInt);
// token_parser!(colon, Colon);

// Unary operators
token_parser!(unary_not, UnaryNot);
// token_parser!(unary_not, UnaryNot);

// Comments
token_parser!(inline_comment, InlineComment(_));
token_parser!(comment, Comment(_));
// token_parser!(inline_comment, InlineComment(_));
// token_parser!(comment, Comment(_));

// EOF
token_parser!(eof, EOF);
Expand Down
8 changes: 8 additions & 0 deletions unsully/tests/format_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,11 @@ comparison_test!(function_definition_one_arg_no_body, "013");
comparison_test!(function_definition_tw0_arg_no_body, "014");
comparison_test!(function_definition_one_default_arg_no_body, "015");
comparison_test!(function_definition_three_args_multiline_body, "016");
comparison_test!(simple_conditional, "017");
comparison_test!(conditional_with_one_expression_in_body, "018");
comparison_test!(conditional_with_two_expression_in_body, "019");
comparison_test!(conditional_with_empty_trailing_else, "020");
comparison_test!(conditional_with_one_expr_trailing_else, "021");
comparison_test!(conditional_with_one_expr_and_one_expr_trailing_else, "022");
comparison_test!(conditional_with_if_else, "023");
comparison_test!(conditional_with_if_if_else_and_trailing_else, "024");
1 change: 1 addition & 0 deletions unsully/tests/test_cases/017.R
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
if(TRUE){}
1 change: 1 addition & 0 deletions unsully/tests/test_cases/017.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
if (TRUE) {}
1 change: 1 addition & 0 deletions unsully/tests/test_cases/018.R
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
if(TRUE){7}
3 changes: 3 additions & 0 deletions unsully/tests/test_cases/018.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if (TRUE) {
7
}
3 changes: 3 additions & 0 deletions unsully/tests/test_cases/019.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if(TRUE){
1
2}
4 changes: 4 additions & 0 deletions unsully/tests/test_cases/019.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
if (TRUE) {
1
2
}
1 change: 1 addition & 0 deletions unsully/tests/test_cases/020.R
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
if(TRUE){}else{}
1 change: 1 addition & 0 deletions unsully/tests/test_cases/020.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
if (TRUE) {} else {}
1 change: 1 addition & 0 deletions unsully/tests/test_cases/021.R
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
if(TRUE){}else{7}
3 changes: 3 additions & 0 deletions unsully/tests/test_cases/021.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if (TRUE) {} else {
7
}
1 change: 1 addition & 0 deletions unsully/tests/test_cases/022.R
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
if(TRUE){1}else{7}
5 changes: 5 additions & 0 deletions unsully/tests/test_cases/022.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
if (TRUE) {
1
} else {
7
}
1 change: 1 addition & 0 deletions unsully/tests/test_cases/023.R
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
if (TRUE) {} else if (FALSE) {}
1 change: 1 addition & 0 deletions unsully/tests/test_cases/023.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
if (TRUE) {} else if (FALSE) {}
1 change: 1 addition & 0 deletions unsully/tests/test_cases/024.R
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
if (TRUE) {1} else if (FALSE) {3} else {2}
7 changes: 7 additions & 0 deletions unsully/tests/test_cases/024.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
if (TRUE) {
1
} else if (FALSE) {
3
} else {
2
}

0 comments on commit d54fc2e

Please sign in to comment.