use crate::pretty_printer::{assert_round_trips, assert_round_trips_with_types};
#[test]
fn type_alias_spaces_around_tokens() {
assert_round_trips_with_types(r" type Foo = string ");
assert_round_trips_with_types(r" type Foo = string ");
assert_round_trips_with_types(r" type Foo = string ");
assert_round_trips_with_types(r" type Foo = string ");
assert_round_trips_with_types(r" export type Foo = string ");
assert_round_trips_with_types(r" export type Foo = string ");
assert_round_trips_with_types(r" type Foo<X, Y, Z...> = string ");
assert_round_trips_with_types(r" type Foo <X, Y, Z...> = string ");
assert_round_trips_with_types(r" type Foo< X, Y, Z...> = string ");
assert_round_trips_with_types(r" type Foo<X , Y, Z...> = string ");
assert_round_trips_with_types(r" type Foo<X, Y, Z...> = string ");
assert_round_trips_with_types(r" type Foo<X, Y , Z...> = string ");
assert_round_trips_with_types(r" type Foo<X, Y, Z...> = string ");
assert_round_trips_with_types(r" type Foo<X, Y, Z ...> = string ");
assert_round_trips_with_types(r" type Foo<X, Y, Z... > = string ");
}
#[test]
fn type_alias_with_defaults_spaces_around_tokens() {
assert_round_trips_with_types(r" type Foo<X = string, Z... = ...any> = string ");
assert_round_trips_with_types(r" type Foo<X = string, Z... = ...any> = string ");
assert_round_trips_with_types(r" type Foo<X = string, Z... = ...any> = string ");
assert_round_trips_with_types(r" type Foo<X = string, Z... = ...any> = string ");
assert_round_trips_with_types(r" type Foo<X = string, Z... = ...any> = string ");
}
#[test]
fn roundtrip_types() {
assert_round_trips_with_types(
r#"
local s:string='str'
local t:{a:string,b:number,[string]:number}
local fn:(string,string)->(number,number)
local s2:typeof(s)='foo'
local os:string?
local sn:string|number
local it:{x:number}&{y:number}
"#,
);
}
#[test]
fn roundtrip_generic_types() {
assert_round_trips_with_types(
r#"
export type A<T> = {v:T, next:A<T>}
"#,
);
}
#[test]
fn pretty_print_type_assertion() {
assert_round_trips_with_types("local a = 5 :: number");
}
#[test]
fn type_assertion_spaces_around_tokens() {
assert_round_trips_with_types("local a = 5 :: number");
assert_round_trips_with_types("local a = 5 :: number");
}
#[test]
fn pretty_print_if_then_else() {
assert_round_trips("local a = if 1 then 2 else 3");
}
#[test]
fn pretty_print_if_then_else_multiple_conditions() {
assert_round_trips("local a = if 1 then 2 elseif 3 then 4 else 5");
}
#[test]
fn pretty_print_if_then_else_multiple_conditions_2() {
assert_round_trips(
r#"
local x = if yes
then nil
else if no
then if this
then that
else other
else nil
"#,
);
}
#[test]
fn if_then_else_spaces_around_tokens() {
assert_round_trips("local a = if 1 then 2 else 3");
assert_round_trips("local a = if 1 then 2 else 3");
assert_round_trips("local a = if 1 then 2 else 3");
assert_round_trips("local a = if 1 then 2 else 3");
assert_round_trips("local a = if 1 then 2 else 3");
assert_round_trips("local a = if 1 then 2 elseif 3 then 4 else 5");
assert_round_trips("local a = if 1 then 2 elseif 3 then 4 else 5");
assert_round_trips("local a = if 1 then 2 elseif 3 then 4 else 5");
assert_round_trips("local a = if 1 then 2 elseif 3 then 4 else 5");
assert_round_trips("local a = if 1 then 2 elseif 3 then 4 else 5");
assert_round_trips("local a = if 1 then 2 elseif 3 then 4 else 5");
}
#[test]
fn if_then_else_spaces_between_else_if() {
assert_round_trips(
r#"
return
if a then "was a" else
if b then "was b" else
if c then "was c" else
"was nothing!"
"#,
);
}
#[test]
fn pretty_print_type_reference_import() {
assert_round_trips_with_types(
r#"
local Import = require(game.A)
local a: Import.Type
"#,
);
}
#[test]
fn pretty_print_type_reference_spaces_around_tokens() {
assert_round_trips_with_types(r" local _: Foo.Type ");
assert_round_trips_with_types(r" local _: Foo .Type ");
assert_round_trips_with_types(r" local _: Foo. Type ");
assert_round_trips_with_types(r" local _: Type <> ");
assert_round_trips_with_types(r" local _: Type< > ");
assert_round_trips_with_types(r" local _: Type< number> ");
assert_round_trips_with_types(r" local _: Type<number ,string> ");
assert_round_trips_with_types(r" local _: Type<number, string > ");
}
#[test]
fn pretty_print_type_annotation_spaces_around_tokens() {
assert_round_trips_with_types(r" local _: Type ");
assert_round_trips_with_types(r" local _ : Type ");
assert_round_trips_with_types(r" local _: Type ");
assert_round_trips_with_types(r" local x: Type, y = 1 ");
assert_round_trips_with_types(r" local x : Type, y = 1 ");
}
#[test]
fn pretty_print_for_loop_annotation_spaces_around_tokens() {
assert_round_trips_with_types(r" for i: number = 1, 10 do end ");
assert_round_trips_with_types(r" for i : number = 1, 10 do end ");
assert_round_trips_with_types(r" for i: number = 1, 10 do end ");
assert_round_trips_with_types(r" for x: number, y: number in ... do end ");
assert_round_trips_with_types(r" for x : number, y: number in ... do end ");
assert_round_trips_with_types(r" for x: number, y: number in ... do end ");
assert_round_trips_with_types(r" for x: number, y : number in ... do end ");
assert_round_trips_with_types(r" for x: number, y: number in ... do end ");
}
#[test]
fn pretty_print_type_packs() {
assert_round_trips_with_types(
r#"
type Packed<T...> = (T...)->(T...)
local a: Packed<>
local b: Packed<(number, string)>
"#,
);
}
#[test]
fn type_packs_spaces_around_tokens() {
assert_round_trips_with_types(r" type _ = Packed< T...> ");
assert_round_trips_with_types(r" type _ = Packed<T ...> ");
assert_round_trips_with_types(r" type _ = Packed< ...T> ");
assert_round_trips_with_types(r" type _ = Packed<... T> ");
assert_round_trips_with_types(r" type _ = Packed< ()> ");
assert_round_trips_with_types(r" type _ = Packed< (string, number)> ");
assert_round_trips_with_types(r" type _ = Packed<( string, number)> ");
assert_round_trips_with_types(r" type _ = Packed<(string , number)> ");
assert_round_trips_with_types(r" type _ = Packed<(string, number)> ");
assert_round_trips_with_types(r" type _ = Packed<(string, number )> ");
assert_round_trips_with_types(r" type _ = Packed<(string, number) > ");
assert_round_trips_with_types(r" type _ = Packed<( )> ");
assert_round_trips_with_types(r" type _ = Packed<() > ");
}
#[test]
fn pretty_print_union_type_nested() {
assert_round_trips_with_types("local a: ((number)->(string))|((string)->(string))");
}
#[test]
fn pretty_print_union_type_nested_2() {
assert_round_trips_with_types("local a: (number&string)|(string&boolean)");
}
#[test]
fn pretty_print_union_type_nested_3() {
assert_round_trips_with_types("local a: nil | (string & number)");
}
#[test]
fn pretty_print_intersection_type_nested() {
assert_round_trips_with_types("local a: ((number)->(string))&((string)->(string))");
}
#[test]
fn pretty_print_intersection_type_nested_2() {
assert_round_trips_with_types("local a: (number|string)&(string|boolean)");
}
#[test]
fn pretty_print_intersection_type_with_function() {
assert_round_trips_with_types("type FnB<U...> = () -> U... & T");
}
#[test]
fn pretty_print_leading_union_pipe() {
assert_round_trips_with_types("local a: | string | number");
assert_round_trips_with_types("local a: | string");
}
#[test]
fn pretty_print_union_spaces_around_tokens() {
assert_round_trips_with_types("local a: string | number");
assert_round_trips_with_types("local a: string | number");
}
#[test]
fn pretty_print_leading_intersection_ampersand() {
assert_round_trips_with_types("local a: & string & number");
assert_round_trips_with_types("local a: & string");
}
#[test]
fn pretty_print_intersection_spaces_around_tokens() {
assert_round_trips_with_types("local a: string & number");
assert_round_trips_with_types("local a: string & number");
}
#[test]
fn pretty_print_mixed_union_intersection() {
assert_round_trips_with_types("local a: string | (Foo & Bar)");
assert_round_trips_with_types("local a: string | (Foo & Bar)");
assert_round_trips_with_types("local a: string | ( Foo & Bar)");
assert_round_trips_with_types("local a: string | (Foo & Bar )");
assert_round_trips_with_types("local a: string & (Foo | Bar)");
assert_round_trips_with_types("local a: string & ( Foo | Bar)");
assert_round_trips_with_types("local a: string & (Foo | Bar )");
}
#[test]
fn pretty_print_preserve_union_optional_style() {
assert_round_trips_with_types("local a: string | nil");
assert_round_trips_with_types("local a: string?");
assert_round_trips_with_types("local a: string???");
assert_round_trips_with_types("local a: string? | nil");
assert_round_trips_with_types("local a: string | nil | number");
assert_round_trips_with_types("local a: string | nil | number?");
assert_round_trips_with_types("local a: string? | number?");
}
#[test]
fn pretty_print_varargs() {
assert_round_trips_with_types("local function f(...) return ... end");
}
#[test]
fn pretty_print_union_reverse() {
assert_round_trips_with_types("local a: nil | number");
}
#[test]
fn pretty_print_singleton_types() {
assert_round_trips_with_types(
r#"
type t1 = 'hello'
type t2 = true
type t3 = ''
type t4 = false
"#,
);
}
#[test]
fn pretty_print_array_types() {
assert_round_trips_with_types(
r#"
type t1 = {number}
type t2 = {[string]: number}
"#,
);
}
#[test]
fn pretty_print_type_alias_default_type_parameters() {
assert_round_trips_with_types(
r#"
type Packed<T = string, U = T, V... = ...boolean, W... = (T, U, V...)> = (T, U, V...)->(W...)
local a: Packed<number>
"#,
);
}
#[test]
fn pretty_print_type_functions() {
assert_round_trips_with_types(
r" type function foo(arg1, arg2) if arg1 == arg2 then return arg1 end return arg2 end ",
);
}
#[test]
fn pretty_print_type_functions_spaces_around_tokens() {
assert_round_trips_with_types(r" type function foo() end ");
assert_round_trips_with_types(r" type function foo() end ");
assert_round_trips_with_types(r" type function foo () end ");
assert_round_trips_with_types(r" export type function foo() end ");
}
#[test]
fn pretty_print_typeof_spaces_around_tokens() {
assert_round_trips_with_types(r" type X = typeof(x) ");
assert_round_trips_with_types(r" type X = typeof(x) ");
assert_round_trips_with_types(r" type X = typeof (x) ");
assert_round_trips_with_types(r" type X = typeof( x) ");
assert_round_trips_with_types(r" type X = typeof(x ) ");
}
#[test]
fn pretty_print_type_table_semicolon_separators() {
assert_round_trips_with_types(
r#"
type Foo = {
bar: number;
baz: number;
}
"#,
);
}
#[test]
fn pretty_print_type_table_access_modifiers() {
assert_round_trips_with_types(
r#"
type Foo = {
read bar: number,
write baz: number,
}
"#,
);
assert_round_trips_with_types(r" type Foo = { read string } ");
assert_round_trips_with_types(
r#" type Foo = {
read [string]: number,
read ["property"]: number
} "#,
);
}
#[test]
fn pretty_print_type_table_spaces_between_tokens() {
assert_round_trips_with_types(r" type Foo = { bar: number, } ");
assert_round_trips_with_types(r" type Foo = { bar: number, } ");
assert_round_trips_with_types(r" type Foo = { bar : number, } ");
assert_round_trips_with_types(r" type Foo = { bar: number, } ");
assert_round_trips_with_types(r" type Foo = { bar: number , } ");
assert_round_trips_with_types(r" type Foo = { bar: number, } ");
assert_round_trips_with_types(r" type Foo = { bar: number } ");
assert_round_trips_with_types(r" type Foo = { [string]: number } ");
assert_round_trips_with_types(r" type Foo = { [string]: number } ");
assert_round_trips_with_types(r" type Foo = { [ string]: number } ");
assert_round_trips_with_types(r" type Foo = { [string ]: number } ");
assert_round_trips_with_types(r" type Foo = { [string] : number } ");
assert_round_trips_with_types(r" type Foo = { [string]: number } ");
}
#[test]
fn pretty_print_type_table_preserve_original_indexer_style() {
assert_round_trips_with_types(
r#"
type Foo = {
[number]: string
}
"#,
);
assert_round_trips_with_types(
r#"
type Foo = { { number } }
"#,
);
}
#[test]
fn pretty_print_type_table_preserve_indexer_location() {
assert_round_trips_with_types(
r#"
type Foo = {
[number]: string,
property: number,
}
"#,
);
assert_round_trips_with_types(
r#"
type Foo = {
property: number,
[number]: string,
}
"#,
);
assert_round_trips_with_types(
r#"
type Foo = {
property: number,
[number]: string,
property2: number,
}
"#,
);
}
#[test]
fn pretty_print_type_table_preserve_property_definition_style() {
assert_round_trips_with_types(
r#"
type Foo = {
["$$typeof1"]: string,
['$$typeof2']: string,
}
"#,
);
}
#[test]
fn pretty_print_type_table_string_properties_spaces_between_tokens() {
assert_round_trips_with_types(
r#"
type Foo = {
[ "$$typeof1"]: string,
['$$typeof2' ]: string,
}
"#,
);
}
#[test]
fn pretty_print_types_preserve_parentheses_style() {
assert_round_trips_with_types(r" type Foo = number ");
assert_round_trips_with_types(r" type Foo = (number) ");
assert_round_trips_with_types(r" type Foo = ((number)) ");
assert_round_trips_with_types(r" type Foo = ( (number) ) ");
}
#[test]
fn pretty_print_type_function_unnamed_arguments() {
assert_round_trips_with_types(r" type Foo = () -> () ");
assert_round_trips_with_types(r" type Foo = () -> () ");
assert_round_trips_with_types(r" type Foo = (string) -> () ");
assert_round_trips_with_types(r" type Foo = (string, number) -> () ");
assert_round_trips_with_types(r" type Foo = ( string, number) -> () ");
assert_round_trips_with_types(r" type Foo = (string , number) -> () ");
assert_round_trips_with_types(r" type Foo = (string, number) -> () ");
assert_round_trips_with_types(r" type Foo = (string, number ) -> () ");
assert_round_trips_with_types(r" type Foo = (string, number) -> () ");
assert_round_trips_with_types(r" type Foo = (string, number) -> () ");
}
#[test]
fn pretty_print_type_function_named_arguments() {
assert_round_trips_with_types(r" type Foo = (x: string) -> () ");
assert_round_trips_with_types(r" type Foo = (x: string, y: number) -> () ");
assert_round_trips_with_types(r" type Foo = ( x: string, y: number) -> () ");
assert_round_trips_with_types(r" type Foo = (x : string, y: number) -> () ");
assert_round_trips_with_types(r" type Foo = (x: string, y: number) -> () ");
assert_round_trips_with_types(r" type Foo = (x: string, y: number) -> () ");
assert_round_trips_with_types(r" type Foo = (number, info: string) -> () ");
assert_round_trips_with_types(r" type Foo = (first: string, second: string, ...string) -> () ");
}
#[test]
fn pretty_print_type_function_generics() {
assert_round_trips_with_types(r" type Foo = <X, Y, Z...>() -> () ");
assert_round_trips_with_types(r" type Foo = <X, Y, Z...>() -> () ");
assert_round_trips_with_types(r" type Foo = < X, Y, Z...>() -> () ");
assert_round_trips_with_types(r" type Foo = <X , Y, Z...>() -> () ");
assert_round_trips_with_types(r" type Foo = <X, Y, Z...>() -> () ");
assert_round_trips_with_types(r" type Foo = <X, Y , Z...>() -> () ");
assert_round_trips_with_types(r" type Foo = <X, Y, Z...>() -> () ");
assert_round_trips_with_types(r" type Foo = <X, Y, Z ...>() -> () ");
assert_round_trips_with_types(r" type Foo = <X, Y, Z... >() -> () ");
assert_round_trips_with_types(r" type Foo = <X, Y, Z...> () -> () ");
}
#[test]
fn pretty_print_type_function_return_types() {
assert_round_trips_with_types(r" type Foo = () -> () ");
assert_round_trips_with_types(r" type Foo = () -> ( ) ");
assert_round_trips_with_types(r" type Foo = () -> string ");
assert_round_trips_with_types(r" type Foo = () -> string ");
assert_round_trips_with_types(r" type Foo = () -> (string) ");
assert_round_trips_with_types(r" type Foo = () -> (string) ");
assert_round_trips_with_types(r" type Foo = () -> ...any ");
assert_round_trips_with_types(r" type Foo = () -> ...any ");
assert_round_trips_with_types(r" type Foo = () -> ... any ");
assert_round_trips_with_types(r" type Foo = () -> (...any) ");
assert_round_trips_with_types(r" type Foo = () -> ( string, number) ");
assert_round_trips_with_types(r" type Foo = () -> (string , number) ");
assert_round_trips_with_types(r" type Foo = () -> (string, number) ");
assert_round_trips_with_types(r" type Foo = () -> (string, number ) ");
}
#[test]
fn pretty_print_chained_function_types() {
assert_round_trips_with_types(r" type Foo = () -> () -> () ");
assert_round_trips_with_types(r" type Foo = () -> () -> () ");
assert_round_trips_with_types(r" type Foo = () -> () -> () ");
}
#[test]
fn fuzzer_nil_optional() {
assert_round_trips_with_types(r" local x: nil? ");
}