Skip to content

Commit

Permalink
derive: for enums, let Self refer to the original type
Browse files Browse the repository at this point in the history
  • Loading branch information
Kijewski committed Feb 1, 2025
1 parent 535df5e commit 5c0de6a
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 5 deletions.
11 changes: 10 additions & 1 deletion rinja_derive/src/generator/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use parser::{
Attr, CharLit, CharPrefix, Expr, Filter, IntKind, Num, Span, StrLit, StrPrefix, Target,
TyGenerics, WithSpan,
};
use quote::quote;

use super::{
DisplayWrap, FILTER_SOURCE, Generator, LocalMeta, TargetIsize, TargetUsize, Writable,
Expand Down Expand Up @@ -1057,9 +1058,17 @@ impl<'a> Generator<'a, '_> {
}

fn visit_path(&mut self, buf: &mut Buffer, path: &[&str]) -> DisplayWrap {
for (i, part) in path.iter().enumerate() {
for (i, part) in path.iter().copied().enumerate() {
if i > 0 {
buf.write("::");
} else if let Some(enum_ast) = self.input.enum_ast {
if part == "Self" {
let this = &enum_ast.ident;
let (_, generics, _) = enum_ast.generics.split_for_impl();
let generics = generics.as_turbofish();
buf.write(quote!(#this #generics));
continue;
}
}
buf.write(part);
}
Expand Down
3 changes: 3 additions & 0 deletions rinja_derive/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::{CompileError, FileInfo, MsgValidEscapers, OnceMap};

pub(crate) struct TemplateInput<'a> {
pub(crate) ast: &'a syn::DeriveInput,
pub(crate) enum_ast: Option<&'a syn::DeriveInput>,
pub(crate) config: &'a Config,
pub(crate) syntax: &'a SyntaxAndCache<'a>,
pub(crate) source: &'a Source,
Expand All @@ -36,6 +37,7 @@ impl TemplateInput<'_> {
/// `template()` attribute list fields.
pub(crate) fn new<'n>(
ast: &'n syn::DeriveInput,
enum_ast: Option<&'n syn::DeriveInput>,
config: &'n Config,
args: &'n TemplateArgs,
) -> Result<TemplateInput<'n>, CompileError> {
Expand Down Expand Up @@ -126,6 +128,7 @@ impl TemplateInput<'_> {

Ok(TemplateInput {
ast,
enum_ast,
config,
syntax,
source,
Expand Down
10 changes: 9 additions & 1 deletion rinja_derive/src/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ impl BufferFmt for Arguments<'_> {
}
}

impl BufferFmt for TokenStream {
fn append_to(&self, buf: &mut String) {
write!(buf, "{self}").unwrap();
}
}

/// Similar to `write!(dest, "{src:?}")`, but only escapes the strictly needed characters,
/// and without the surrounding `"…"` quotation marks.
fn string_escape(dest: &mut String, src: &str) {
Expand Down Expand Up @@ -271,7 +277,7 @@ pub(crate) fn build_template_enum(
};

let var_ast = type_for_enum_variant(enum_ast, &generics, var);
buf.write(quote!(#var_ast).to_string());
buf.write(quote!(#var_ast));

// not inherited: template, meta_docs, block, print
if let Some(enum_args) = &mut enum_args {
Expand All @@ -285,6 +291,7 @@ pub(crate) fn build_template_enum(
let size_hint = biggest_size_hint.max(build_template_item(
buf,
&var_ast,
Some(enum_ast),
&TemplateArgs::from_partial(&var_ast, Some(var_args))?,
TmplKind::Variant,
)?);
Expand All @@ -302,6 +309,7 @@ pub(crate) fn build_template_enum(
let size_hint = build_template_item(
buf,
enum_ast,
None,
&TemplateArgs::from_partial(enum_ast, enum_args)?,
TmplKind::Variant,
)?;
Expand Down
7 changes: 4 additions & 3 deletions rinja_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ fn compile_error(msgs: impl Iterator<Item = String>, span: Span) -> TokenStream
fn build_skeleton(buf: &mut Buffer, ast: &syn::DeriveInput) -> Result<usize, CompileError> {
let template_args = TemplateArgs::fallback();
let config = Config::new("", None, None, None)?;
let input = TemplateInput::new(ast, config, &template_args)?;
let input = TemplateInput::new(ast, None, config, &template_args)?;
let mut contexts = HashMap::default();
let parsed = parser::Parsed::default();
contexts.insert(&input.path, Context::empty(&parsed));
Expand All @@ -177,7 +177,7 @@ pub(crate) fn build_template(
let mut result = match AnyTemplateArgs::new(ast)? {
AnyTemplateArgs::Struct(item) => {
err_span = item.source.1.or(item.template_span);
build_template_item(buf, ast, &item, TmplKind::Struct)
build_template_item(buf, ast, None, &item, TmplKind::Struct)
}
AnyTemplateArgs::Enum {
enum_args,
Expand All @@ -203,6 +203,7 @@ pub(crate) fn build_template(
fn build_template_item(
buf: &mut Buffer,
ast: &syn::DeriveInput,
enum_ast: Option<&syn::DeriveInput>,
template_args: &TemplateArgs,
tmpl_kind: TmplKind,
) -> Result<usize, CompileError> {
Expand All @@ -214,7 +215,7 @@ fn build_template_item(
template_args.whitespace,
template_args.config_span,
)?;
let input = TemplateInput::new(ast, config, template_args)?;
let input = TemplateInput::new(ast, enum_ast, config, template_args)?;

let mut templates = HashMap::default();
input.find_used_templates(&mut templates)?;
Expand Down
39 changes: 39 additions & 0 deletions testing/tests/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,45 @@ fn test_enum_blocks() {
);
}

#[test]
fn associated_constants() {
#[derive(Template, Debug)]
#[template(
ext = "txt",
source = "\
{% block a -%} {{ Self::CONST_A }} {{ self.0 }} {%- endblock %}
{% block b -%} {{ Self::CONST_B }} {{ self.0 }} {%- endblock %}
{% block c -%} {{ Self::func_c(self.0) }} {{ self.0 }} {%- endblock %}
"
)]
enum BlockEnum<'a, T: Display> {
#[template(block = "a")]
A(&'a str),
#[template(block = "b")]
B(T),
#[template(block = "c")]
C(&'a T),
}

impl<'a, T: Display> BlockEnum<'a, T> {
const CONST_A: &'static str = "<A>";
const CONST_B: &'static str = "<B>";

fn func_c(_: &'a T) -> &'static str {
"<C>"
}
}

let tmpl: BlockEnum<'_, X> = BlockEnum::A("hello");
assert_eq!(tmpl.render().unwrap(), "<A> hello");

let tmpl: BlockEnum<'_, X> = BlockEnum::B(X);
assert_eq!(tmpl.render().unwrap(), "<B> X");

let tmpl: BlockEnum<'_, X> = BlockEnum::C(&X);
assert_eq!(tmpl.render().unwrap(), "<C> X");
}

#[derive(Debug)]
struct X;

Expand Down

0 comments on commit 5c0de6a

Please sign in to comment.