summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaibo Huang <hhb@google.com>2020-09-30 05:13:57 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-09-30 05:13:57 +0000
commitdf30da36276dc22d98f49b08e92b457f4309d4f6 (patch)
tree69e46fa116b3825bcdf7a74834fa37f5c95916d3
parent443b69b5cd3925f4f4972f3689c27f70e2c32dc6 (diff)
parent3ac8fcf7c2141950e5f042977942fa1bc46172a4 (diff)
downloadproc-macro-error-attr-df30da36276dc22d98f49b08e92b457f4309d4f6.tar.gz
Upgrade rust/crates/proc-macro-error-attr to 1.0.4 am: f2a694b71a am: 3ac8fcf7c2
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/proc-macro-error-attr/+/1413681 Change-Id: Ibd5f441dd816170651692d003388f7ee6ef34123
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--.gitignore4
-rw-r--r--Android.bp8
-rw-r--r--Cargo.toml10
-rw-r--r--Cargo.toml.orig5
-rw-r--r--METADATA8
-rw-r--r--src/lib.rs153
-rw-r--r--src/parse.rs89
-rw-r--r--src/settings.rs72
9 files changed, 234 insertions, 117 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 0b126fe..1561cb4 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
{
"git": {
- "sha1": "69743a4ceab6c8da1ddb473f54a6a01840de90d9"
+ "sha1": "e231741c47af1beda78d53aee29500cccb8266cd"
}
}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5e81b66
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/target
+**/*.rs.bk
+Cargo.lock
+.fuse_hidden*
diff --git a/Android.bp b/Android.bp
index 4b2ac70..c2a35e2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -8,8 +8,6 @@ rust_proc_macro {
rustlibs: [
"libproc_macro2",
"libquote",
- "libsyn",
- "libsyn_mid",
],
compile_multilib: "first",
}
@@ -24,15 +22,11 @@ rust_test_host {
rustlibs: [
"libproc_macro2",
"libquote",
- "libsyn",
- "libsyn_mid",
],
}
// dependent_library ["feature_list"]
-// proc-macro2-1.0.19 "default,proc-macro"
+// proc-macro2-1.0.23 "default,proc-macro"
// quote-1.0.7 "default,proc-macro"
-// syn-1.0.36 "derive,parsing,printing,proc-macro,quote"
-// syn-mid-0.5.0
// unicode-xid-0.2.1 "default"
// version_check-0.9.2
diff --git a/Cargo.toml b/Cargo.toml
index 1365dbb..a2c766d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "proc-macro-error-attr"
-version = "1.0.2"
+version = "1.0.4"
authors = ["CreepySkeleton <creepy-skeleton@yandex.ru>"]
build = "build.rs"
description = "Attribute macro for proc-macro-error crate"
@@ -29,13 +29,5 @@ version = "1"
[dependencies.quote]
version = "1"
-
-[dependencies.syn]
-version = "1"
-features = ["derive", "parsing", "proc-macro", "printing"]
-default-features = false
-
-[dependencies.syn-mid]
-version = "0.5"
[build-dependencies.version_check]
version = "0.9"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 7414642..a6b7069 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "proc-macro-error-attr"
-version = "1.0.2"
+version = "1.0.4"
authors = ["CreepySkeleton <creepy-skeleton@yandex.ru>"]
edition = "2018"
description = "Attribute macro for proc-macro-error crate"
@@ -18,9 +18,6 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
quote = "1"
proc-macro2 = "1"
-syn-mid = "0.5"
-# "derive" is for `Attribute`, "parsing" is for `Parse`
-syn = { version = "1", default-features = false, features = ["derive", "parsing", "proc-macro", "printing"] }
[build-dependencies]
version_check = "0.9"
diff --git a/METADATA b/METADATA
index cdd4435..0864788 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/proc-macro-error-attr/proc-macro-error-attr-1.0.2.crate"
+ value: "https://static.crates.io/crates/proc-macro-error-attr/proc-macro-error-attr-1.0.4.crate"
}
- version: "1.0.2"
+ version: "1.0.4"
license_type: NOTICE
last_upgrade_date {
year: 2020
- month: 5
- day: 6
+ month: 9
+ day: 29
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 75953fe..ac0ac21 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,37 +3,59 @@
extern crate proc_macro;
+use crate::parse::parse_input;
+use crate::parse::Attribute;
use proc_macro::TokenStream;
-use proc_macro2::Ident;
-use quote::quote;
-use std::iter::FromIterator;
-use syn::{
- parse::{Parse, ParseStream},
- parse_macro_input,
- punctuated::Punctuated,
- Attribute, Token,
-};
-use syn_mid::{Block, ItemFn};
-
-use self::Setting::*;
+use proc_macro2::{Literal, Span, TokenStream as TokenStream2, TokenTree};
+use quote::{quote, quote_spanned};
+
+use crate::settings::{Setting::*, *};
+
+mod parse;
+mod settings;
+
+type Result<T> = std::result::Result<T, Error>;
+
+struct Error {
+ span: Span,
+ message: String,
+}
+
+impl Error {
+ fn new(span: Span, message: String) -> Self {
+ Error { span, message }
+ }
+
+ fn into_compile_error(self) -> TokenStream2 {
+ let mut message = Literal::string(&self.message);
+ message.set_span(self.span);
+ quote_spanned!(self.span=> compile_error!{#message})
+ }
+}
#[proc_macro_attribute]
pub fn proc_macro_error(attr: TokenStream, input: TokenStream) -> TokenStream {
- let input = parse_macro_input!(input as ItemFn);
- let mut settings = match syn::parse::<Settings>(attr) {
- Ok(settings) => settings,
- Err(err) => {
- let err = err.to_compile_error();
- return quote!(#input #err).into();
+ match impl_proc_macro_error(attr.into(), input.clone().into()) {
+ Ok(ts) => ts,
+ Err(e) => {
+ let error = e.into_compile_error();
+ let input = TokenStream2::from(input);
+
+ quote!(#input #error).into()
}
- };
+ }
+}
- let is_proc_macro = is_proc_macro(&input.attrs);
+fn impl_proc_macro_error(attr: TokenStream2, input: TokenStream2) -> Result<TokenStream> {
+ let (attrs, signature, body) = parse_input(input)?;
+ let mut settings = parse_settings(attr)?;
+
+ let is_proc_macro = is_proc_macro(&attrs);
if is_proc_macro {
settings.set(AssertUnwindSafe);
}
- if detect_proc_macro_hack(&input.attrs) {
+ if detect_proc_macro_hack(&attrs) {
settings.set(ProcMacroHack);
}
@@ -42,80 +64,27 @@ pub fn proc_macro_error(attr: TokenStream, input: TokenStream) -> TokenStream {
}
if !(settings.is_set(AllowNotMacro) || is_proc_macro) {
- return quote!(
- #input
- compile_error!(
- "#[proc_macro_error] attribute can be used only with a proc-macro\n\n \
- = hint: if you are really sure that #[proc_macro_error] should be applied \
- to this exact function use #[proc_macro_error(allow_not_macro)]\n");
- )
- .into();
+ return Err(Error::new(
+ Span::call_site(),
+ "#[proc_macro_error] attribute can be used only with procedural macros\n\n \
+ = hint: if you are really sure that #[proc_macro_error] should be applied \
+ to this exact function, use #[proc_macro_error(allow_not_macro)]\n"
+ .into(),
+ ));
}
- let ItemFn {
- attrs,
- vis,
- sig,
- block,
- } = input;
-
- let body = gen_body(*block, settings);
+ let body = gen_body(body, settings);
- quote!(
+ let res = quote! {
#(#attrs)*
- #vis
- #sig
+ #(#signature)*
{ #body }
- )
- .into()
-}
-
-#[derive(PartialEq)]
-enum Setting {
- AssertUnwindSafe,
- AllowNotMacro,
- ProcMacroHack,
-}
-
-impl Parse for Setting {
- fn parse(input: ParseStream) -> syn::Result<Self> {
- let ident: Ident = input.parse()?;
- match &*ident.to_string() {
- "assert_unwind_safe" => Ok(AssertUnwindSafe),
- "allow_not_macro" => Ok(AllowNotMacro),
- "proc_macro_hack" => Ok(ProcMacroHack),
- _ => Err(syn::Error::new(
- ident.span(),
- format!(
- "unknown setting `{}`, expected one of \
- `assert_unwind_safe`, `allow_not_macro`, `proc_macro_hack`",
- ident
- ),
- )),
- }
- }
-}
-
-struct Settings(Vec<Setting>);
-impl Parse for Settings {
- fn parse(input: ParseStream) -> syn::Result<Self> {
- let punct = Punctuated::<Setting, Token![,]>::parse_terminated(input)?;
- Ok(Settings(Vec::from_iter(punct)))
- }
-}
-
-impl Settings {
- fn is_set(&self, setting: Setting) -> bool {
- self.0.iter().any(|s| *s == setting)
- }
-
- fn set(&mut self, setting: Setting) {
- self.0.push(setting)
- }
+ };
+ Ok(res.into())
}
#[cfg(not(always_assert_unwind))]
-fn gen_body(block: Block, settings: Settings) -> proc_macro2::TokenStream {
+fn gen_body(block: TokenTree, settings: Settings) -> proc_macro2::TokenStream {
let is_proc_macro_hack = settings.is_set(ProcMacroHack);
let closure = if settings.is_set(AssertUnwindSafe) {
quote!(::std::panic::AssertUnwindSafe(|| #block ))
@@ -131,7 +100,7 @@ fn gen_body(block: Block, settings: Settings) -> proc_macro2::TokenStream {
// Considering this is the closure's return type the unwind safety check would fail
// for virtually every closure possible, the check is meaningless.
#[cfg(always_assert_unwind)]
-fn gen_body(block: Block, settings: Settings) -> proc_macro2::TokenStream {
+fn gen_body(block: TokenTree, settings: Settings) -> proc_macro2::TokenStream {
let is_proc_macro_hack = settings.is_set(ProcMacroHack);
let closure = quote!(::std::panic::AssertUnwindSafe(|| #block ));
quote!( ::proc_macro_error::entry_point(#closure, #is_proc_macro_hack) )
@@ -140,13 +109,13 @@ fn gen_body(block: Block, settings: Settings) -> proc_macro2::TokenStream {
fn detect_proc_macro_hack(attrs: &[Attribute]) -> bool {
attrs
.iter()
- .any(|attr| attr.path.is_ident("proc_macro_hack"))
+ .any(|attr| attr.path_is_ident("proc_macro_hack"))
}
fn is_proc_macro(attrs: &[Attribute]) -> bool {
attrs.iter().any(|attr| {
- attr.path.is_ident("proc_macro")
- || attr.path.is_ident("proc_macro_derive")
- || attr.path.is_ident("proc_macro_attribute")
+ attr.path_is_ident("proc_macro")
+ || attr.path_is_ident("proc_macro_derive")
+ || attr.path_is_ident("proc_macro_attribute")
})
}
diff --git a/src/parse.rs b/src/parse.rs
new file mode 100644
index 0000000..6f4663f
--- /dev/null
+++ b/src/parse.rs
@@ -0,0 +1,89 @@
+use crate::{Error, Result};
+use proc_macro2::{Delimiter, Ident, Span, TokenStream, TokenTree};
+use quote::ToTokens;
+use std::iter::Peekable;
+
+pub(crate) fn parse_input(
+ input: TokenStream,
+) -> Result<(Vec<Attribute>, Vec<TokenTree>, TokenTree)> {
+ let mut input = input.into_iter().peekable();
+ let mut attrs = Vec::new();
+
+ while let Some(attr) = parse_next_attr(&mut input)? {
+ attrs.push(attr);
+ }
+
+ let sig = parse_signature(&mut input);
+ let body = input.next().ok_or_else(|| {
+ Error::new(
+ Span::call_site(),
+ "`#[proc_macro_error]` can be applied only to functions".to_string(),
+ )
+ })?;
+
+ Ok((attrs, sig, body))
+}
+
+fn parse_next_attr(
+ input: &mut Peekable<impl Iterator<Item = TokenTree>>,
+) -> Result<Option<Attribute>> {
+ let shebang = match input.peek() {
+ Some(TokenTree::Punct(ref punct)) if punct.as_char() == '#' => input.next().unwrap(),
+ _ => return Ok(None),
+ };
+
+ let group = match input.peek() {
+ Some(TokenTree::Group(ref group)) if group.delimiter() == Delimiter::Bracket => {
+ let res = group.clone();
+ input.next();
+ res
+ }
+ other => {
+ let span = other.map_or(Span::call_site(), |tt| tt.span());
+ return Err(Error::new(span, "expected `[`".to_string()));
+ }
+ };
+
+ let path = match group.stream().into_iter().next() {
+ Some(TokenTree::Ident(ident)) => Some(ident),
+ _ => None,
+ };
+
+ Ok(Some(Attribute {
+ shebang,
+ group: TokenTree::Group(group),
+ path,
+ }))
+}
+
+fn parse_signature(input: &mut Peekable<impl Iterator<Item = TokenTree>>) -> Vec<TokenTree> {
+ let mut sig = Vec::new();
+ loop {
+ match input.peek() {
+ Some(TokenTree::Group(ref group)) if group.delimiter() == Delimiter::Brace => {
+ return sig;
+ }
+ None => return sig,
+ _ => sig.push(input.next().unwrap()),
+ }
+ }
+}
+
+pub(crate) struct Attribute {
+ pub(crate) shebang: TokenTree,
+ pub(crate) group: TokenTree,
+ pub(crate) path: Option<Ident>,
+}
+
+impl Attribute {
+ pub(crate) fn path_is_ident(&self, ident: &str) -> bool {
+ self.path.as_ref().map_or(false, |p| *p == ident)
+ }
+}
+
+impl ToTokens for Attribute {
+ fn to_tokens(&self, ts: &mut TokenStream) {
+ self.shebang.to_tokens(ts);
+ self.group.to_tokens(ts);
+ }
+}
diff --git a/src/settings.rs b/src/settings.rs
new file mode 100644
index 0000000..0b7ec76
--- /dev/null
+++ b/src/settings.rs
@@ -0,0 +1,72 @@
+use crate::{Error, Result};
+use proc_macro2::{Ident, Span, TokenStream, TokenTree};
+
+macro_rules! decl_settings {
+ ($($val:expr => $variant:ident),+ $(,)*) => {
+ #[derive(PartialEq)]
+ pub(crate) enum Setting {
+ $($variant),*
+ }
+
+ fn ident_to_setting(ident: Ident) -> Result<Setting> {
+ match &*ident.to_string() {
+ $($val => Ok(Setting::$variant),)*
+ _ => {
+ let possible_vals = [$($val),*]
+ .iter()
+ .map(|v| format!("`{}`", v))
+ .collect::<Vec<_>>()
+ .join(", ");
+
+ Err(Error::new(
+ ident.span(),
+ format!("unknown setting `{}`, expected one of {}", ident, possible_vals)))
+ }
+ }
+ }
+ };
+}
+
+decl_settings! {
+ "assert_unwind_safe" => AssertUnwindSafe,
+ "allow_not_macro" => AllowNotMacro,
+ "proc_macro_hack" => ProcMacroHack,
+}
+
+pub(crate) fn parse_settings(input: TokenStream) -> Result<Settings> {
+ let mut input = input.into_iter();
+ let mut res = Settings(Vec::new());
+ loop {
+ match input.next() {
+ Some(TokenTree::Ident(ident)) => {
+ res.0.push(ident_to_setting(ident)?);
+ }
+ None => return Ok(res),
+ other => {
+ let span = other.map_or(Span::call_site(), |tt| tt.span());
+ return Err(Error::new(span, "expected identifier".to_string()));
+ }
+ }
+
+ match input.next() {
+ Some(TokenTree::Punct(ref punct)) if punct.as_char() == ',' => {}
+ None => return Ok(res),
+ other => {
+ let span = other.map_or(Span::call_site(), |tt| tt.span());
+ return Err(Error::new(span, "expected `,`".to_string()));
+ }
+ }
+ }
+}
+
+pub(crate) struct Settings(Vec<Setting>);
+
+impl Settings {
+ pub(crate) fn is_set(&self, setting: Setting) -> bool {
+ self.0.iter().any(|s| *s == setting)
+ }
+
+ pub(crate) fn set(&mut self, setting: Setting) {
+ self.0.push(setting)
+ }
+}