mirror of
https://github.com/askama-rs/askama.git
synced 2025-10-02 15:25:19 +00:00
Rename Expr::Attr
into Expr::AssociatedItem
This commit is contained in:
parent
338369a424
commit
ca6573bf56
@ -594,16 +594,18 @@ fn is_copyable_within_op(expr: &Expr<'_>, within_op: bool) -> bool {
|
||||
// will solve that issue. However, if the operand is
|
||||
// implicitly borrowed, then it's likely not even possible
|
||||
// to get the template to compile.
|
||||
_ => within_op && is_attr_self(expr),
|
||||
_ => within_op && is_associated_item_self(expr),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this is an `Attr` where the `obj` is `"self"`.
|
||||
fn is_attr_self(mut expr: &Expr<'_>) -> bool {
|
||||
/// Returns `true` if this is an `AssociatedItem` where the `obj` is `"self"`.
|
||||
fn is_associated_item_self(mut expr: &Expr<'_>) -> bool {
|
||||
loop {
|
||||
match expr {
|
||||
Expr::Attr(obj, _) if matches!(***obj, Expr::Var("self")) => return true,
|
||||
Expr::Attr(obj, _) if matches!(***obj, Expr::Attr(..)) => expr = obj,
|
||||
Expr::AssociatedItem(obj, _) if matches!(***obj, Expr::Var("self")) => return true,
|
||||
Expr::AssociatedItem(obj, _) if matches!(***obj, Expr::AssociatedItem(..)) => {
|
||||
expr = obj
|
||||
}
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use parser::node::CondTest;
|
||||
use parser::{Attr, CharLit, CharPrefix, Expr, Span, StrLit, Target, TyGenerics, WithSpan};
|
||||
use parser::{
|
||||
AssociatedItem, CharLit, CharPrefix, Expr, Span, StrLit, Target, TyGenerics, WithSpan,
|
||||
};
|
||||
use quote::quote;
|
||||
|
||||
use super::{
|
||||
@ -46,7 +48,7 @@ impl<'a> Generator<'a, '_> {
|
||||
}
|
||||
// If accessing a field then it most likely needs to be
|
||||
// borrowed, to prevent an attempt of moving.
|
||||
Expr::Attr(..) => buf.write(format_args!("(&{expr_code}).into_iter()")),
|
||||
Expr::AssociatedItem(..) => buf.write(format_args!("(&{expr_code}).into_iter()")),
|
||||
// Otherwise, we borrow `iter` assuming that it implements `IntoIterator`.
|
||||
_ => buf.write(format_args!("({expr_code}).into_iter()")),
|
||||
}
|
||||
@ -67,7 +69,9 @@ impl<'a> Generator<'a, '_> {
|
||||
Expr::Var(s) => self.visit_var(buf, s),
|
||||
Expr::Path(ref path) => self.visit_path(buf, path),
|
||||
Expr::Array(ref elements) => self.visit_array(ctx, buf, elements)?,
|
||||
Expr::Attr(ref obj, ref attr) => self.visit_attr(ctx, buf, obj, attr)?,
|
||||
Expr::AssociatedItem(ref obj, ref associated_item) => {
|
||||
self.visit_associated_item(ctx, buf, obj, associated_item)?
|
||||
}
|
||||
Expr::Index(ref obj, ref key) => self.visit_index(ctx, buf, obj, key)?,
|
||||
Expr::Filter(ref v) => {
|
||||
self.visit_filter(ctx, buf, &v.name, &v.arguments, &v.generics, expr.span())?
|
||||
@ -389,15 +393,15 @@ impl<'a> Generator<'a, '_> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn visit_attr(
|
||||
pub(crate) fn visit_associated_item(
|
||||
&mut self,
|
||||
ctx: &Context<'_>,
|
||||
buf: &mut Buffer,
|
||||
obj: &WithSpan<'a, Expr<'a>>,
|
||||
attr: &Attr<'a>,
|
||||
associated_item: &AssociatedItem<'a>,
|
||||
) -> Result<DisplayWrap, CompileError> {
|
||||
if let Expr::Var("loop") = **obj {
|
||||
buf.write(match attr.name {
|
||||
buf.write(match associated_item.name {
|
||||
"index0" => "__askama_item.index0",
|
||||
"index" => "(__askama_item.index0 + 1)",
|
||||
"first" => "(__askama_item.index0 == 0)",
|
||||
@ -413,8 +417,11 @@ impl<'a> Generator<'a, '_> {
|
||||
}
|
||||
|
||||
self.visit_expr(ctx, buf, obj)?;
|
||||
buf.write(format_args!(".{}", normalize_identifier(attr.name)));
|
||||
self.visit_call_generics(buf, &attr.generics);
|
||||
buf.write(format_args!(
|
||||
".{}",
|
||||
normalize_identifier(associated_item.name)
|
||||
));
|
||||
self.visit_call_generics(buf, &associated_item.generics);
|
||||
Ok(DisplayWrap::Unwrapped)
|
||||
}
|
||||
|
||||
@ -479,7 +486,9 @@ impl<'a> Generator<'a, '_> {
|
||||
generics: &[WithSpan<'a, TyGenerics<'a>>],
|
||||
) -> Result<DisplayWrap, CompileError> {
|
||||
match &**left {
|
||||
Expr::Attr(sub_left, Attr { name, .. }) if ***sub_left == Expr::Var("loop") => {
|
||||
Expr::AssociatedItem(sub_left, AssociatedItem { name, .. })
|
||||
if ***sub_left == Expr::Var("loop") =>
|
||||
{
|
||||
match *name {
|
||||
"cycle" => {
|
||||
if let [generic, ..] = generics {
|
||||
|
@ -196,7 +196,7 @@ impl<'a> Generator<'a, '_> {
|
||||
| Expr::Var(_)
|
||||
| Expr::Path(_)
|
||||
| Expr::Array(_)
|
||||
| Expr::Attr(_, _)
|
||||
| Expr::AssociatedItem(_, _)
|
||||
| Expr::Index(_, _)
|
||||
| Expr::Filter(_)
|
||||
| Expr::Range(_)
|
||||
@ -702,12 +702,12 @@ impl<'a> Generator<'a, '_> {
|
||||
this.locals
|
||||
.insert(Cow::Borrowed(arg), LocalMeta::with_ref(var));
|
||||
}
|
||||
Expr::Attr(obj, attr) => {
|
||||
let mut attr_buf = Buffer::new();
|
||||
this.visit_attr(ctx, &mut attr_buf, obj, attr)?;
|
||||
Expr::AssociatedItem(obj, associated_item) => {
|
||||
let mut associated_item_buf = Buffer::new();
|
||||
this.visit_associated_item(ctx, &mut associated_item_buf, obj, associated_item)?;
|
||||
|
||||
let attr = attr_buf.into_string();
|
||||
let var = this.locals.resolve(&attr).unwrap_or(attr);
|
||||
let associated_item = associated_item_buf.into_string();
|
||||
let var = this.locals.resolve(&associated_item).unwrap_or(associated_item);
|
||||
this.locals
|
||||
.insert(Cow::Borrowed(arg), LocalMeta::with_ref(var));
|
||||
}
|
||||
@ -1133,12 +1133,20 @@ impl<'a> Generator<'a, '_> {
|
||||
this.locals
|
||||
.insert(Cow::Borrowed(arg), LocalMeta::with_ref(var));
|
||||
}
|
||||
Expr::Attr(obj, attr) => {
|
||||
let mut attr_buf = Buffer::new();
|
||||
this.visit_attr(ctx, &mut attr_buf, obj, attr)?;
|
||||
Expr::AssociatedItem(obj, associated_item) => {
|
||||
let mut associated_item_buf = Buffer::new();
|
||||
this.visit_associated_item(
|
||||
ctx,
|
||||
&mut associated_item_buf,
|
||||
obj,
|
||||
associated_item,
|
||||
)?;
|
||||
|
||||
let attr = attr_buf.into_string();
|
||||
let var = this.locals.resolve(&attr).unwrap_or(attr);
|
||||
let associated_item = associated_item_buf.into_string();
|
||||
let var = this
|
||||
.locals
|
||||
.resolve(&associated_item)
|
||||
.unwrap_or(associated_item);
|
||||
this.locals
|
||||
.insert(Cow::Borrowed(arg), LocalMeta::with_ref(var));
|
||||
}
|
||||
@ -1639,7 +1647,7 @@ fn is_cacheable(expr: &WithSpan<'_, Expr<'_>>) -> bool {
|
||||
Expr::Path(_) => true,
|
||||
// Check recursively:
|
||||
Expr::Array(args) => args.iter().all(is_cacheable),
|
||||
Expr::Attr(lhs, _) => is_cacheable(lhs),
|
||||
Expr::AssociatedItem(lhs, _) => is_cacheable(lhs),
|
||||
Expr::Index(lhs, rhs) => is_cacheable(lhs) && is_cacheable(rhs),
|
||||
Expr::Filter(v) => v.arguments.iter().all(is_cacheable),
|
||||
Expr::Unary(_, arg) => is_cacheable(arg),
|
||||
|
@ -84,11 +84,11 @@ fn check_expr<'a>(expr: &WithSpan<'a, Expr<'a>>, allowed: Allowed) -> Result<(),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Expr::Attr(elem, attr) => {
|
||||
if attr.name == "_" {
|
||||
Err(err_underscore_identifier(attr.name))
|
||||
} else if !crate::can_be_variable_name(attr.name) {
|
||||
Err(err_reserved_identifier(attr.name))
|
||||
Expr::AssociatedItem(elem, associated_item) => {
|
||||
if associated_item.name == "_" {
|
||||
Err(err_underscore_identifier(associated_item.name))
|
||||
} else if !crate::can_be_variable_name(associated_item.name) {
|
||||
Err(err_reserved_identifier(associated_item.name))
|
||||
} else {
|
||||
check_expr(elem, Allowed::default())
|
||||
}
|
||||
@ -163,7 +163,7 @@ pub enum Expr<'a> {
|
||||
Var(&'a str),
|
||||
Path(Vec<&'a str>),
|
||||
Array(Vec<WithSpan<'a, Expr<'a>>>),
|
||||
Attr(Box<WithSpan<'a, Expr<'a>>>, Attr<'a>),
|
||||
AssociatedItem(Box<WithSpan<'a, Expr<'a>>>, AssociatedItem<'a>),
|
||||
Index(Box<WithSpan<'a, Expr<'a>>>, Box<WithSpan<'a, Expr<'a>>>),
|
||||
Filter(Box<Filter<'a>>),
|
||||
As(Box<WithSpan<'a, Expr<'a>>>, &'a str),
|
||||
@ -460,7 +460,7 @@ impl<'a> Expr<'a> {
|
||||
};
|
||||
let var_name = match *lhs {
|
||||
Self::Var(var_name) => var_name,
|
||||
Self::Attr(_, _) => {
|
||||
Self::AssociatedItem(_, _) => {
|
||||
return Err(ErrMode::Cut(ErrorContext::new(
|
||||
"`is defined` operator can only be used on variables, not on their fields",
|
||||
start,
|
||||
@ -632,7 +632,7 @@ impl<'a> Expr<'a> {
|
||||
| Self::Try(_)
|
||||
| Self::NamedArgument(_, _)
|
||||
| Self::Filter(_)
|
||||
| Self::Attr(_, _)
|
||||
| Self::AssociatedItem(_, _)
|
||||
| Self::Index(_, _)
|
||||
| Self::Tuple(_)
|
||||
| Self::Array(_)
|
||||
@ -677,13 +677,13 @@ pub struct Filter<'a> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Attr<'a> {
|
||||
pub struct AssociatedItem<'a> {
|
||||
pub name: &'a str,
|
||||
pub generics: Vec<WithSpan<'a, TyGenerics<'a>>>,
|
||||
}
|
||||
|
||||
enum Suffix<'a> {
|
||||
Attr(Attr<'a>),
|
||||
AssociatedItem(AssociatedItem<'a>),
|
||||
Index(WithSpan<'a, Expr<'a>>),
|
||||
Call {
|
||||
args: Vec<WithSpan<'a, Expr<'a>>>,
|
||||
@ -699,7 +699,7 @@ impl<'a> Suffix<'a> {
|
||||
let mut level_guard = level.guard();
|
||||
let mut expr = Expr::single(i, level)?;
|
||||
let mut right = opt(alt((
|
||||
|i: &mut _| Self::attr(i, level),
|
||||
|i: &mut _| Self::associated_item(i, level),
|
||||
|i: &mut _| Self::index(i, level),
|
||||
|i: &mut _| Self::call(i, level),
|
||||
Self::r#try,
|
||||
@ -714,8 +714,11 @@ impl<'a> Suffix<'a> {
|
||||
level_guard.nest(before_suffix)?;
|
||||
|
||||
match suffix {
|
||||
Self::Attr(attr) => {
|
||||
expr = WithSpan::new(Expr::Attr(expr.into(), attr), before_suffix)
|
||||
Self::AssociatedItem(associated_item) => {
|
||||
expr = WithSpan::new(
|
||||
Expr::AssociatedItem(expr.into(), associated_item),
|
||||
before_suffix,
|
||||
)
|
||||
}
|
||||
Self::Index(index) => {
|
||||
expr = WithSpan::new(Expr::Index(expr.into(), index.into()), before_suffix);
|
||||
@ -1034,7 +1037,7 @@ impl<'a> Suffix<'a> {
|
||||
(|i: &mut _| macro_arguments(i, open_token)).parse_next(i)
|
||||
}
|
||||
|
||||
fn attr(i: &mut &'a str, level: Level<'_>) -> ParseResult<'a, Self> {
|
||||
fn associated_item(i: &mut &'a str, level: Level<'_>) -> ParseResult<'a, Self> {
|
||||
preceded(
|
||||
ws(('.', not('.'))),
|
||||
cut_err((
|
||||
@ -1053,7 +1056,7 @@ impl<'a> Suffix<'a> {
|
||||
)),
|
||||
)
|
||||
.map(|(name, generics)| {
|
||||
Self::Attr(Attr {
|
||||
Self::AssociatedItem(AssociatedItem {
|
||||
name,
|
||||
generics: generics.unwrap_or_default(),
|
||||
})
|
||||
|
@ -27,7 +27,7 @@ use winnow::token::{any, none_of, one_of, take_till, take_while};
|
||||
use winnow::{ModalParser, Parser};
|
||||
|
||||
use crate::ascii_str::{AsciiChar, AsciiStr};
|
||||
pub use crate::expr::{Attr, Expr, Filter, TyGenerics};
|
||||
pub use crate::expr::{AssociatedItem, Expr, Filter, TyGenerics};
|
||||
pub use crate::node::Node;
|
||||
pub use crate::target::Target;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user