Skip to content

Commit 65e2d64

Browse files
committed
derive: for enums, let Self refer to the original type
1 parent 535df5e commit 65e2d64

File tree

5 files changed

+65
-5
lines changed

5 files changed

+65
-5
lines changed

rinja_derive/src/generator/expr.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use parser::{
55
Attr, CharLit, CharPrefix, Expr, Filter, IntKind, Num, Span, StrLit, StrPrefix, Target,
66
TyGenerics, WithSpan,
77
};
8+
use quote::quote;
89

910
use super::{
1011
DisplayWrap, FILTER_SOURCE, Generator, LocalMeta, TargetIsize, TargetUsize, Writable,
@@ -1057,9 +1058,17 @@ impl<'a> Generator<'a, '_> {
10571058
}
10581059

10591060
fn visit_path(&mut self, buf: &mut Buffer, path: &[&str]) -> DisplayWrap {
1060-
for (i, part) in path.iter().enumerate() {
1061+
for (i, part) in path.iter().copied().enumerate() {
10611062
if i > 0 {
10621063
buf.write("::");
1064+
} else if let Some(enum_ast) = self.input.enum_ast {
1065+
if part == "Self" {
1066+
let this = &enum_ast.ident;
1067+
let (_, generics, _) = enum_ast.generics.split_for_impl();
1068+
let generics = generics.as_turbofish();
1069+
buf.write(quote!(#this #generics));
1070+
continue;
1071+
}
10631072
}
10641073
buf.write(part);
10651074
}

rinja_derive/src/input.rs

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::{CompileError, FileInfo, MsgValidEscapers, OnceMap};
1919

2020
pub(crate) struct TemplateInput<'a> {
2121
pub(crate) ast: &'a syn::DeriveInput,
22+
pub(crate) enum_ast: Option<&'a syn::DeriveInput>,
2223
pub(crate) config: &'a Config,
2324
pub(crate) syntax: &'a SyntaxAndCache<'a>,
2425
pub(crate) source: &'a Source,
@@ -36,6 +37,7 @@ impl TemplateInput<'_> {
3637
/// `template()` attribute list fields.
3738
pub(crate) fn new<'n>(
3839
ast: &'n syn::DeriveInput,
40+
enum_ast: Option<&'n syn::DeriveInput>,
3941
config: &'n Config,
4042
args: &'n TemplateArgs,
4143
) -> Result<TemplateInput<'n>, CompileError> {
@@ -126,6 +128,7 @@ impl TemplateInput<'_> {
126128

127129
Ok(TemplateInput {
128130
ast,
131+
enum_ast,
129132
config,
130133
syntax,
131134
source,

rinja_derive/src/integration.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,12 @@ impl BufferFmt for Arguments<'_> {
210210
}
211211
}
212212

213+
impl BufferFmt for TokenStream {
214+
fn append_to(&self, buf: &mut String) {
215+
write!(buf, "{self}").unwrap();
216+
}
217+
}
218+
213219
/// Similar to `write!(dest, "{src:?}")`, but only escapes the strictly needed characters,
214220
/// and without the surrounding `"…"` quotation marks.
215221
fn string_escape(dest: &mut String, src: &str) {
@@ -271,7 +277,7 @@ pub(crate) fn build_template_enum(
271277
};
272278

273279
let var_ast = type_for_enum_variant(enum_ast, &generics, var);
274-
buf.write(quote!(#var_ast).to_string());
280+
buf.write(quote!(#var_ast));
275281

276282
// not inherited: template, meta_docs, block, print
277283
if let Some(enum_args) = &mut enum_args {
@@ -285,6 +291,7 @@ pub(crate) fn build_template_enum(
285291
let size_hint = biggest_size_hint.max(build_template_item(
286292
buf,
287293
&var_ast,
294+
Some(enum_ast),
288295
&TemplateArgs::from_partial(&var_ast, Some(var_args))?,
289296
TmplKind::Variant,
290297
)?);
@@ -302,6 +309,7 @@ pub(crate) fn build_template_enum(
302309
let size_hint = build_template_item(
303310
buf,
304311
enum_ast,
312+
None,
305313
&TemplateArgs::from_partial(enum_ast, enum_args)?,
306314
TmplKind::Variant,
307315
)?;

rinja_derive/src/lib.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ fn compile_error(msgs: impl Iterator<Item = String>, span: Span) -> TokenStream
155155
fn build_skeleton(buf: &mut Buffer, ast: &syn::DeriveInput) -> Result<usize, CompileError> {
156156
let template_args = TemplateArgs::fallback();
157157
let config = Config::new("", None, None, None)?;
158-
let input = TemplateInput::new(ast, config, &template_args)?;
158+
let input = TemplateInput::new(ast, None, config, &template_args)?;
159159
let mut contexts = HashMap::default();
160160
let parsed = parser::Parsed::default();
161161
contexts.insert(&input.path, Context::empty(&parsed));
@@ -177,7 +177,7 @@ pub(crate) fn build_template(
177177
let mut result = match AnyTemplateArgs::new(ast)? {
178178
AnyTemplateArgs::Struct(item) => {
179179
err_span = item.source.1.or(item.template_span);
180-
build_template_item(buf, ast, &item, TmplKind::Struct)
180+
build_template_item(buf, ast, None, &item, TmplKind::Struct)
181181
}
182182
AnyTemplateArgs::Enum {
183183
enum_args,
@@ -203,6 +203,7 @@ pub(crate) fn build_template(
203203
fn build_template_item(
204204
buf: &mut Buffer,
205205
ast: &syn::DeriveInput,
206+
enum_ast: Option<&syn::DeriveInput>,
206207
template_args: &TemplateArgs,
207208
tmpl_kind: TmplKind,
208209
) -> Result<usize, CompileError> {
@@ -214,7 +215,7 @@ fn build_template_item(
214215
template_args.whitespace,
215216
template_args.config_span,
216217
)?;
217-
let input = TemplateInput::new(ast, config, template_args)?;
218+
let input = TemplateInput::new(ast, enum_ast, config, template_args)?;
218219

219220
let mut templates = HashMap::default();
220221
input.find_used_templates(&mut templates)?;

testing/tests/enum.rs

+39
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,45 @@ fn test_enum_blocks() {
196196
);
197197
}
198198

199+
#[test]
200+
fn associated_contants() {
201+
#[derive(Template, Debug)]
202+
#[template(
203+
ext = "txt",
204+
source = "\
205+
{% block a -%} {{ Self::CONST_A }} {{ self.0 }} {%- endblock %}
206+
{% block b -%} {{ Self::CONST_B }} {{ self.0 }} {%- endblock %}
207+
{% block c -%} {{ Self::func_c(self.0) }} {{ self.0 }} {%- endblock %}
208+
"
209+
)]
210+
enum BlockEnum<'a, T: Display> {
211+
#[template(block = "a")]
212+
A(&'a str),
213+
#[template(block = "b")]
214+
B(T),
215+
#[template(block = "c")]
216+
C(&'a T),
217+
}
218+
219+
impl<'a, T: Display> BlockEnum<'a, T> {
220+
const CONST_A: &'static str = "<A>";
221+
const CONST_B: &'static str = "<B>";
222+
223+
fn func_c(_: &'a T) -> &'static str {
224+
"<C>"
225+
}
226+
}
227+
228+
let tmpl: BlockEnum<'_, X> = BlockEnum::A("hello");
229+
assert_eq!(tmpl.render().unwrap(), "<A> hello");
230+
231+
let tmpl: BlockEnum<'_, X> = BlockEnum::B(X);
232+
assert_eq!(tmpl.render().unwrap(), "<B> X");
233+
234+
let tmpl: BlockEnum<'_, X> = BlockEnum::C(&X);
235+
assert_eq!(tmpl.render().unwrap(), "<C> X");
236+
}
237+
199238
#[derive(Debug)]
200239
struct X;
201240

0 commit comments

Comments
 (0)