nushell/src/tests/test_signatures.rs

135 lines
3.9 KiB
Rust
Raw Normal View History

allow lists to have type annotations (#8529) this pr refines #8270 and closes #8109 # description examples: the original syntax is okay ```nu def okay [nums: list] {} # the type of list will be list<any> ``` empty annotations are allowed in any variation the last two may be caught by a future formatter, but do not affect `nu` code currently ```nu def okay [nums: list<>] {} # okay def okay [nums: list< >] {} # weird but also okay def okay [nums: list< >] {} # also weird but okay ``` types are allowed (See [notes](#notes) below) ```nu def okay [nums: list<int>] {} # `test [a b c]` will throw an error def okay [nums: list< int > {} # any amount of space within the angle brackets is okay def err [nums: list <int>] {} # this is not okay, `nums` and `<int>` will be parsed as # two separate params, ``` nested annotations are allowed in many variations ```nu def okay [items: list<list<int>>] {} def okay [items: list<list>] {} ``` any unterminated annotation is caught ```nu Error: nu::parser::unexpected_eof × Unexpected end of code. ╭─[source:1:1] 1 │ def err [nums: list<int] {} · ▲ · ╰── expected closing > ╰──── ``` unknown types are flagged ```nu Error: nu::parser::unknown_type × Unknown type. ╭─[source:1:1] 1 │ def err [nums: list<str>] {} · ─┬─ · ╰── unknown type ╰──── Error: nu::parser::unknown_type × Unknown type. ╭─[source:1:1] 1 │ def err [nums: list<int, string>] {} · ─────┬───── · ╰── unknown type ╰──── ``` # notes the error message for mismatched types in not as intuitive ```nu Error: nu::parser::parse_mismatch × Parse mismatch during operation. ╭─[source:1:1] 1 │ def err [nums: list<int>] {}; err [a b c] · ┬ · ╰── expected int ╰──── ``` it should be something like this ```nu Error: nu::parser::parse_mismatch × Parse mismatch during operation. ╭─[source:1:1] 1 │ def err [nums: list<int>] {}; err [a b c] · ──┬── · ╰── expected list<int> ╰──── ``` this is currently not implemented
2023-03-24 12:54:06 +01:00
use crate::tests::{fail_test, run_test, TestResult};
#[test]
fn list_annotations() -> TestResult {
let input = "def run [list: list<int>] {$list | length}; run [2 5 4]";
let expected = "3";
run_test(input, expected)
}
#[test]
fn list_annotations_unknown_prefix() -> TestResult {
let input = "def run [list: listint>] {$list | length}; run [2 5 4]";
let expected = "unknown type";
fail_test(input, expected)
}
#[test]
fn list_annotations_empty_1() -> TestResult {
let input = "def run [list: list] {$list | length}; run [2 5 4]";
let expected = "3";
run_test(input, expected)
}
#[test]
fn list_annotations_empty_2() -> TestResult {
let input = "def run [list: list<>] {$list | length}; run [2 5 4]";
let expected = "3";
run_test(input, expected)
}
#[test]
fn list_annotations_empty_3() -> TestResult {
let input = "def run [list: list< >] {$list | length}; run [2 5 4]";
let expected = "3";
run_test(input, expected)
}
#[test]
fn list_annotations_empty_4() -> TestResult {
let input = "def run [list: list<\n>] {$list | length}; run [2 5 4]";
let expected = "3";
run_test(input, expected)
}
#[test]
fn list_annotations_nested() -> TestResult {
let input = "def run [list: list<list<float>>] {$list | length}; run [ [2.0] [5.0] [4.0]]";
let expected = "3";
run_test(input, expected)
}
#[test]
fn list_annotations_unknown_inner_type() -> TestResult {
let input = "def run [list: list<str>] {$list | length}; run ['nushell' 'nunu' 'nana']";
let expected = "unknown type";
fail_test(input, expected)
}
#[test]
fn list_annotations_nested_unknown_inner() -> TestResult {
let input = "def run [list: list<list<str>>] {$list | length}; run [ [nushell] [nunu] [nana]]";
let expected = "unknown type";
fail_test(input, expected)
}
#[test]
fn list_annotations_unterminated() -> TestResult {
let input = "def run [list: list<string] {$list | length}; run [nu she ll]";
let expected = "expected closing >";
fail_test(input, expected)
}
#[test]
fn list_annotations_nested_unterminated() -> TestResult {
let input = "def run [list: list<list<>] {$list | length}; run [2 5 4]";
let expected = "expected closing >";
fail_test(input, expected)
}
#[test]
fn list_annotations_space_within_1() -> TestResult {
let input = "def run [list: list< range>] {$list | length}; run [2..32 5..<64 4..128]";
let expected = "3";
run_test(input, expected)
}
#[test]
fn list_annotations_space_within_2() -> TestResult {
let input = "def run [list: list<number >] {$list | length}; run [2 5 4]";
let expected = "3";
run_test(input, expected)
}
#[test]
fn list_annotations_space_within_3() -> TestResult {
let input = "def run [list: list< int >] {$list | length}; run [2 5 4]";
let expected = "3";
run_test(input, expected)
}
#[test]
fn list_annotations_space_before() -> TestResult {
let input = "def run [list: list <int>] {$list | length}; run [2 5 4]";
let expected = "expected valid variable name for this parameter";
fail_test(input, expected)
}
#[test]
fn list_annotations_unknown_separators() -> TestResult {
let input = "def run [list: list<int, string>] {$list | length}; run [2 5 4]";
let expected = "unknown type";
fail_test(input, expected)
}
#[test]
fn list_annotations_with_default_val_1() -> TestResult {
let input = "def run [list: list<int> = [2 5 4]] {$list | length}; run";
let expected = "3";
run_test(input, expected)
}
#[test]
fn list_annotations_with_default_val_2() -> TestResult {
let input = "def run [list: list<string> = [2 5 4]] {$list | length}; run";
let expected = "Default value wrong type";
fail_test(input, expected)
}
#[test]
fn list_annotations_with_extra_characters() -> TestResult {
let input = "def run [list: list<int>extra] {$list | length}; run [1 2 3]";
let expected = "Extra characters in the parameter name";
fail_test(input, expected)
}