mirror of
https://github.com/askama-rs/askama.git
synced 2025-09-29 22:11:17 +00:00
Merge pull request #266 from Kijewski/pr-enum-optimizations
Second round of optimizations extracted from PR to implement `enum` variants
This commit is contained in:
commit
829ebb0ab3
@ -95,7 +95,7 @@ pub use crate::helpers::PrimitiveType;
|
||||
/// `.render()`.
|
||||
///
|
||||
/// [dynamic methods calls]: <https://doc.rust-lang.org/stable/std/keyword.dyn.html>
|
||||
pub trait Template: fmt::Display {
|
||||
pub trait Template: fmt::Display + filters::FastWritable {
|
||||
/// Helper method which allocates a new `String` and renders into it
|
||||
fn render(&self) -> Result<String> {
|
||||
let mut buf = String::new();
|
||||
@ -152,17 +152,17 @@ pub trait Template: fmt::Display {
|
||||
impl<T: Template + ?Sized> Template for &T {
|
||||
#[inline]
|
||||
fn render_into<W: fmt::Write + ?Sized>(&self, writer: &mut W) -> Result<()> {
|
||||
T::render_into(self, writer)
|
||||
<T as Template>::render_into(self, writer)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn render(&self) -> Result<String> {
|
||||
T::render(self)
|
||||
<T as Template>::render(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_into<W: io::Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
|
||||
T::write_into(self, writer)
|
||||
<T as Template>::write_into(self, writer)
|
||||
}
|
||||
|
||||
const SIZE_HINT: usize = T::SIZE_HINT;
|
||||
@ -254,6 +254,7 @@ mod tests {
|
||||
#[test]
|
||||
fn dyn_template() {
|
||||
struct Test;
|
||||
|
||||
impl Template for Test {
|
||||
fn render_into<W: fmt::Write + ?Sized>(&self, writer: &mut W) -> Result<()> {
|
||||
Ok(writer.write_str("test")?)
|
||||
@ -271,6 +272,13 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
impl filters::FastWritable for Test {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, f: &mut W) -> crate::Result<()> {
|
||||
self.render_into(f)
|
||||
}
|
||||
}
|
||||
|
||||
fn render(t: &dyn DynTemplate) -> String {
|
||||
t.dyn_render().unwrap()
|
||||
}
|
||||
|
@ -307,7 +307,7 @@ impl RawConfig<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "config", derive(Deserialize))]
|
||||
#[cfg_attr(feature = "config", derive(serde::Deserialize))]
|
||||
struct General<'a> {
|
||||
#[cfg_attr(feature = "config", serde(borrow))]
|
||||
dirs: Option<Vec<&'a str>>,
|
||||
|
@ -22,22 +22,12 @@ use crate::integration::{Buffer, impl_everything, write_header};
|
||||
use crate::{BUILT_IN_FILTERS, CRATE, CompileError, FileInfo, MsgValidEscapers};
|
||||
|
||||
pub(crate) fn template_to_string(
|
||||
input: &TemplateInput<'_>,
|
||||
contexts: &HashMap<&Arc<Path>, Context<'_>, FxBuildHasher>,
|
||||
heritage: Option<&Heritage<'_, '_>>,
|
||||
) -> Result<String, CompileError> {
|
||||
let mut buf = Buffer::new();
|
||||
template_into_buffer(input, contexts, heritage, &mut buf, false)?;
|
||||
Ok(buf.into_string())
|
||||
}
|
||||
|
||||
pub(crate) fn template_into_buffer(
|
||||
input: &TemplateInput<'_>,
|
||||
contexts: &HashMap<&Arc<Path>, Context<'_>, FxBuildHasher>,
|
||||
heritage: Option<&Heritage<'_, '_>>,
|
||||
buf: &mut Buffer,
|
||||
only_template: bool,
|
||||
) -> Result<(), CompileError> {
|
||||
input: &TemplateInput<'_>,
|
||||
contexts: &HashMap<&Arc<Path>, Context<'_>, FxBuildHasher>,
|
||||
heritage: Option<&Heritage<'_, '_>>,
|
||||
target: Option<&str>,
|
||||
) -> Result<usize, CompileError> {
|
||||
let ctx = &contexts[&input.path];
|
||||
let generator = Generator::new(
|
||||
input,
|
||||
@ -47,7 +37,7 @@ pub(crate) fn template_into_buffer(
|
||||
input.block.is_some(),
|
||||
0,
|
||||
);
|
||||
let mut result = generator.build(ctx, buf, only_template);
|
||||
let mut result = generator.build(ctx, buf, target);
|
||||
if let Err(err) = &mut result {
|
||||
if err.span.is_none() {
|
||||
err.span = input.source_span;
|
||||
@ -110,24 +100,19 @@ impl<'a, 'h> Generator<'a, 'h> {
|
||||
mut self,
|
||||
ctx: &Context<'a>,
|
||||
buf: &mut Buffer,
|
||||
only_template: bool,
|
||||
) -> Result<(), CompileError> {
|
||||
if !only_template {
|
||||
target: Option<&str>,
|
||||
) -> Result<usize, CompileError> {
|
||||
if target.is_none() {
|
||||
buf.write(format_args!(
|
||||
"\
|
||||
const _: () = {{\
|
||||
extern crate {CRATE} as rinja;\
|
||||
"
|
||||
"const _: () = {{ extern crate {CRATE} as rinja;"
|
||||
));
|
||||
}
|
||||
|
||||
self.impl_template(ctx, buf)?;
|
||||
impl_everything(self.input.ast, buf, only_template);
|
||||
|
||||
if !only_template {
|
||||
let size_hint = self.impl_template(ctx, buf, target.unwrap_or("rinja::Template"))?;
|
||||
if target.is_none() {
|
||||
impl_everything(self.input.ast, buf);
|
||||
buf.write("};");
|
||||
}
|
||||
Ok(())
|
||||
Ok(size_hint)
|
||||
}
|
||||
|
||||
fn push_locals<T, F>(&mut self, callback: F) -> Result<T, CompileError>
|
||||
@ -178,8 +163,9 @@ impl<'a, 'h> Generator<'a, 'h> {
|
||||
&mut self,
|
||||
ctx: &Context<'a>,
|
||||
buf: &mut Buffer,
|
||||
target: &str,
|
||||
) -> Result<usize, CompileError> {
|
||||
write_header(self.input.ast, buf, "rinja::Template", None);
|
||||
write_header(self.input.ast, buf, target, None);
|
||||
buf.write(
|
||||
"fn render_into<RinjaW>(&self, writer: &mut RinjaW) -> rinja::Result<()>\
|
||||
where \
|
||||
@ -189,7 +175,6 @@ impl<'a, 'h> Generator<'a, 'h> {
|
||||
use rinja::helpers::core::fmt::Write as _;",
|
||||
);
|
||||
|
||||
buf.set_discard(self.buf_writable.discard);
|
||||
// Make sure the compiler understands that the generated code depends on the template files.
|
||||
let mut paths = self
|
||||
.contexts
|
||||
@ -212,14 +197,7 @@ impl<'a, 'h> Generator<'a, 'h> {
|
||||
}
|
||||
}
|
||||
|
||||
let size_hint = if let Some(heritage) = self.heritage {
|
||||
self.handle(heritage.root, heritage.root.nodes, buf, AstLevel::Top)
|
||||
} else {
|
||||
self.handle(ctx, ctx.nodes, buf, AstLevel::Top)
|
||||
}?;
|
||||
buf.set_discard(false);
|
||||
|
||||
self.flush_ws(Ws(None, None));
|
||||
let size_hint = self.impl_template_inner(ctx, buf)?;
|
||||
|
||||
buf.write(format_args!(
|
||||
"\
|
||||
@ -234,6 +212,22 @@ impl<'a, 'h> Generator<'a, 'h> {
|
||||
Ok(size_hint)
|
||||
}
|
||||
|
||||
fn impl_template_inner(
|
||||
&mut self,
|
||||
ctx: &Context<'a>,
|
||||
buf: &mut Buffer,
|
||||
) -> Result<usize, CompileError> {
|
||||
buf.set_discard(self.buf_writable.discard);
|
||||
let size_hint = if let Some(heritage) = self.heritage {
|
||||
self.handle(heritage.root, heritage.root.nodes, buf, AstLevel::Top)
|
||||
} else {
|
||||
self.handle(ctx, ctx.nodes, buf, AstLevel::Top)
|
||||
}?;
|
||||
self.flush_ws(Ws(None, None));
|
||||
buf.set_discard(false);
|
||||
Ok(size_hint)
|
||||
}
|
||||
|
||||
// Helper methods for handling node types
|
||||
|
||||
fn handle(
|
||||
|
@ -290,41 +290,37 @@ pub(crate) struct TemplateArgs {
|
||||
|
||||
impl TemplateArgs {
|
||||
pub(crate) fn new(ast: &syn::DeriveInput) -> Result<Self, CompileError> {
|
||||
// FIXME: implement once <https://github.com/rust-lang/rfcs/pull/3715> is stable
|
||||
if let syn::Data::Union(data) = &ast.data {
|
||||
return Err(CompileError::new_with_span(
|
||||
"rinja templates are not supported for `union` types, only `struct` and `enum`",
|
||||
None,
|
||||
Some(data.union_token.span),
|
||||
));
|
||||
}
|
||||
Self::from_partial(ast, PartialTemplateArgs::new(ast, &ast.attrs)?)
|
||||
}
|
||||
|
||||
let args = PartialTemplateArgs::new(&ast.attrs)?;
|
||||
let Some(template) = args.template else {
|
||||
return Err(CompileError::no_file_info(
|
||||
pub(crate) fn from_partial(
|
||||
ast: &syn::DeriveInput,
|
||||
args: Option<PartialTemplateArgs>,
|
||||
) -> Result<Self, CompileError> {
|
||||
let Some(args) = args else {
|
||||
return Err(CompileError::new_with_span(
|
||||
"no attribute `template` found",
|
||||
None,
|
||||
Some(ast.ident.span()),
|
||||
));
|
||||
};
|
||||
Ok(Self {
|
||||
source: match args.source {
|
||||
Some(PartialTemplateArgsSource::Path(s)) => {
|
||||
(Source::Path(s.value()), Some(s.span()))
|
||||
(Source::Path(s.value().into()), Some(s.span()))
|
||||
}
|
||||
Some(PartialTemplateArgsSource::Source(s)) => {
|
||||
(Source::Source(s.value().into()), Some(s.span()))
|
||||
}
|
||||
#[cfg(feature = "code-in-doc")]
|
||||
Some(PartialTemplateArgsSource::InDoc(s)) => {
|
||||
source_from_docs(s.span(), &args.meta_docs, ast)?
|
||||
}
|
||||
Some(PartialTemplateArgsSource::InDoc(span, source)) => (source, Some(span)),
|
||||
None => {
|
||||
return Err(CompileError::no_file_info(
|
||||
#[cfg(not(feature = "code-in-doc"))]
|
||||
"specify one template argument `path` or `source`",
|
||||
#[cfg(feature = "code-in-doc")]
|
||||
"specify one template argument `path`, `source` or `in_doc`",
|
||||
Some(template.span()),
|
||||
Some(args.template.span()),
|
||||
));
|
||||
}
|
||||
},
|
||||
@ -336,7 +332,7 @@ impl TemplateArgs {
|
||||
syntax: args.syntax.map(|value| value.value()),
|
||||
config: args.config.as_ref().map(|value| value.value()),
|
||||
whitespace: args.whitespace,
|
||||
template_span: Some(template.span()),
|
||||
template_span: Some(args.template.span()),
|
||||
config_span: args.config.as_ref().map(|value| value.span()),
|
||||
})
|
||||
}
|
||||
@ -368,7 +364,7 @@ impl TemplateArgs {
|
||||
#[cfg(feature = "code-in-doc")]
|
||||
fn source_from_docs(
|
||||
span: Span,
|
||||
docs: &[Attribute],
|
||||
docs: &[&Attribute],
|
||||
ast: &syn::DeriveInput,
|
||||
) -> Result<(Source, Option<Span>), CompileError> {
|
||||
let (source_span, source) = collect_comment_blocks(span, docs, ast)?;
|
||||
@ -380,7 +376,7 @@ fn source_from_docs(
|
||||
#[cfg(feature = "code-in-doc")]
|
||||
fn collect_comment_blocks(
|
||||
span: Span,
|
||||
docs: &[Attribute],
|
||||
docs: &[&Attribute],
|
||||
ast: &syn::DeriveInput,
|
||||
) -> Result<(Option<Span>, String), CompileError> {
|
||||
let mut source_span: Option<Span> = None;
|
||||
@ -547,9 +543,9 @@ fn extension(path: &Path) -> Option<&str> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq)]
|
||||
#[derive(Debug, Clone, Hash, PartialEq)]
|
||||
pub(crate) enum Source {
|
||||
Path(String),
|
||||
Path(Arc<str>),
|
||||
Source(Arc<str>),
|
||||
}
|
||||
|
||||
@ -649,10 +645,8 @@ pub(crate) fn get_template_source(
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct PartialTemplateArgs {
|
||||
pub(crate) template: Option<Ident>,
|
||||
pub(crate) meta_docs: Vec<Attribute>,
|
||||
pub(crate) template: Ident,
|
||||
pub(crate) source: Option<PartialTemplateArgsSource>,
|
||||
pub(crate) block: Option<LitStr>,
|
||||
pub(crate) print: Option<Print>,
|
||||
@ -663,34 +657,67 @@ pub(crate) struct PartialTemplateArgs {
|
||||
pub(crate) whitespace: Option<Whitespace>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum PartialTemplateArgsSource {
|
||||
Path(LitStr),
|
||||
Source(LitStr),
|
||||
#[cfg(feature = "code-in-doc")]
|
||||
InDoc(#[allow(dead_code)] LitBool),
|
||||
InDoc(Span, Source),
|
||||
}
|
||||
|
||||
// implement PartialTemplateArgs::new()
|
||||
const _: () = {
|
||||
impl PartialTemplateArgs {
|
||||
pub(crate) fn new(attrs: &[Attribute]) -> Result<Self, CompileError> {
|
||||
new(attrs)
|
||||
pub(crate) fn new(
|
||||
ast: &syn::DeriveInput,
|
||||
attrs: &[Attribute],
|
||||
) -> Result<Option<Self>, CompileError> {
|
||||
new(ast, attrs)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn new(attrs: &[Attribute]) -> Result<PartialTemplateArgs, CompileError> {
|
||||
let mut this = PartialTemplateArgs::default();
|
||||
fn new(
|
||||
ast: &syn::DeriveInput,
|
||||
attrs: &[Attribute],
|
||||
) -> Result<Option<PartialTemplateArgs>, CompileError> {
|
||||
// FIXME: implement once <https://github.com/rust-lang/rfcs/pull/3715> is stable
|
||||
if let syn::Data::Union(data) = &ast.data {
|
||||
return Err(CompileError::new_with_span(
|
||||
"rinja templates are not supported for `union` types, only `struct` and `enum`",
|
||||
None,
|
||||
Some(data.union_token.span),
|
||||
));
|
||||
}
|
||||
|
||||
#[cfg(feature = "code-in-doc")]
|
||||
let mut meta_docs = vec![];
|
||||
|
||||
let mut this = PartialTemplateArgs {
|
||||
template: Ident::new("template", Span::call_site()),
|
||||
source: None,
|
||||
block: None,
|
||||
print: None,
|
||||
escape: None,
|
||||
ext: None,
|
||||
syntax: None,
|
||||
config: None,
|
||||
whitespace: None,
|
||||
};
|
||||
let mut has_data = false;
|
||||
|
||||
for attr in attrs {
|
||||
let Some(ident) = attr.path().get_ident() else {
|
||||
continue;
|
||||
};
|
||||
if ident == "doc" {
|
||||
this.meta_docs.push(attr.clone());
|
||||
continue;
|
||||
} else if ident == "template" {
|
||||
this.template = Some(ident.clone());
|
||||
if ident == "template" {
|
||||
this.template = ident.clone();
|
||||
has_data = true;
|
||||
} else {
|
||||
#[cfg(feature = "code-in-doc")]
|
||||
if ident == "doc" {
|
||||
meta_docs.push(attr);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -742,7 +769,10 @@ const _: () = {
|
||||
}
|
||||
#[cfg(feature = "code-in-doc")]
|
||||
{
|
||||
this.source = Some(PartialTemplateArgsSource::InDoc(value));
|
||||
this.source = Some(PartialTemplateArgsSource::InDoc(
|
||||
value.span(),
|
||||
Source::Path("".into()),
|
||||
));
|
||||
}
|
||||
} else if ident == "block" {
|
||||
set_strlit_pair(ident, value, &mut this.block)?;
|
||||
@ -766,7 +796,20 @@ const _: () = {
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(this)
|
||||
if !has_data {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
#[cfg(feature = "code-in-doc")]
|
||||
if let Some(PartialTemplateArgsSource::InDoc(lit_span, _)) = this.source {
|
||||
let (source, doc_span) = source_from_docs(lit_span, &meta_docs, ast)?;
|
||||
this.source = Some(PartialTemplateArgsSource::InDoc(
|
||||
doc_span.unwrap_or(lit_span),
|
||||
source,
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Some(this))
|
||||
}
|
||||
|
||||
fn set_strlit_pair(
|
||||
|
@ -4,20 +4,18 @@ use quote::quote;
|
||||
use syn::DeriveInput;
|
||||
|
||||
/// Implement every integration for the given item
|
||||
pub(crate) fn impl_everything(ast: &DeriveInput, buf: &mut Buffer, only_template: bool) {
|
||||
pub(crate) fn impl_everything(ast: &DeriveInput, buf: &mut Buffer) {
|
||||
impl_display(ast, buf);
|
||||
impl_fast_writable(ast, buf);
|
||||
|
||||
if !only_template {
|
||||
#[cfg(feature = "with-actix-web")]
|
||||
impl_actix_web_responder(ast, buf);
|
||||
#[cfg(feature = "with-axum")]
|
||||
impl_axum_into_response(ast, buf);
|
||||
#[cfg(feature = "with-rocket")]
|
||||
impl_rocket_responder(ast, buf);
|
||||
#[cfg(feature = "with-warp")]
|
||||
impl_warp_reply(ast, buf);
|
||||
}
|
||||
#[cfg(feature = "with-actix-web")]
|
||||
impl_actix_web_responder(ast, buf);
|
||||
#[cfg(feature = "with-axum")]
|
||||
impl_axum_into_response(ast, buf);
|
||||
#[cfg(feature = "with-rocket")]
|
||||
impl_rocket_responder(ast, buf);
|
||||
#[cfg(feature = "with-warp")]
|
||||
impl_warp_reply(ast, buf);
|
||||
}
|
||||
|
||||
/// Writes header for the `impl` for `TraitFromPathName` or `Template` for the given item
|
||||
@ -258,6 +256,14 @@ impl Buffer {
|
||||
self.buf.clear();
|
||||
self.last_was_write_str = false;
|
||||
}
|
||||
|
||||
pub(crate) fn get_mark(&mut self) -> usize {
|
||||
self.buf.len()
|
||||
}
|
||||
|
||||
pub(crate) fn marked_text(&self, mark: usize) -> &str {
|
||||
&self.buf[..mark]
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait BufferFmt {
|
||||
|
@ -22,6 +22,7 @@ use config::{Config, read_config_file};
|
||||
use generator::template_to_string;
|
||||
use heritage::{Context, Heritage};
|
||||
use input::{Print, TemplateArgs, TemplateInput};
|
||||
use integration::Buffer;
|
||||
use parser::{Parsed, WithSpan, strip_common};
|
||||
#[cfg(not(feature = "__standalone"))]
|
||||
use proc_macro::TokenStream as TokenStream12;
|
||||
@ -126,16 +127,18 @@ pub fn derive_template(input: TokenStream12) -> TokenStream12 {
|
||||
return compile_error(msgs, Span::call_site()).into();
|
||||
}
|
||||
};
|
||||
match build_template(&ast) {
|
||||
Ok(source) => source.parse().unwrap(),
|
||||
Err(CompileError { msg, span }) => {
|
||||
let mut ts = compile_error(std::iter::once(msg), span.unwrap_or(ast.ident.span()));
|
||||
if let Ok(source) = build_skeleton(&ast) {
|
||||
let source: TokenStream = source.parse().unwrap();
|
||||
ts.extend(source);
|
||||
}
|
||||
ts.into()
|
||||
|
||||
let mut buf = Buffer::new();
|
||||
if let Err(CompileError { msg, span }) = build_template(&mut buf, &ast) {
|
||||
let mut ts = compile_error(std::iter::once(msg), span.unwrap_or(ast.ident.span()));
|
||||
buf.clear();
|
||||
if build_skeleton(&mut buf, &ast).is_ok() {
|
||||
let source: TokenStream = buf.into_string().parse().unwrap();
|
||||
ts.extend(source);
|
||||
}
|
||||
ts.into()
|
||||
} else {
|
||||
buf.into_string().parse().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,14 +153,14 @@ fn compile_error(msgs: impl Iterator<Item = String>, span: Span) -> TokenStream
|
||||
}
|
||||
}
|
||||
|
||||
fn build_skeleton(ast: &syn::DeriveInput) -> Result<String, CompileError> {
|
||||
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 mut contexts = HashMap::default();
|
||||
let parsed = parser::Parsed::default();
|
||||
contexts.insert(&input.path, Context::empty(&parsed));
|
||||
template_to_string(&input, &contexts, None)
|
||||
template_to_string(buf, &input, &contexts, None, None)
|
||||
}
|
||||
|
||||
/// Takes a `syn::DeriveInput` and generates source code for it
|
||||
@ -167,9 +170,12 @@ fn build_skeleton(ast: &syn::DeriveInput) -> Result<String, CompileError> {
|
||||
/// parsed, and the parse tree is fed to the code generator. Will print
|
||||
/// the parse tree and/or generated source according to the `print` key's
|
||||
/// value as passed to the `template()` attribute.
|
||||
pub(crate) fn build_template(ast: &syn::DeriveInput) -> Result<String, CompileError> {
|
||||
pub(crate) fn build_template(
|
||||
buf: &mut Buffer,
|
||||
ast: &syn::DeriveInput,
|
||||
) -> Result<usize, CompileError> {
|
||||
let template_args = TemplateArgs::new(ast)?;
|
||||
let mut result = build_template_inner(ast, &template_args);
|
||||
let mut result = build_template_item(buf, ast, &template_args, None);
|
||||
if let Err(err) = &mut result {
|
||||
if err.span.is_none() {
|
||||
err.span = template_args.source.1.or(template_args.template_span);
|
||||
@ -178,10 +184,12 @@ pub(crate) fn build_template(ast: &syn::DeriveInput) -> Result<String, CompileEr
|
||||
result
|
||||
}
|
||||
|
||||
fn build_template_inner(
|
||||
fn build_template_item(
|
||||
buf: &mut Buffer,
|
||||
ast: &syn::DeriveInput,
|
||||
template_args: &TemplateArgs,
|
||||
) -> Result<String, CompileError> {
|
||||
target: Option<&str>,
|
||||
) -> Result<usize, CompileError> {
|
||||
let config_path = template_args.config_path();
|
||||
let s = read_config_file(config_path, template_args.config_span)?;
|
||||
let config = Config::new(
|
||||
@ -222,11 +230,12 @@ fn build_template_inner(
|
||||
eprintln!("{:?}", templates[&input.path].nodes());
|
||||
}
|
||||
|
||||
let code = template_to_string(&input, &contexts, heritage.as_ref())?;
|
||||
let mark = buf.get_mark();
|
||||
let size_hint = template_to_string(buf, &input, &contexts, heritage.as_ref(), target)?;
|
||||
if input.print == Print::Code || input.print == Print::All {
|
||||
eprintln!("{code}");
|
||||
eprintln!("{}", buf.marked_text(mark));
|
||||
}
|
||||
Ok(code)
|
||||
Ok(size_hint)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -7,7 +7,13 @@ use console::style;
|
||||
use prettyplease::unparse;
|
||||
use similar::{Algorithm, ChangeTag, TextDiffConfig};
|
||||
|
||||
use crate::build_template;
|
||||
use crate::integration::Buffer;
|
||||
|
||||
fn build_template(ast: &syn::DeriveInput) -> Result<String, crate::CompileError> {
|
||||
let mut buf = Buffer::new();
|
||||
crate::build_template(&mut buf, ast)?;
|
||||
Ok(buf.into_string())
|
||||
}
|
||||
|
||||
// This function makes it much easier to compare expected code by adding the wrapping around
|
||||
// the code we want to check.
|
||||
|
Loading…
x
Reference in New Issue
Block a user