diff --git a/crates/nu-parser/src/parse_shape_specs.rs b/crates/nu-parser/src/parse_shape_specs.rs index 746bfd5232..4f3ab40c2e 100644 --- a/crates/nu-parser/src/parse_shape_specs.rs +++ b/crates/nu-parser/src/parse_shape_specs.rs @@ -64,12 +64,17 @@ pub fn parse_shape_name( b"number" => SyntaxShape::Number, b"path" => SyntaxShape::Filepath, b"range" => SyntaxShape::Range, - _ if bytes.starts_with(b"list") + _ if bytes.starts_with(b"oneof") + || bytes.starts_with(b"list") || bytes.starts_with(b"record") || bytes.starts_with(b"table") => { let (type_name, type_params) = split_generic_params(working_set, bytes, span); match type_name { + b"oneof" => SyntaxShape::OneOf(match type_params { + Some(params) => parse_type_params(working_set, params, use_loc), + None => vec![], + }), b"list" => SyntaxShape::List(Box::new(match type_params { Some(params) => { let mut parsed_params = parse_type_params(working_set, params, use_loc); @@ -101,11 +106,6 @@ pub fn parse_shape_name( } } b"string" => SyntaxShape::String, - _ if bytes.starts_with(b"(") && bytes.ends_with(b")") => { - let source = - bytes[1..(bytes.len() - 1)].into_spanned(Span::new(span.start + 1, span.end - 1)); - parse_one_of(working_set, source, use_loc) - } _ => { if bytes.contains(&b'@') { let mut split = bytes.splitn(2, |b| b == &b'@'); @@ -312,44 +312,3 @@ fn parse_type_params( sig } - -fn parse_one_of( - working_set: &mut StateWorkingSet, - Spanned { item: source, span }: Spanned<&[u8]>, - use_loc: ShapeDescriptorUse, -) -> SyntaxShape { - let (tokens, err) = lex_signature(source, span.start, &[b'\n', b'\r'], &[b':', b','], true); - - if let Some(err) = err { - working_set.error(err); - return SyntaxShape::Any; - } - - let mut sig = vec![]; - - let mut tokens = tokens.into_iter().peekable(); - while let Some(token) = tokens.next() { - let TokenContents::Item = token.contents else { - working_set.error(ParseError::Expected("a type", token.span)); - return SyntaxShape::Any; - }; - - let shape_bytes = working_set.get_span_contents(token.span).to_vec(); - let shape = parse_shape_name(working_set, &shape_bytes, token.span, use_loc); - sig.push(shape); - - let Some(token_pipe) = tokens.next() else { - break; - }; - - match token_pipe.contents { - TokenContents::Pipe => {} - _ => { - working_set.error(ParseError::Expected("pipe '|'", token_pipe.span)); - return SyntaxShape::Any; - } - } - } - - SyntaxShape::OneOf(sig) -} diff --git a/crates/nu-protocol/src/syntax_shape.rs b/crates/nu-protocol/src/syntax_shape.rs index 87d491e40a..786a00982e 100644 --- a/crates/nu-protocol/src/syntax_shape.rs +++ b/crates/nu-protocol/src/syntax_shape.rs @@ -250,14 +250,14 @@ impl Display for SyntaxShape { SyntaxShape::Error => write!(f, "error"), SyntaxShape::CompleterWrapper(x, _) => write!(f, "completable<{x}>"), SyntaxShape::OneOf(list) => { - write!(f, "(")?; + write!(f, "oneof<")?; if let Some((last, rest)) = list.split_last() { for ty in rest { - write!(f, "{ty} | ")?; + write!(f, "{ty}, ")?; } write!(f, "{last}")?; } - write!(f, ")") + write!(f, ">") } SyntaxShape::Nothing => write!(f, "nothing"), } diff --git a/tests/repl/test_signatures.rs b/tests/repl/test_signatures.rs index 0fee593546..cc8133afb5 100644 --- a/tests/repl/test_signatures.rs +++ b/tests/repl/test_signatures.rs @@ -340,32 +340,32 @@ fn table_annotations_with_extra_characters() -> TestResult { } #[rstest] -fn one_of_annotations( +fn oneof_annotations( #[values( - ("(cell-path | list)", "a.b.c", "cell-path"), - ("(cell-path | list)", "[a.b.c d.e.f]", "list"), - ("(closure | any)", "{}", "closure"), - ("(closure | any)", "{a: 1}", "record"), + ("cell-path, list", "a.b.c", "cell-path"), + ("cell-path, list", "[a.b.c d.e.f]", "list"), + ("closure, any", "{}", "closure"), + ("closure, any", "{a: 1}", "record"), )] annotation_data: (&str, &str, &str), ) -> TestResult { - let (one_of_type, argument, expected) = annotation_data; + let (types, argument, expected) = annotation_data; - let input = format!("def run [t: {one_of_type}] {{ $t }}; run {argument} | describe"); + let input = format!("def run [t: oneof<{types}>] {{ $t }}; run {argument} | describe"); run_test(&input, expected) } #[test] -fn one_of_annotations_not_terminated() -> TestResult { - let input = "def run [t: (binary | string] { $t }"; - let expected = "expected closing )"; +fn oneof_annotations_not_terminated() -> TestResult { + let input = "def run [t: oneof TestResult { - let input = "def run [t: (int | string)extra] {$t}"; - let expected = "Unknown type."; +fn oneof_annotations_with_extra_characters() -> TestResult { + let input = "def run [t: oneofextra] {$t}"; + let expected = "Extra characters in the parameter name"; fail_test(input, expected) }