Skip to content

Commit

Permalink
Merge pull request #60 from CreepySkeleton/use-trybuild
Browse files Browse the repository at this point in the history
Use trybuild and move to proc-macro-error
  • Loading branch information
LukasKalbertodt committed Jan 12, 2020
2 parents be035a9 + 0ed1b90 commit a4a7f59
Show file tree
Hide file tree
Showing 26 changed files with 303 additions and 548 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ travis-ci = { repository = "auto-impl-rs/auto_impl" }
proc-macro = true

[features]
nightly = ["proc-macro2/nightly"]
nightly = []

[dependencies]
proc-macro2 = { version = "1.0" }
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "1.0", features = ["full", "visit", "visit-mut"] }
proc-macro-error = "0.4.4"

[dev-dependencies]
trybuild = "1"
Expand Down
2 changes: 0 additions & 2 deletions examples/error_messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
//! ```
//! cargo build --example error_messages
//! ```
//!
//! If you want to see nicer error messages, add `--features=nightly`.
#![allow(unused_imports, dead_code)]

use auto_impl::auto_impl;
Expand Down
83 changes: 40 additions & 43 deletions src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@
//! attached to trait items.

use proc_macro2::{Delimiter, TokenTree};
use proc_macro_error::{abort, emit_error};
use syn::{
spanned::Spanned,
visit_mut::{visit_item_trait_mut, VisitMut},
Attribute, TraitItem,
visit_mut::{VisitMut, visit_item_trait_mut},
};

use crate::{
diag::{DiagnosticExt, SpanExt},
proxy::{parse_types, ProxyType},
spanned::Spanned
};

use crate::proxy::{parse_types, ProxyType};

/// Removes all `#[auto_impl]` attributes that are attached to methods of the
/// given trait.
Expand All @@ -26,14 +23,19 @@ pub(crate) fn remove_our_attrs(trait_def: &mut syn::ItemTrait) {
TraitItem::Const(c) => (&mut c.attrs, false),
TraitItem::Type(t) => (&mut t.attrs, false),
TraitItem::Macro(m) => (&mut m.attrs, false),
_ => panic!("encountered unexpected `TraitItem`, cannot handle that, sorry!"),
_ => abort!(
item.span(),
"encountered unexpected `TraitItem`, cannot handle that, sorry!";
note = "auto-impl supports only methods, consts, types and macros currently";
),
};

// Make sure non-methods do not have our attributes.
if !is_method && attrs.iter().any(|a| is_our_attr(a)) {
item_span
.err("`auto_impl` attributes are only allowed on methods")
.emit();
emit_error!(
item_span,
"`#[auto_impl]` attributes are only allowed on methods",
);
}

attrs.retain(|a| !is_our_attr(a));
Expand All @@ -46,10 +48,7 @@ pub(crate) fn remove_our_attrs(trait_def: &mut syn::ItemTrait) {
/// Checks if the given attribute is "our" attribute. That means that it's path
/// is `auto_impl`.
pub(crate) fn is_our_attr(attr: &Attribute) -> bool {
attr.path.segments.len() == 1
&& attr.path.segments.iter().next().map(|seg| {
seg.ident == "auto_impl" && seg.arguments.is_empty()
}).unwrap()
attr.path.is_ident("auto_impl")
}

/// Tries to parse the given attribute as one of our own `auto_impl`
Expand All @@ -66,9 +65,12 @@ pub(crate) fn parse_our_attr(attr: &Attribute) -> Result<OurAttr, ()> {
let body = match &*tokens {
[TokenTree::Group(g)] => g.stream(),
_ => {
return attr.tokens.span()
.err(format!("expected single group delimitted by`()`, found '{:?}'", tokens))
.emit_with_attr_note();
emit_error!(
attr.tokens.span(),
"expected single group delimited by `()`, found '{:?}'",
tokens,
);
return Err(());
}
};

Expand All @@ -78,55 +80,50 @@ pub(crate) fn parse_our_attr(attr: &Attribute) -> Result<OurAttr, ()> {
let name = match it.next() {
Some(TokenTree::Ident(x)) => x,
Some(other) => {
return Spanned::span(&other)
.err(format!("expected ident, found '{}'", other))
.emit_with_attr_note();
emit_error!(other.span(), "expected ident, found '{}'", other);
return Err(());
}
None => {
return attr.tokens.span()
.err("expected ident, found nothing")
.emit_with_attr_note();
emit_error!(attr.tokens.span(), "expected ident, found nothing");
return Err(());
}
};

// Extract the parameters (which again, have to be a group delimitted by
// Extract the parameters (which again, have to be a group delimited by
// `()`)
let params = match it.next() {
Some(TokenTree::Group(ref g)) if g.delimiter() == Delimiter::Parenthesis => {
g.stream()
}
Some(other) => {
let msg = format!(
emit_error!(
other.span(),
"expected arguments for '{}' in parenthesis `()`, found `{}`",
name,
other,
);
return Spanned::span(&other)
.err(msg)
.emit_with_attr_note();
return Err(());
}
None => {
let msg = format!(
emit_error!(
body.span(),
"expected arguments for '{}' in parenthesis `()`, found nothing",
name,
);
return body.span()
.err(msg)
.emit_with_attr_note();
return Err(());
}
};

// Finally match over the name of the attribute.
let out = match () {
() if name == "keep_default_for" => {
let proxy_types = parse_types(params.into())?;
OurAttr::KeepDefaultFor(proxy_types)
}
_ => {
return Spanned::span(&name)
.err(format!("invalid attribute '{}'", name))
.emit_with_attr_note();
}
let out = if name == "keep_default_for" {
let proxy_types = parse_types(params.into());
OurAttr::KeepDefaultFor(proxy_types)
} else {
emit_error!(
name.span(), "invalid attribute '{}'", name;
note = "only `keep_default_for` is supported";
);
return Err(());
};

Ok(out)
Expand Down
190 changes: 0 additions & 190 deletions src/diag.rs

This file was deleted.

Loading

0 comments on commit a4a7f59

Please sign in to comment.