mirror of
https://github.com/nushell/nushell.git
synced 2025-06-30 14:40:06 +02:00
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
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
use nu_parser::{lex, ParseError, Token, TokenContents};
|
||||
use nu_parser::{lex, lex_signature, ParseError, Token, TokenContents};
|
||||
use nu_protocol::Span;
|
||||
|
||||
#[test]
|
||||
@ -22,6 +22,100 @@ fn lex_newline() {
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lex_annotations_list() {
|
||||
let file = b"items: list<string>";
|
||||
|
||||
let (output, err) = lex_signature(file, 0, &[b'\n', b'\r'], &[b':', b'=', b','], false);
|
||||
|
||||
assert!(err.is_none());
|
||||
assert_eq!(output.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lex_annotations_record() {
|
||||
let file = b"config: record<name: string>";
|
||||
|
||||
let (output, err) = lex_signature(file, 0, &[b'\n', b'\r'], &[b':', b'=', b','], false);
|
||||
|
||||
assert!(err.is_none());
|
||||
assert_eq!(output.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lex_annotations_empty() {
|
||||
let file = b"items: list<>";
|
||||
|
||||
let (output, err) = lex_signature(file, 0, &[b'\n', b'\r'], &[b':', b'=', b','], false);
|
||||
|
||||
assert!(err.is_none());
|
||||
assert_eq!(output.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lex_annotations_space_before_annotations() {
|
||||
let file = b"items: list <string>";
|
||||
|
||||
let (output, err) = lex_signature(file, 0, &[b'\n', b'\r'], &[b':', b'=', b','], false);
|
||||
|
||||
assert!(err.is_none());
|
||||
assert_eq!(output.len(), 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lex_annotations_space_within_annotations() {
|
||||
let file = b"items: list< string>";
|
||||
|
||||
let (output, err) = lex_signature(file, 0, &[b'\n', b'\r'], &[b':', b'=', b','], false);
|
||||
|
||||
assert!(err.is_none());
|
||||
assert_eq!(output.len(), 3);
|
||||
|
||||
let file = b"items: list<string >";
|
||||
|
||||
let (output, err) = lex_signature(file, 0, &[b'\n', b'\r'], &[b':', b'=', b','], false);
|
||||
|
||||
assert!(err.is_none());
|
||||
assert_eq!(output.len(), 3);
|
||||
|
||||
let file = b"items: list< string >";
|
||||
|
||||
let (output, err) = lex_signature(file, 0, &[b'\n', b'\r'], &[b':', b'=', b','], false);
|
||||
|
||||
assert!(err.is_none());
|
||||
assert_eq!(output.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lex_annotations_nested() {
|
||||
let file = b"items: list<record<name: string>>";
|
||||
|
||||
let (output, err) = lex_signature(file, 0, &[b'\n', b'\r'], &[b':', b'=', b','], false);
|
||||
|
||||
assert!(err.is_none());
|
||||
assert_eq!(output.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lex_annotations_nested_unterminated() {
|
||||
let file = b"items: list<record<name: string>";
|
||||
|
||||
let (output, err) = lex_signature(file, 0, &[b'\n', b'\r'], &[b':', b'=', b','], false);
|
||||
|
||||
assert!(matches!(err.unwrap(), ParseError::UnexpectedEof(_, _)));
|
||||
assert_eq!(output.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lex_annotations_unterminated() {
|
||||
let file = b"items: list<string";
|
||||
|
||||
let (output, err) = lex_signature(file, 0, &[b'\n', b'\r'], &[b':', b'=', b','], false);
|
||||
|
||||
assert!(matches!(err.unwrap(), ParseError::UnexpectedEof(_, _)));
|
||||
assert_eq!(output.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lex_empty() {
|
||||
let file = b"";
|
||||
|
Reference in New Issue
Block a user