Remove duplicate spans for func args

This commit is contained in:
Laurenz 2020-07-18 18:02:38 +02:00
parent 332f83ed2d
commit 38a2424742
3 changed files with 23 additions and 37 deletions

View File

@ -132,7 +132,7 @@ macro_rules! function {
let func = $code; let func = $code;
for arg in header.args.into_iter() { for arg in header.args.into_iter() {
feedback.errors.push(err!(arg.span(); "unexpected argument")); feedback.errors.push(err!(arg.span; "unexpected argument"));
} }
$crate::Pass::new(func, feedback) $crate::Pass::new(func, feedback)

View File

@ -42,17 +42,22 @@ impl FuncArgs {
} }
/// Add an argument. /// Add an argument.
pub fn add(&mut self, arg: FuncArg) { pub fn add(&mut self, arg: Spanned<FuncArg>) {
match arg { match arg.v {
FuncArg::Pos(item) => self.pos.add(item), FuncArg::Pos(item) => self.pos.add(Spanned::new(item, arg.span)),
FuncArg::Key(pair) => self.key.add(pair), FuncArg::Key(pair) => self.key.add(Spanned::new(pair, arg.span)),
} }
} }
/// Iterate over all arguments. /// Iterate over all arguments.
pub fn into_iter(self) -> impl Iterator<Item=FuncArg> { pub fn into_iter(self) -> impl Iterator<Item=Spanned<FuncArg>> {
self.pos.items.into_iter().map(|item| FuncArg::Pos(item)) let pos = self.pos.items.into_iter()
.chain(self.key.pairs.into_iter().map(|pair| FuncArg::Key(pair))) .map(|spanned| spanned.map(|item| FuncArg::Pos(item)));
let key = self.key.pairs.into_iter()
.map(|spanned| spanned.map(|pair| FuncArg::Key(pair)));
pos.chain(key)
} }
} }
@ -60,7 +65,7 @@ impl FromIterator<Spanned<FuncArg>> for FuncArgs {
fn from_iter<I: IntoIterator<Item=Spanned<FuncArg>>>(iter: I) -> Self { fn from_iter<I: IntoIterator<Item=Spanned<FuncArg>>>(iter: I) -> Self {
let mut args = FuncArgs::new(); let mut args = FuncArgs::new();
for item in iter.into_iter() { for item in iter.into_iter() {
args.add(item.v); args.add(item);
} }
args args
} }
@ -70,22 +75,9 @@ impl FromIterator<Spanned<FuncArg>> for FuncArgs {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum FuncArg { pub enum FuncArg {
/// A positional argument. /// A positional argument.
Pos(Spanned<Expr>), Pos(Expr),
/// A keyword argument. /// A keyword argument.
Key(Spanned<Pair>), Key(Pair),
}
impl FuncArg {
/// The full span of this argument.
///
/// In case of a positional argument this is just the span of the expression
/// and in case of a keyword argument the combined span of key and value.
pub fn span(&self) -> Span {
match self {
FuncArg::Pos(item) => item.span,
FuncArg::Key(item) => item.span,
}
}
} }
/// Extra methods on [`Options`](Option) used for argument parsing. /// Extra methods on [`Options`](Option) used for argument parsing.

View File

@ -190,10 +190,8 @@ impl<'s> FuncParser<'s> {
if let Some(ident) = p.parse_ident() { if let Some(ident) = p.parse_ident() {
// This could still be a named tuple // This could still be a named tuple
if let Some(Token::LeftParen) = p.peekv() { if let Some(Token::LeftParen) = p.peekv() {
let n_tuple = p.parse_named_tuple(ident) let tuple = p.parse_named_tuple(ident);
.map(|t| Expr::NamedTuple(t)); return Ok(tuple.map(|t| FuncArg::Pos(Expr::NamedTuple(t))));
let span = n_tuple.span;
return Ok(Spanned::new(FuncArg::Pos(n_tuple), span));
} }
p.skip_whitespace(); p.skip_whitespace();
@ -210,22 +208,18 @@ impl<'s> FuncParser<'s> {
// Add a keyword argument. // Add a keyword argument.
let span = Span::merge(ident.span, value.span); let span = Span::merge(ident.span, value.span);
Ok(Spanned::new( let pair = Pair { key: ident, value };
FuncArg::Key(Spanned::new(Pair { key: ident, value }, span)), Ok(Spanned::new(FuncArg::Key(pair), span))
span,
))
} else { } else {
// Add a positional argument because there was no equals // Add a positional argument because there was no equals
// sign after the identifier that could have been a key. // sign after the identifier that could have been a key.
let ident = ident.map(|id| Expr::Ident(id)); Ok(ident.map(|id| FuncArg::Pos(Expr::Ident(id))))
let span = ident.span;
Ok(Spanned::new(FuncArg::Pos(ident), span))
} }
} else { } else {
// Add a positional argument because we haven't got an // Add a positional argument because we haven't got an
// identifier that could be an argument key. // identifier that could be an argument key.
p.parse_expr().map(|expr| Spanned { span: expr.span, v: FuncArg::Pos(expr) }) let value = p.parse_expr().ok_or(("argument", None))?;
.ok_or(("argument", None)) Ok(value.map(|expr| FuncArg::Pos(expr)))
} }
}).v }).v
} }