Skip to content

Commit af8cce5

Browse files
committed
Pass generic parameters when referencing structs/enums (#2)
1 parent 923bda6 commit af8cce5

File tree

3 files changed

+54
-8
lines changed

3 files changed

+54
-8
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/imp.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ use venial::parse_declaration;
1818
use venial::Attribute;
1919
use venial::AttributeValue;
2020
use venial::Declaration;
21+
use venial::GenericParam;
22+
use venial::GenericParamList;
2123
use venial::StructFields;
2224

2325
fn stream_span(input: impl Iterator<Item = impl Deref<Target = TokenTree>>) -> Option<Span> {
@@ -40,15 +42,15 @@ pub(crate) fn recurse_through_definition(
4042
mut strike_attrs: Vec<Attribute>,
4143
make_pub: bool,
4244
ret: &mut TokenStream,
43-
) {
45+
) -> Option<GenericParamList> {
4446
let span = stream_span(input.clone().into_iter().map(Cow::Owned));
4547
let input = move_out_inner_attrs(input);
4648
let mut parsed = match parse_declaration(input) {
4749
Ok(parsed) => parsed,
4850
Err(e) => {
4951
// Sadly, venial still panics on invalid syntax
5052
report_error(span, ret, &format!("{}", e));
51-
return;
53+
return None;
5254
}
5355
};
5456
match &mut parsed {
@@ -74,11 +76,12 @@ pub(crate) fn recurse_through_definition(
7476
}
7577
}
7678
_ => {
77-
return report_error(
79+
report_error(
7880
span,
7981
ret,
8082
"Unsupported declaration (only struct and enum are allowed)",
8183
);
84+
return None;
8285
}
8386
}
8487
if let Declaration::Struct(s) = &mut parsed {
@@ -89,6 +92,7 @@ pub(crate) fn recurse_through_definition(
8992
}
9093
}
9194
parsed.to_tokens(ret);
95+
parsed.generic_params().cloned()
9296
}
9397

9498
pub(crate) fn make_pub_marker() -> venial::VisMarker {
@@ -292,14 +296,14 @@ fn recurse_through_type(
292296
.iter()
293297
.position(|t| matches!(t, TokenTree::Ident(kw) if is_decl_kw(kw)))
294298
.unwrap();
295-
if let Some(name @ TokenTree::Ident(_)) = decl.get(pos + 1) {
299+
let generics = if let Some(name @ TokenTree::Ident(_)) = decl.get(pos + 1) {
296300
type_ret.push(name.clone());
297301
recurse_through_definition(
298302
decl.into_iter().collect(),
299303
strike_attrs.to_vec(),
300304
pub_hint,
301305
ret,
302-
);
306+
)
303307
} else {
304308
let name = match name_hint {
305309
Some(name) => TokenTree::Ident(name.clone()),
@@ -315,8 +319,27 @@ fn recurse_through_type(
315319
let tail = decl.drain((pos + 1)..).collect::<TokenStream>();
316320
let head = decl.into_iter().collect::<TokenStream>();
317321
let newthing = quote! {#head #name #tail};
318-
recurse_through_definition(newthing, strike_attrs.to_vec(), pub_hint, ret);
322+
let generics =
323+
recurse_through_definition(newthing, strike_attrs.to_vec(), pub_hint, ret);
324+
319325
type_ret.push(name);
326+
generics
327+
};
328+
if let Some(generics) = generics {
329+
type_ret.push(generics.tk_l_bracket.into());
330+
let mut gp = generics.params.clone();
331+
gp.iter_mut().for_each(|(gp, _)| {
332+
*gp = GenericParam {
333+
name: gp.name.clone(),
334+
tk_prefix: gp
335+
.tk_prefix
336+
.clone()
337+
.filter(|pfx| matches!(pfx, TokenTree::Punct(_))),
338+
bound: None,
339+
}
340+
});
341+
type_ret.extend(gp.into_token_stream());
342+
type_ret.push(generics.tk_r_bracket.into());
320343
}
321344
} else {
322345
un_type_tree(tok, type_ret, |g, type_ret| {

src/test.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ fn generics_on_def() {
306306
let out = quote! {
307307
struct Unnamed < T > { t : T }
308308
struct Named < T > { t : T }
309-
struct Outer { unnamed : Unnamed , whatev : Named , }
309+
struct Outer { unnamed : Unnamed <T> , whatev : Named <T> , }
310310
};
311311
check(from, out);
312312
}
@@ -442,3 +442,26 @@ fn pub_markers_sane() {
442442
use crate::imp::*;
443443
assert!(is_plain_pub(&Some(make_pub_marker())))
444444
}
445+
446+
#[test]
447+
fn issue_2() {
448+
let from = quote! {
449+
pub enum Expr<'src> {
450+
Binary(struct<'src> {
451+
left: Box<Expr<'src>>,
452+
operator: BinaryOp,
453+
right: Box<Expr<'src>>,
454+
}),
455+
Literal(enum<'src> {
456+
StringLit(&'src str),
457+
NumLit(&'src str),
458+
}),
459+
}
460+
};
461+
let out = quote! {
462+
struct Binary < 'src > { left : Box < Expr < 'src >> , operator : BinaryOp , right : Box < Expr < 'src >> , }
463+
enum Literal < 'src > { StringLit (& 'src str) , NumLit (& 'src str) , }
464+
pub enum Expr < 'src > { Binary (Binary<'src>) , Literal (Literal<'src>) , }
465+
};
466+
check(from, out)
467+
}

0 commit comments

Comments
 (0)