roc/tests/test_format.rs

861 lines
16 KiB
Rust
Raw Normal View History

2019-09-16 04:37:20 +03:00
#[macro_use]
extern crate pretty_assertions;
#[macro_use]
extern crate indoc;
extern crate bumpalo;
2019-11-20 13:37:19 +03:00
#[macro_use]
2019-09-16 04:37:20 +03:00
extern crate roc;
#[cfg(test)]
2019-09-16 07:25:31 +03:00
mod test_format {
2019-11-26 04:42:44 +03:00
use bumpalo::collections::String;
2019-09-16 04:37:20 +03:00
use bumpalo::Bump;
use roc::fmt::def::fmt_def;
2019-11-26 04:42:44 +03:00
use roc::fmt::expr::fmt_expr;
use roc::fmt::module::fmt_module;
2019-09-16 04:37:20 +03:00
use roc::parse;
2019-11-26 04:42:44 +03:00
use roc::parse::ast::{Attempting, Expr};
2019-09-30 19:02:09 +03:00
use roc::parse::blankspace::space0_before;
use roc::parse::module::{module, module_defs};
2019-11-20 13:37:19 +03:00
use roc::parse::parser::{Fail, Parser, State};
2019-09-16 04:37:20 +03:00
fn parse_with<'a>(arena: &'a Bump, input: &'a str) -> Result<Expr<'a>, Fail> {
let state = State::new(&input, Attempting::Module);
2019-11-20 13:37:19 +03:00
let parser = space0_before(loc!(parse::expr(0)), 0);
2019-09-16 04:37:20 +03:00
let answer = parser.parse(&arena, state);
2019-09-30 19:02:09 +03:00
answer
.map(|(loc_expr, _)| loc_expr.value)
.map_err(|(fail, _)| fail)
2019-09-16 04:37:20 +03:00
}
2019-11-26 04:42:44 +03:00
fn expr_formats_to(input: &str, expected: &str) {
2019-09-16 04:37:20 +03:00
let arena = Bump::new();
let input = input.trim_end();
let expected = expected.trim_end();
match parse_with(&arena, input) {
2019-11-26 04:42:44 +03:00
Ok(actual) => {
let mut buf = String::new_in(&arena);
fmt_expr(&mut buf, &actual, 0, false, true);
2019-11-26 04:42:44 +03:00
assert_eq!(buf, expected)
},
2019-09-16 04:37:20 +03:00
Err(error) => panic!("Unexpected parse failure when parsing this for formatting:\n\n{:?}\n\nParse error was:\n\n{:?}\n\n", input, error)
}
}
2019-11-26 04:42:44 +03:00
fn expr_formats_same(input: &str) {
expr_formats_to(input, input);
}
fn module_formats_to(src: &str, expected: &str) {
let arena = Bump::new();
let src = src.trim_end();
let expected = expected.trim_end();
match module().parse(&arena, State::new(&src, Attempting::Module)) {
Ok((actual, state)) => {
2019-11-26 04:42:44 +03:00
let mut buf = String::new_in(&arena);
fmt_module(&mut buf, &actual);
match module_defs().parse(&arena, state) {
Ok((loc_defs, _)) => {
for loc_def in loc_defs {
fmt_def(&mut buf, arena.alloc(loc_def.value), 0);
}
}
Err(error) => panic!("Unexpected parse failure when parsing this for defs formatting:\n\n{:?}\n\nParse error was:\n\n{:?}\n\n", src, error)
}
2019-11-26 04:42:44 +03:00
assert_eq!(buf, expected)
},
Err(error) => panic!("Unexpected parse failure when parsing this for module header formatting:\n\n{:?}\n\nParse error was:\n\n{:?}\n\n", src, error)
2019-11-26 04:42:44 +03:00
};
}
fn module_formats_same(input: &str) {
module_formats_to(input, input);
2019-09-16 04:37:20 +03:00
}
// STRING LITERALS
#[test]
fn empty_string() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
2019-09-16 04:37:20 +03:00
r#"
""
"#
));
}
2019-09-16 06:29:06 +03:00
#[test]
2019-12-05 06:38:57 +03:00
fn def_with_comment() {
expr_formats_same(indoc!(
r#"
# This variable is for greeting
a = "Hello"
a
"#
));
}
#[test]
2019-12-05 06:38:57 +03:00
fn def_with_comment_and_extra_space() {
expr_formats_to(
indoc!(
r#"
# This variable is for greeting
a = "Hello"
a
"#
),
indoc!(
r#"
# This variable is for greeting
a = "Hello"
a
"#
),
);
}
2019-12-05 06:36:28 +03:00
#[test]
fn func_def() {
expr_formats_same(indoc!(
r#"
2019-12-19 05:45:00 +03:00
f = \x, y ->
x
f 4
"#
));
}
#[test]
fn new_line_above_return() {
2019-12-09 14:41:42 +03:00
expr_formats_to(
indoc!(
r#"
2019-12-19 05:45:00 +03:00
f = \x, y ->
y = 4
z = 8
x
"string"
"#
2019-12-09 14:41:42 +03:00
),
indoc!(
r#"
2019-12-19 05:45:00 +03:00
f = \x, y ->
y = 4
z = 8
x
"string"
"#
2019-12-09 14:41:42 +03:00
),
);
expr_formats_same(indoc!(
r#"
2019-12-19 05:45:00 +03:00
f = \x, y ->
a = 3
b = 6
c
"string"
"#
));
}
2019-09-16 06:29:06 +03:00
#[test]
fn basic_string() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
2019-09-16 06:29:06 +03:00
r#"
"blah"
2019-09-16 06:29:06 +03:00
"#
));
}
#[test]
fn escaped_unicode_string() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
2019-09-16 06:29:06 +03:00
r#"
"unicode: \u{A00A}!"
2019-09-16 06:29:06 +03:00
"#
));
}
#[test]
fn escaped_quote_string() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
2019-09-16 06:29:06 +03:00
r#"
"\""
2019-09-16 06:29:06 +03:00
"#
));
}
#[test]
fn empty_block_string() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
2019-09-16 06:29:06 +03:00
r#"
""""""
2019-09-16 06:29:06 +03:00
"#
));
}
2019-09-16 07:25:31 +03:00
#[test]
fn basic_block_string() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
2019-09-16 07:25:31 +03:00
r#"
"""blah"""
2019-09-16 07:25:31 +03:00
"#
));
}
#[test]
fn newlines_block_string() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
2019-09-16 07:25:31 +03:00
r#"
"""blah
spam
foo"""
"#
));
}
#[test]
fn quotes_block_string() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
r#"
"""
"" \""" ""\"
"""
"#
));
}
#[test]
fn zero() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
r#"
0
"#
));
}
#[test]
fn zero_point_zero() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
r#"
0.0
"#
));
}
#[test]
fn int_with_underscores() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
r#"
1_23_456
"#
));
}
#[test]
fn float_with_underscores() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
r#"
1_23_456.7_89_10
2019-09-16 07:25:31 +03:00
"#
));
}
#[test]
fn multi_arg_closure() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
r#"
2019-12-19 05:45:00 +03:00
\a, b, c -> a b c
"#
));
}
// DEFS
2019-09-30 19:02:09 +03:00
#[test]
fn single_def() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
2019-10-02 21:06:34 +03:00
r#"
2019-09-30 19:02:09 +03:00
x = 5
42
"#
));
}
2019-09-30 19:03:28 +03:00
#[test]
fn two_defs() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
2019-10-02 21:06:34 +03:00
r#"
2019-09-30 19:03:28 +03:00
x = 5
y = 10
42
"#
));
expr_formats_to(
indoc!(
2019-12-09 14:41:42 +03:00
r#"
x = 5
y = 10
42
"#
),
indoc!(
2019-12-09 14:41:42 +03:00
r#"
x = 5
y = 10
42
"#
),
);
}
2019-12-09 14:41:42 +03:00
// #[test]
// fn defs_with_defs() {
// expr_formats_to(indoc!(
// r#"
// x =
// y = 4
// z = 8
// w
//
// x
// "#
// ), indoc!(
// r#"
// x =
// y = 4
// z = 8
//
// w
//
// x
// "#
// ));
// }
#[test]
2019-12-05 06:38:57 +03:00
fn comment_between_two_defs() {
expr_formats_same(indoc!(
r#"
x = 5
# Hello
y = 10
42
"#
));
expr_formats_same(indoc!(
r#"
x = 5
# Hello
# two comments
y = 10
42
"#
));
expr_formats_same(indoc!(
r#"
x = 5
# Hello
# two comments
y = 10
# v-- This is the return value
42
"#
));
}
#[test]
fn space_between_comments() {
expr_formats_same(indoc!(
r#"
# 9
# A
# B
# C
9
"#
));
}
#[test]
fn doesnt_detect_comment_in_comment() {
expr_formats_same(indoc!(
r#"
# One Comment # Still one Comment
9
"#
));
2019-09-30 19:03:28 +03:00
}
2019-10-02 21:06:41 +03:00
#[test]
fn parenthetical_def() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
2019-10-02 21:06:41 +03:00
r#"
(UserId userId) = 5
y = 10
42
"#
));
expr_formats_same(indoc!(
r#"
# A
(UserId userId) = 5
# B
y = 10
42
"#
));
2019-10-02 21:06:41 +03:00
}
2019-10-01 00:04:18 +03:00
#[test]
fn record_destructuring() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
2019-10-02 21:06:34 +03:00
r#"
2019-10-01 00:04:18 +03:00
{ x, y } = 5
{ x: 5 } = { x: 5 }
2019-10-01 00:04:18 +03:00
42
"#
));
}
// #[test]
// fn record_field_destructuring() {
2019-11-26 04:42:44 +03:00
// expr_formats_same(indoc!(
// r#"
2019-12-19 05:45:00 +03:00
// case foo when
// { x: 5 } -> 42
// "#
// ));
// }
2019-10-03 10:27:05 +03:00
#[test]
fn def_closure() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
2019-10-03 10:27:05 +03:00
r#"
identity = \a -> a
identity 42
"#
));
expr_formats_same(indoc!(
r#"
identity = \a ->
a
2019-12-16 20:51:13 +03:00
identity 44
"#
));
expr_formats_same(indoc!(
r#"
identity = \a -> a
# Hello
2019-12-16 20:51:13 +03:00
identity 40
"#
));
2019-12-16 21:35:30 +03:00
// expr_formats_to(indoc!(
// r#"
// identity = \a
// -> a
//
// identity 41
// "#
// ), indoc!(
// r#"
// identity = \a ->
// a
//
// identity 41
// "#
// ));
2019-12-16 20:51:13 +03:00
expr_formats_same(indoc!(
r#"
2019-12-19 05:45:00 +03:00
identity = \a,
2019-12-16 20:51:13 +03:00
b
-> a
identity 43
"#
));
expr_formats_same(indoc!(
r#"
2019-12-19 05:45:00 +03:00
identity = \a,
b,
2019-12-17 05:30:13 +03:00
# it's c!!
c
-> a
identity 43
"#
));
2019-10-03 10:27:05 +03:00
}
2019-09-16 07:25:31 +03:00
// RECORD LITERALS
#[test]
fn empty_record() {
2019-11-26 04:42:44 +03:00
expr_formats_same("{}");
2019-09-16 07:25:31 +03:00
}
#[test]
fn one_field() {
2019-11-26 04:42:44 +03:00
expr_formats_same("{ x: 4 }");
}
#[test]
fn two_fields() {
2019-11-26 04:42:44 +03:00
expr_formats_same("{ x: 4, y: 42 }");
}
#[test]
fn two_fields_newline() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
r#"
{
x: 4,
y: 42
}
"#
));
}
2019-11-14 15:49:40 +03:00
#[test]
fn two_fields_center_newline() {
2019-11-26 04:42:44 +03:00
expr_formats_to(
2019-11-14 15:49:40 +03:00
indoc!(
r#"
{ x: 4,
y: 42
}
"#
),
indoc!(
r#"
{
x: 4,
y: 42
}
"#
),
);
}
#[test]
fn one_unnamed_field() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
r#"
foo = 4
{ foo }
"#
));
}
// IF
#[test]
fn single_line_if() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
r#"
if foo bar then a b c else d e f
"#
));
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
r#"
if foo (a b c) then a b c else d e f
"#
));
}
2019-12-21 00:04:09 +03:00
#[test]
fn multi_line_if() {
2019-12-21 00:16:45 +03:00
expr_formats_to(
indoc!(
r#"
2019-12-21 10:11:14 +03:00
if lessThan four five then
four
else
five
"#
2019-12-21 00:16:45 +03:00
),
indoc!(
r#"
2019-12-21 10:11:14 +03:00
if lessThan four five then
four
2019-12-21 00:04:09 +03:00
2019-12-21 10:11:14 +03:00
else
five
"#
2019-12-21 00:16:45 +03:00
),
);
2019-12-21 00:04:09 +03:00
expr_formats_to(
indoc!(
r#"
if lessThan three four then
three
else
four
"#
),
indoc!(
r#"
if lessThan three four then
three
else
four
"#
),
);
2019-12-21 10:11:14 +03:00
expr_formats_same(indoc!(
r#"
2019-12-21 00:04:09 +03:00
if foo bar then
a b c
else
d e f
"#
2019-12-21 10:11:14 +03:00
));
2019-12-21 00:04:09 +03:00
}
// fn multi_line_application() {
// expr_formats_same(indoc!(
// r#"
// combine
// peanutButter
// chocolate
// "#
// ));
// }
// CASE
#[test]
fn integer_case() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
r#"
case b when
1 ->
1
_ ->
2
"#
));
}
#[test]
fn case_with_comments() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
r#"
case b when
# look at cases
1 ->
# case 1
1
# important
# fall through
_ ->
# case 2
# more comment
2
"#
));
}
2019-11-20 16:44:32 +03:00
#[test]
fn nested_case() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
2019-11-20 16:44:32 +03:00
r#"
case b when
_ ->
case c when
_ ->
1
"#
));
}
#[test]
fn case_with_moving_comments() {
2019-11-26 04:42:44 +03:00
expr_formats_to(
indoc!(
r#"
case b when
1 ->
1 # case 1
# fall through
_ ->
2
"#
),
indoc!(
r#"
case b when
1 ->
1
# case 1
# fall through
_ ->
2
"#
),
);
}
// NEWLINES
#[test]
fn multiple_blank_lines_collapse_to_one() {
2019-11-26 04:42:44 +03:00
expr_formats_to(
indoc!(
r#"
x = 5
y = 10
42
"#
),
indoc!(
r#"
x = 5
y = 10
42
"#
),
);
}
2019-11-21 01:50:16 +03:00
#[test]
fn def_returning_closure() {
2019-11-26 04:42:44 +03:00
expr_formats_same(indoc!(
2019-11-21 02:14:33 +03:00
r#"
2019-11-21 01:50:16 +03:00
f = \x -> x
g = \x -> x
\x ->
a = f x
b = f x
x
"#
2019-11-21 02:14:33 +03:00
));
2019-11-21 01:50:16 +03:00
}
2019-11-26 04:42:44 +03:00
// MODULES
#[test]
2019-11-26 04:52:34 +03:00
fn single_line_interface() {
2019-11-26 04:42:44 +03:00
module_formats_same(indoc!(
r#"
interface Foo exposes [] imports []
"#
));
}
#[test]
2019-11-26 04:52:34 +03:00
fn multiline_interface() {
2019-11-26 04:42:44 +03:00
module_formats_same(indoc!(
r#"
interface Foo
exposes []
imports []
"#
));
}
2019-11-26 04:52:34 +03:00
#[test]
fn interface_exposing() {
module_formats_same(indoc!(
r#"
interface Foo
exposes [ Bar, Baz, a, b ]
imports []
"#
));
}
2019-11-26 05:08:20 +03:00
#[test]
fn interface_importing() {
module_formats_same(indoc!(
r#"
interface Foo
exposes [ Bar, Baz, a, b ]
imports [ Blah, Thing.{ foo, bar }, Stuff ]
"#
));
}
2019-09-16 04:37:20 +03:00
}