diff --git a/proxmox-api-macro/src/parsing.rs b/proxmox-api-macro/src/parsing.rs index 1082f44e..0e51c3de 100644 --- a/proxmox-api-macro/src/parsing.rs +++ b/proxmox-api-macro/src/parsing.rs @@ -50,33 +50,38 @@ pub fn optional_visibility(tokens: &mut TokenIter) -> Result Result<(), Error> { +pub fn match_keyword( + span: Span, + tokens: &mut TokenIter, + keyword: &'static str, +) -> Result { if let Some(tt) = tokens.next() { if let TokenTree::Ident(ident) = tt { if ident.to_string() == keyword { - return Ok(()); + return Ok(ident.span()); } } } - bail!("expected `{}` keyword", keyword); + c_bail!(span, "expected `{}` keyword", keyword); } -pub fn need_ident(tokens: &mut TokenIter) -> Result { +pub fn need_ident(before: Span, tokens: &mut TokenIter) -> Result { match tokens.next() { Some(TokenTree::Ident(ident)) => Ok(ident), - other => bail!("expected ident: {:?}", other), + Some(other) => c_bail!(other.span(), "expected ident"), + None => c_bail!(before, "expected ident after this expression"), } } -pub fn match_punct(tokens: &mut TokenIter, punct: char) -> Result<(), Error> { +pub fn match_punct(span: Span, tokens: &mut TokenIter, punct: char) -> Result { if let Some(tt) = tokens.next() { if let TokenTree::Punct(p) = tt { if p.as_char() == punct { - return Ok(()); + return Ok(p.span()); } } } - bail!("expected `{}`", punct); + c_bail!(span, "expected `{}` after this expression", punct); } pub fn need_group(tokens: &mut TokenIter, delimiter: Delimiter) -> Result { @@ -91,11 +96,19 @@ pub fn need_group(tokens: &mut TokenIter, delimiter: Delimiter) -> Result Result<(), Error> { match tokens.next() { Some(TokenTree::Punct(ref punct)) if punct.as_char() == ':' => Ok(()), - Some(other) => bail!("expected colon at {:?}", other.span()), + Some(other) => c_bail!(other.span(), "expected colon"), None => bail!("colon expected"), } } +pub fn match_colon2(span: Span, tokens: &mut TokenIter) -> Result { + match tokens.next() { + Some(TokenTree::Punct(ref punct)) if punct.as_char() == ':' => Ok(punct.span()), + Some(other) => c_bail!(other.span(), "expected colon"), + None => c_bail!(span, "colon expected following this expression"), + } +} + pub fn maybe_comma(tokens: &mut TokenIter) -> Result { match tokens.next() { Some(TokenTree::Punct(ref punct)) if punct.as_char() == ',' => Ok(true), @@ -119,8 +132,8 @@ pub fn comma_or_end(tokens: &mut TokenIter) -> Result<(), Error> { Ok(()) } -pub fn need_hyphenated_name(tokens: &mut TokenIter) -> Result { - let start = need_ident(&mut *tokens)?; +pub fn need_hyphenated_name(span: Span, tokens: &mut TokenIter) -> Result { + let start = need_ident(span, &mut *tokens)?; finish_hyphenated_name(&mut *tokens, start) } @@ -313,12 +326,13 @@ pub fn parse_object(tokens: TokenStream) -> Result { } fn parse_object_key(tokens: &mut TokenIter) -> Result, Error> { - if tokens.peek().is_none() { - return Ok(None); - } + let span = match tokens.peek() { + Some(ref val) => val.span(), + None => return Ok(None), + }; let key = need_ident_or_string(&mut *tokens)?; - match_colon(&mut *tokens)?; + match_colon2(span, &mut *tokens)?; Ok(Some(key)) } diff --git a/proxmox-api-macro/src/router_macro.rs b/proxmox-api-macro/src/router_macro.rs index 5089aafb..fd9133a7 100644 --- a/proxmox-api-macro/src/router_macro.rs +++ b/proxmox-api-macro/src/router_macro.rs @@ -14,23 +14,26 @@ pub fn router_macro(input: TokenStream) -> Result { let mut out = TokenStream::new(); loop { - if input.peek().is_none() { - break; - } + let mut at_span = match input.peek() { + Some(ref val) => val.span(), + None => break, + }; let public = optional_visibility(&mut input)?; - match_keyword(&mut input, "static")?; - let router_name = need_ident(&mut input)?; + at_span = match_keyword(at_span, &mut input, "static")?; + let router_name = need_ident(at_span, &mut input)?; - match_colon(&mut input)?; - match_keyword(&mut input, "Router")?; - match_punct(&mut input, '<')?; - let body_type = need_ident(&mut input)?; - match_punct(&mut input, '>')?; + at_span = match_colon2(router_name.span(), &mut input)?; + at_span = match_keyword(at_span, &mut input, "Router")?; + at_span = match_punct(at_span, &mut input, '<')?; + let body_type = need_ident(at_span, &mut input)?; + at_span = match_punct(body_type.span(), &mut input, '>')?; - match_punct(&mut input, '=')?; + at_span = match_punct(at_span, &mut input, '=')?; let content = need_group(&mut input, Delimiter::Brace)?; + let _ = at_span; + at_span = content.span(); let router = parse_router(content.stream().into_iter().peekable())?; let router = router.into_token_stream(&body_type, Some((router_name, public))); @@ -39,7 +42,7 @@ pub fn router_macro(input: TokenStream) -> Result { out.extend(router); - match_punct(&mut input, ';')?; + match_punct(at_span, &mut input, ';')?; } Ok(out) @@ -270,7 +273,7 @@ fn parse_router(mut input: TokenIter) -> Result { loop { match parse_entry_key(&mut input)? { Some(Entry::Method(name)) => { - let function = need_ident(&mut input)?; + let function = need_ident(name.span(), &mut input)?; let method_ptr = match name.to_string().as_str() { "GET" => &mut router.get, @@ -334,7 +337,10 @@ fn parse_path_name(tokens: &mut TokenIter) -> Result { if group.delimiter() != Delimiter::Brace { bail!("invalid path component: {:?}", group); } - let name = need_hyphenated_name(&mut group.stream().into_iter().peekable())?; + let name = need_hyphenated_name( + group.span(), + &mut group.stream().into_iter().peekable(), + )?; push_component(&mut path, &mut component, &mut span); path.push(Component::Match(name));