Repository: nushell/nushell
File: crates/nu-parser/src/parse_shape_specs.rs (Rust)

Code before:
                    span,
                ));
            }
            //TODO: Handle error case for unknown shapes
            working_set.error(ParseError::UnknownType(span));
            SyntaxShape::Any
        }
    }
}

/// Handles the specification of custom completions with `type@completer`.
pub fn parse_completer(
    working_set: &mut StateWorkingSet,
    bytes: &[u8],
    span: Span,
) -> Option<DeclId> {
    let cmd_name = trim_quotes(bytes);
    if cmd_name.is_empty() {
        working_set.error(ParseError::Expected(
            "the command name of a completion function",
            span,
        ));
        return None;
    }
    working_set.find_decl(cmd_name)
}

fn parse_generic_shape(
    working_set: &mut StateWorkingSet<'_>,
    bytes: &[u8],
    span: Span,
) -> SyntaxShape {
    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),
            None => vec![],
        }),
        b"list" => SyntaxShape::List(Box::new(match type_params {
            Some(params) => {
                let mut parsed_params = parse_type_params(working_set, params);
                if parsed_params.len() > 1 {
                    working_set.error(ParseError::LabeledError(
                        "expected a single type parameter".into(),
                        "only one parameter allowed".into(),
                        params.span,
                    ));
                    SyntaxShape::Any
                } else {
                    parsed_params.pop().unwrap_or(SyntaxShape::Any)
                }

Review comment (suggestion):
Using `SyntaxShape::String` here is quite interesting: it allows

```nushell
def test [
  y: list<int>@["[1]" "[1 2]"],
] {}
```

to work surprisingly well.

As a side effect, this kind of type mismatch is not detected in signature parsing:

```nushell
def test [
  y: int@[a b],
] {}
```

I don't think it will hurt any practical usage, just something to keep in mind.



Code after:
            if bytes.contains(&b'@') {
                working_set.error(ParseError::LabeledError(
                    "Unexpected custom completer in type spec".into(),
                    "Type specifications do not support custom completers".into(),
                    span,
                ));
            }
            //TODO: Handle error case for unknown shapes
            working_set.error(ParseError::UnknownType(span));
            SyntaxShape::Any
        }
    }
}

/// Handles the specification of custom completions with `type@completer`.
pub fn parse_completer(
    working_set: &mut StateWorkingSet,
    _bytes: &[u8],
    span: Span,
) -> Option<Completion> {
    let error_count = working_set.parse_errors.len();
    let expr = parse_value(
        working_set,
        span,
        &SyntaxShape::OneOf(vec![
            SyntaxShape::List(Box::new(SyntaxShape::String)),
            SyntaxShape::String,
        ]),
    );

    if working_set.parse_errors.len() > error_count {
        return None;
    }

    let val = match eval_constant(working_set, &expr) {
        Ok(val) => val,
        Err(e) => {
            working_set.error(e.wrap(working_set, span));
            return None;
        }
    };

    let completion = match val {
        // Static list completions
        Value::List { vals, .. } => vals
            .into_iter()
            .map(|val| {
                let span = val.span();
                match val {
                    // TODO: currently `Completion::List` only supports simple string suggestions,
                    // but it will likely support description and style properties as well.