Implement better error reporting using spans of token subtrees
This commit is contained in:
parent
23ac36b559
commit
5890676710
|
@ -39,11 +39,11 @@ struct ContainerMeta {
|
||||||
impl ContainerMeta {
|
impl ContainerMeta {
|
||||||
fn from_derive(input: &syn::DeriveInput) -> Result<ContainerMeta, syn::Error> {
|
fn from_derive(input: &syn::DeriveInput) -> Result<ContainerMeta, syn::Error> {
|
||||||
let mut meta = ContainerMeta::default();
|
let mut meta = ContainerMeta::default();
|
||||||
for item in meta_items(&input.attrs) {
|
for (item, span) in meta_items(&input.attrs) {
|
||||||
match item {
|
match item {
|
||||||
MetaItem::Attribute => {
|
MetaItem::Attribute => {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
input.span(),
|
span,
|
||||||
"attribute key invalid in container xml attribute",
|
"attribute key invalid in container xml attribute",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ impl ContainerMeta {
|
||||||
MetaItem::RenameAll(lit) => {
|
MetaItem::RenameAll(lit) => {
|
||||||
meta.rename_all = match RenameRule::from_str(&lit.to_string()) {
|
meta.rename_all = match RenameRule::from_str(&lit.to_string()) {
|
||||||
Ok(rule) => rule,
|
Ok(rule) => rule,
|
||||||
Err(err) => return Err(syn::Error::new(input.span(), err)),
|
Err(err) => return Err(syn::Error::new(span, err)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
MetaItem::Scalar => meta.scalar = true,
|
MetaItem::Scalar => meta.scalar = true,
|
||||||
|
@ -72,20 +72,20 @@ struct FieldMeta {
|
||||||
impl FieldMeta {
|
impl FieldMeta {
|
||||||
fn from_field(input: &syn::Field) -> Result<FieldMeta, syn::Error> {
|
fn from_field(input: &syn::Field) -> Result<FieldMeta, syn::Error> {
|
||||||
let mut meta = FieldMeta::default();
|
let mut meta = FieldMeta::default();
|
||||||
for item in meta_items(&input.attrs) {
|
for (item, span) in meta_items(&input.attrs) {
|
||||||
match item {
|
match item {
|
||||||
MetaItem::Attribute => meta.attribute = true,
|
MetaItem::Attribute => meta.attribute = true,
|
||||||
MetaItem::Ns(ns) => meta.ns = ns,
|
MetaItem::Ns(ns) => meta.ns = ns,
|
||||||
MetaItem::Rename(lit) => meta.rename = Some(lit),
|
MetaItem::Rename(lit) => meta.rename = Some(lit),
|
||||||
MetaItem::RenameAll(_) => {
|
MetaItem::RenameAll(_) => {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
input.span(),
|
span,
|
||||||
"attribute 'rename_all' invalid in field xml attribute",
|
"attribute 'rename_all' invalid in field xml attribute",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
MetaItem::Scalar => {
|
MetaItem::Scalar => {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
input.span(),
|
span,
|
||||||
"attribute 'scalar' is invalid for struct fields",
|
"attribute 'scalar' is invalid for struct fields",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -114,31 +114,31 @@ impl VariantMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut rename = None;
|
let mut rename = None;
|
||||||
for item in meta_items(&input.attrs) {
|
for (item, span) in meta_items(&input.attrs) {
|
||||||
match item {
|
match item {
|
||||||
MetaItem::Rename(lit) => rename = Some(lit.to_token_stream()),
|
MetaItem::Rename(lit) => rename = Some(lit.to_token_stream()),
|
||||||
|
|
||||||
MetaItem::Attribute => {
|
MetaItem::Attribute => {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
input.span(),
|
span,
|
||||||
"attribute 'attribute' is invalid for enum variants",
|
"attribute 'attribute' is invalid for enum variants",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
MetaItem::Ns(_ns) => {
|
MetaItem::Ns(_ns) => {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
input.span(),
|
span,
|
||||||
"attribute 'ns' is invalid for enum variants",
|
"attribute 'ns' is invalid for enum variants",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
MetaItem::RenameAll(_) => {
|
MetaItem::RenameAll(_) => {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
input.span(),
|
span,
|
||||||
"attribute 'rename_all' invalid in field xml attribute",
|
"attribute 'rename_all' invalid in field xml attribute",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
MetaItem::Scalar => {
|
MetaItem::Scalar => {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
input.span(),
|
span,
|
||||||
"attribute 'scalar' is invalid for enum variants",
|
"attribute 'scalar' is invalid for enum variants",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -445,7 +445,7 @@ impl NamespaceMeta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn meta_items(attrs: &[syn::Attribute]) -> Vec<MetaItem> {
|
fn meta_items(attrs: &[syn::Attribute]) -> Vec<(MetaItem, Span)> {
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
let attr = match attrs.iter().find(|attr| attr.path.is_ident("xml")) {
|
let attr = match attrs.iter().find(|attr| attr.path.is_ident("xml")) {
|
||||||
Some(attr) => attr,
|
Some(attr) => attr,
|
||||||
|
@ -466,10 +466,11 @@ fn meta_items(attrs: &[syn::Attribute]) -> Vec<MetaItem> {
|
||||||
|
|
||||||
let mut state = MetaState::Start;
|
let mut state = MetaState::Start;
|
||||||
for tree in first {
|
for tree in first {
|
||||||
|
let span = tree.span();
|
||||||
state = match (state, tree) {
|
state = match (state, tree) {
|
||||||
(MetaState::Start, TokenTree::Ident(id)) => {
|
(MetaState::Start, TokenTree::Ident(id)) => {
|
||||||
if id == "attribute" {
|
if id == "attribute" {
|
||||||
items.push(MetaItem::Attribute);
|
items.push((MetaItem::Attribute, span));
|
||||||
MetaState::Comma
|
MetaState::Comma
|
||||||
} else if id == "ns" {
|
} else if id == "ns" {
|
||||||
MetaState::Ns
|
MetaState::Ns
|
||||||
|
@ -478,7 +479,7 @@ fn meta_items(attrs: &[syn::Attribute]) -> Vec<MetaItem> {
|
||||||
} else if id == "rename_all" {
|
} else if id == "rename_all" {
|
||||||
MetaState::RenameAll
|
MetaState::RenameAll
|
||||||
} else if id == "scalar" {
|
} else if id == "scalar" {
|
||||||
items.push(MetaItem::Scalar);
|
items.push((MetaItem::Scalar, span));
|
||||||
MetaState::Comma
|
MetaState::Comma
|
||||||
} else {
|
} else {
|
||||||
panic!("unexpected key in xml attribute");
|
panic!("unexpected key in xml attribute");
|
||||||
|
@ -490,21 +491,21 @@ fn meta_items(attrs: &[syn::Attribute]) -> Vec<MetaItem> {
|
||||||
(MetaState::Ns, TokenTree::Group(group))
|
(MetaState::Ns, TokenTree::Group(group))
|
||||||
if group.delimiter() == Delimiter::Parenthesis =>
|
if group.delimiter() == Delimiter::Parenthesis =>
|
||||||
{
|
{
|
||||||
items.push(MetaItem::Ns(NamespaceMeta::from_tokens(group)));
|
items.push((MetaItem::Ns(NamespaceMeta::from_tokens(group)), span));
|
||||||
MetaState::Comma
|
MetaState::Comma
|
||||||
}
|
}
|
||||||
(MetaState::Rename, TokenTree::Punct(punct)) if punct.as_char() == '=' => {
|
(MetaState::Rename, TokenTree::Punct(punct)) if punct.as_char() == '=' => {
|
||||||
MetaState::RenameValue
|
MetaState::RenameValue
|
||||||
}
|
}
|
||||||
(MetaState::RenameValue, TokenTree::Literal(lit)) => {
|
(MetaState::RenameValue, TokenTree::Literal(lit)) => {
|
||||||
items.push(MetaItem::Rename(lit));
|
items.push((MetaItem::Rename(lit), span));
|
||||||
MetaState::Comma
|
MetaState::Comma
|
||||||
}
|
}
|
||||||
(MetaState::RenameAll, TokenTree::Punct(punct)) if punct.as_char() == '=' => {
|
(MetaState::RenameAll, TokenTree::Punct(punct)) if punct.as_char() == '=' => {
|
||||||
MetaState::RenameAllValue
|
MetaState::RenameAllValue
|
||||||
}
|
}
|
||||||
(MetaState::RenameAllValue, TokenTree::Literal(lit)) => {
|
(MetaState::RenameAllValue, TokenTree::Literal(lit)) => {
|
||||||
items.push(MetaItem::RenameAll(lit));
|
items.push((MetaItem::RenameAll(lit), span));
|
||||||
MetaState::Comma
|
MetaState::Comma
|
||||||
}
|
}
|
||||||
(state, tree) => {
|
(state, tree) => {
|
||||||
|
|
Loading…
Reference in New Issue