Skip to content

Commit 47bd68c

Browse files
committed
Remove use of procedural-masquerade
It’s unnecessary since Rust 1.30
1 parent 0c9c54b commit 47bd68c

File tree

5 files changed

+136
-118
lines changed

5 files changed

+136
-118
lines changed

Cargo.toml

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ dtoa-short = "0.3"
2424
heapsize = {version = ">= 0.3, < 0.5", optional = true}
2525
itoa = "0.4"
2626
matches = "0.1"
27-
phf = "0.8"
28-
procedural-masquerade = {path = "./procedural-masquerade", version = "0.1"}
27+
phf = {version = "0.8", features = ["macros"]}
2928
serde = {version = "1.0", optional = true}
3029
smallvec = "0.6"
3130

macros/Cargo.toml

+1-3
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@ description = "Procedural macros for cssparser"
66
documentation = "https://docs.rs/cssparser-macros/"
77
repository = "https://github.com/servo/rust-cssparser"
88
license = "MPL-2.0"
9+
edition = "2018"
910

1011
[lib]
1112
path = "lib.rs"
1213
proc-macro = true
1314

1415
[dependencies]
15-
procedural-masquerade = {path = "../procedural-masquerade", version = "0.1"}
16-
phf_codegen = "0.8"
1716
quote = "1"
1817
syn = {version = "1", features = ["full", "extra-traits"]}
19-
proc-macro2 = "1"

macros/lib.rs

+106-81
Original file line numberDiff line numberDiff line change
@@ -2,103 +2,128 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5-
#[macro_use]
6-
extern crate procedural_masquerade;
7-
extern crate phf_codegen;
85
extern crate proc_macro;
9-
extern crate proc_macro2;
10-
#[macro_use]
11-
extern crate quote;
12-
extern crate syn;
136

14-
use proc_macro2::{TokenStream, TokenTree};
15-
use quote::TokenStreamExt;
16-
use std::iter;
7+
use proc_macro::TokenStream;
178

18-
define_proc_macros! {
19-
/// Input: the arms of a `match` expression.
20-
///
21-
/// Output: a `MAX_LENGTH` constant with the length of the longest string pattern.
22-
///
23-
/// Panic if the arms contain non-string patterns,
24-
/// or string patterns that contains ASCII uppercase letters.
25-
#[allow(non_snake_case)]
26-
pub fn cssparser_internal__assert_ascii_lowercase__max_len(input: &str) -> String {
27-
let expr = syn::parse_str(&format!("match x {{ {} }}", input)).unwrap();
28-
let arms = match expr {
29-
syn::Expr::Match(syn::ExprMatch { arms, .. }) => arms,
30-
_ => panic!("expected a match expression, got {:?}", expr)
31-
};
32-
max_len(arms.into_iter().flat_map(|ref arm| {
33-
match arm.pat {
34-
syn::Pat::Or(ref p) => p.cases.iter().cloned().collect(),
35-
ref p => vec![p.clone()]
36-
}
37-
}).filter_map(|pattern| {
9+
/// Input: a `match` expression.
10+
///
11+
/// Output: a `MAX_LENGTH` constant with the length of the longest string pattern.
12+
///
13+
/// Panic if the arms contain non-string patterns,
14+
/// or string patterns that contains ASCII uppercase letters.
15+
#[allow(non_snake_case)]
16+
#[proc_macro]
17+
pub fn cssparser_internal__assert_ascii_lowercase__max_len(input: TokenStream) -> TokenStream {
18+
let expr: syn::ExprMatch = syn::parse_macro_input!(input);
19+
let strings = expr
20+
.arms
21+
.iter()
22+
.flat_map(|arm| match arm.pat {
23+
syn::Pat::Or(ref p) => p.cases.iter().collect(),
24+
ref p => vec![p],
25+
})
26+
.filter_map(|pattern| {
3827
let expr = match pattern {
3928
syn::Pat::Lit(expr) => expr,
4029
syn::Pat::Wild(_) => return None,
41-
_ => panic!("expected string or wildcard pattern, got {:?}", pattern)
30+
_ => panic!("expected string or wildcard pattern, got {:?}", pattern),
4231
};
4332
match *expr.expr {
44-
syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(ref lit), .. }) => {
45-
assert_eq!(lit.value(), lit.value().to_ascii_lowercase(),
46-
"string patterns must be given in ASCII lowercase");
47-
Some(lit.value().len())
33+
syn::Expr::Lit(syn::ExprLit {
34+
lit: syn::Lit::Str(ref lit),
35+
..
36+
}) => {
37+
assert_eq!(
38+
lit.value(),
39+
lit.value().to_ascii_lowercase(),
40+
"string patterns must be given in ASCII lowercase"
41+
);
42+
Some(lit)
4843
}
49-
_ => panic!("expected string pattern, got {:?}", expr)
44+
_ => panic!("expected string pattern, got {:?}", expr),
5045
}
51-
}))
52-
}
53-
54-
/// Input: string literals with no separator
55-
///
56-
/// Output: a `MAX_LENGTH` constant with the length of the longest string.
57-
#[allow(non_snake_case)]
58-
pub fn cssparser_internal__max_len(input: &str) -> String {
59-
max_len(syn::parse_str::<TokenStream>(input).unwrap().into_iter().map(|tt| string_literal(&tt).len()))
60-
}
46+
});
47+
max_len(strings)
48+
}
6149

62-
/// Input: parsed as token trees. The first TT is a type. (Can be wrapped in parens.)
63-
/// following TTs are grouped in pairs, each pair being a key as a string literal
64-
/// and the corresponding value as a const expression.
65-
///
66-
/// Output: a rust-phf map, with keys ASCII-lowercased:
67-
/// ```text
68-
/// static MAP: &'static ::cssparser::phf::Map<&'static str, $ValueType> = …;
69-
/// ```
70-
#[allow(non_snake_case)]
71-
pub fn cssparser_internal__phf_map(input: &str) -> String {
72-
let token_trees: Vec<TokenTree> = syn::parse_str::<TokenStream>(input).unwrap().into_iter().collect();
73-
let value_type = &token_trees[0];
74-
let pairs: Vec<_> = token_trees[1..].chunks(2).map(|chunk| {
75-
let key = string_literal(&chunk[0]);
76-
let value = &chunk[1];
77-
(key.to_ascii_lowercase(), quote!(#value).to_string())
78-
}).collect();
50+
/// Input: string literals with no separator
51+
///
52+
/// Output: a `MAX_LENGTH` constant with the length of the longest string.
53+
#[allow(non_snake_case)]
54+
#[proc_macro]
55+
pub fn cssparser_internal__max_len(input: TokenStream) -> TokenStream {
56+
struct Input(Vec<syn::LitStr>);
7957

80-
let mut map = phf_codegen::Map::new();
81-
map.phf_path("::cssparser::_internal__phf");
82-
for &(ref key, ref value) in &pairs {
83-
map.entry(&**key, &**value);
58+
impl syn::parse::Parse for Input {
59+
fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
60+
let mut strings = Vec::new();
61+
while !input.is_empty() {
62+
strings.push(input.parse()?)
63+
}
64+
Ok(Self(strings))
8465
}
85-
86-
let mut tokens = quote! {
87-
static MAP: ::cssparser::_internal__phf::Map<&'static str, #value_type> =
88-
};
89-
tokens.append_all(syn::parse_str::<proc_macro2::TokenStream>(&map.build().to_string()));
90-
tokens.append_all(quote!(;));
91-
tokens.to_string()
9266
}
67+
68+
let strings: Input = syn::parse_macro_input!(input);
69+
max_len(strings.0.iter())
9370
}
9471

95-
fn max_len<I: Iterator<Item = usize>>(lengths: I) -> String {
96-
let max_length = lengths.max().expect("expected at least one string");
97-
quote!( const MAX_LENGTH: usize = #max_length; ).to_string()
72+
fn max_len<'a, I: Iterator<Item = &'a syn::LitStr>>(strings: I) -> TokenStream {
73+
let max_length = strings
74+
.map(|s| s.value().len())
75+
.max()
76+
.expect("expected at least one string");
77+
quote::quote!( pub(super) const MAX_LENGTH: usize = #max_length; ).into()
9878
}
9979

100-
fn string_literal(token: &TokenTree) -> String {
101-
let lit: syn::LitStr = syn::parse2(iter::once(token.clone()).collect())
102-
.expect(&format!("expected string literal, got {:?}", token));
103-
lit.value()
80+
/// Input: A type, followed by pairs of string literal keys and expression values. No separator.
81+
///
82+
/// Output: a rust-phf map, with keys ASCII-lowercased:
83+
/// ```text
84+
/// static MAP: &'static ::cssparser::phf::Map<&'static str, $ValueType> = …;
85+
/// ```
86+
#[allow(non_snake_case)]
87+
#[proc_macro]
88+
pub fn cssparser_internal__phf_map(input: TokenStream) -> TokenStream {
89+
struct Input {
90+
value_type: syn::Type,
91+
keys: Vec<syn::LitStr>,
92+
values: Vec<syn::Expr>,
93+
}
94+
95+
impl syn::parse::Parse for Input {
96+
fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
97+
let mut keys = Vec::new();
98+
let mut values = Vec::new();
99+
let value_type = input.parse()?;
100+
while !input.is_empty() {
101+
keys.push(input.parse()?);
102+
values.push(input.parse()?);
103+
}
104+
Ok(Input {
105+
value_type,
106+
keys,
107+
values,
108+
})
109+
}
110+
}
111+
112+
let Input {
113+
value_type,
114+
keys,
115+
values,
116+
} = syn::parse_macro_input!(input);
117+
let keys = keys
118+
.iter()
119+
.map(|s| syn::LitStr::new(&s.value().to_ascii_lowercase(), s.span()));
120+
121+
quote::quote!(
122+
pub(super) static MAP: Map<&'static str, #value_type> = phf_map! {
123+
#(
124+
#keys => #values,
125+
)*
126+
};
127+
)
128+
.into()
104129
}

src/lib.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,16 @@ extern crate itoa;
7373
extern crate cssparser_macros;
7474
#[macro_use]
7575
extern crate matches;
76-
#[macro_use]
77-
extern crate procedural_masquerade;
7876
#[cfg(test)]
7977
extern crate difference;
8078
#[cfg(test)]
8179
extern crate encoding_rs;
8280
#[doc(hidden)]
8381
pub extern crate phf as _internal__phf;
84-
#[cfg(test)]
85-
extern crate serde_json;
8682
#[cfg(feature = "serde")]
8783
extern crate serde;
84+
#[cfg(test)]
85+
extern crate serde_json;
8886
#[cfg(feature = "heapsize")]
8987
#[macro_use]
9088
extern crate heapsize;

src/macros.rs

+26-28
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44

55
use std::mem::MaybeUninit;
66

7-
// See docs of the `procedural-masquerade` crate.
8-
define_invoke_proc_macro!(cssparser_internal__invoke_proc_macro);
9-
107
/// Expands to a `match` expression with string patterns,
118
/// matching case-insensitively in the ASCII range.
129
///
@@ -37,19 +34,22 @@ define_invoke_proc_macro!(cssparser_internal__invoke_proc_macro);
3734
macro_rules! match_ignore_ascii_case {
3835
( $input:expr, $( $match_body:tt )* ) => {
3936
{
40-
cssparser_internal__invoke_proc_macro! {
41-
cssparser_internal__assert_ascii_lowercase__max_len!( $( $match_body )* )
42-
}
43-
44-
{
45-
// MAX_LENGTH is generated by cssparser_internal__assert_ascii_lowercase__max_len
46-
cssparser_internal__to_lowercase!($input, MAX_LENGTH => lowercase);
47-
// "A" is a short string that we know is different for every string pattern,
48-
// since we’ve verified that none of them include ASCII upper case letters.
49-
match lowercase.unwrap_or("A") {
50-
$( $match_body )*
37+
// This dummy module works around the feature gate
38+
// `error[E0658]: procedural macros cannot be expanded to statements`
39+
// by forcing the macro to be in an item context
40+
// rather than expression/statement context,
41+
// even though the macro only expands to items.
42+
mod cssparser_internal {
43+
cssparser_internal__assert_ascii_lowercase__max_len! {
44+
match x { $( $match_body )* }
5145
}
5246
}
47+
cssparser_internal__to_lowercase!($input, cssparser_internal::MAX_LENGTH => lowercase);
48+
// "A" is a short string that we know is different for every string pattern,
49+
// since we’ve verified that none of them include ASCII upper case letters.
50+
match lowercase.unwrap_or("A") {
51+
$( $match_body )*
52+
}
5353
}
5454
};
5555
}
@@ -80,23 +80,21 @@ macro_rules! match_ignore_ascii_case {
8080
/// }
8181
#[macro_export]
8282
macro_rules! ascii_case_insensitive_phf_map {
83-
($name: ident -> $ValueType: ty = { $( $key: expr => $value: expr ),* }) => {
84-
ascii_case_insensitive_phf_map!($name -> $ValueType = { $( $key => $value, )* })
83+
($name: ident -> $ValueType: ty = { $( $key: tt => $value: expr ),+ }) => {
84+
ascii_case_insensitive_phf_map!($name -> $ValueType = { $( $key => $value, )+ })
8585
};
86-
($name: ident -> $ValueType: ty = { $( $key: expr => $value: expr, )* }) => {
86+
($name: ident -> $ValueType: ty = { $( $key: tt => $value: expr, )+ }) => {
8787
pub fn $name(input: &str) -> Option<&'static $ValueType> {
88-
cssparser_internal__invoke_proc_macro! {
89-
cssparser_internal__phf_map!( ($ValueType) $( $key ($value) )+ )
90-
}
91-
92-
{
93-
cssparser_internal__invoke_proc_macro! {
94-
cssparser_internal__max_len!( $( $key )+ )
95-
}
96-
// MAX_LENGTH is generated by cssparser_internal__max_len
97-
cssparser_internal__to_lowercase!(input, MAX_LENGTH => lowercase);
98-
lowercase.and_then(|s| MAP.get(s))
88+
// This dummy module works around a feature gate,
89+
// see comment on the similar module in `match_ignore_ascii_case!` above.
90+
mod cssparser_internal {
91+
use $crate::_internal__phf::{Map, phf_map};
92+
#[allow(unused)] use super::*;
93+
cssparser_internal__max_len!( $( $key )+ );
94+
cssparser_internal__phf_map!( $ValueType $( $key $value )+ );
9995
}
96+
cssparser_internal__to_lowercase!(input, cssparser_internal::MAX_LENGTH => lowercase);
97+
lowercase.and_then(|s| cssparser_internal::MAP.get(s))
10098
}
10199
}
102100
}

0 commit comments

Comments
 (0)