templater: add property.into_dyn() helper

I'm going to move Box<dyn _> conversion to callers, so there will be more places
to use this helper.
This commit is contained in:
Yuya Nishihara 2025-04-30 10:59:41 +09:00
parent 533fb5e4bb
commit 96b633a091
4 changed files with 45 additions and 67 deletions

View File

@ -202,14 +202,8 @@ impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo> {
let type_name = "Commit";
let table = &self.build_fn_table.commit_methods;
let build = template_parser::lookup_method(type_name, table, function)?;
let inner_property = property.try_unwrap(type_name);
build(
self,
diagnostics,
build_ctx,
Box::new(inner_property),
function,
)
let inner_property = property.try_unwrap(type_name).into_dyn();
build(self, diagnostics, build_ctx, inner_property, function)
}
CommitTemplatePropertyKind::CommitList(property) => {
// TODO: migrate to table?
@ -232,14 +226,8 @@ impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo> {
let type_name = "CommitRef";
let table = &self.build_fn_table.commit_ref_methods;
let build = template_parser::lookup_method(type_name, table, function)?;
let inner_property = property.try_unwrap(type_name);
build(
self,
diagnostics,
build_ctx,
Box::new(inner_property),
function,
)
let inner_property = property.try_unwrap(type_name).into_dyn();
build(self, diagnostics, build_ctx, inner_property, function)
}
CommitTemplatePropertyKind::CommitRefList(property) => {
// TODO: migrate to table?
@ -262,14 +250,8 @@ impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo> {
let type_name = "RepoPath";
let table = &self.build_fn_table.repo_path_methods;
let build = template_parser::lookup_method(type_name, table, function)?;
let inner_property = property.try_unwrap(type_name);
build(
self,
diagnostics,
build_ctx,
Box::new(inner_property),
function,
)
let inner_property = property.try_unwrap(type_name).into_dyn();
build(self, diagnostics, build_ctx, inner_property, function)
}
CommitTemplatePropertyKind::CommitOrChangeId(property) => {
let table = &self.build_fn_table.commit_or_change_id_methods;
@ -313,21 +295,15 @@ impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo> {
let build = template_parser::lookup_method(type_name, table, function)?;
// Strip off formatting parameters which are needed only for the
// default template output.
let property = Box::new(property.map(|formatted| formatted.stats));
let property = property.map(|formatted| formatted.stats).into_dyn();
build(self, diagnostics, build_ctx, property, function)
}
CommitTemplatePropertyKind::CryptographicSignatureOpt(property) => {
let type_name = "CryptographicSignature";
let table = &self.build_fn_table.cryptographic_signature_methods;
let build = template_parser::lookup_method(type_name, table, function)?;
let inner_property = property.try_unwrap(type_name);
build(
self,
diagnostics,
build_ctx,
Box::new(inner_property),
function,
)
let inner_property = property.try_unwrap(type_name).into_dyn();
build(self, diagnostics, build_ctx, inner_property, function)
}
CommitTemplatePropertyKind::AnnotationLine(property) => {
let type_name = "AnnotationLine";
@ -557,21 +533,21 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::Core(property) => property.try_into_boolean(),
CommitTemplatePropertyKind::Commit(_) => None,
CommitTemplatePropertyKind::CommitOpt(property) => {
Some(Box::new(property.map(|opt| opt.is_some())))
Some(property.map(|opt| opt.is_some()).into_dyn())
}
CommitTemplatePropertyKind::CommitList(property) => {
Some(Box::new(property.map(|l| !l.is_empty())))
Some(property.map(|l| !l.is_empty()).into_dyn())
}
CommitTemplatePropertyKind::CommitRef(_) => None,
CommitTemplatePropertyKind::CommitRefOpt(property) => {
Some(Box::new(property.map(|opt| opt.is_some())))
Some(property.map(|opt| opt.is_some()).into_dyn())
}
CommitTemplatePropertyKind::CommitRefList(property) => {
Some(Box::new(property.map(|l| !l.is_empty())))
Some(property.map(|l| !l.is_empty()).into_dyn())
}
CommitTemplatePropertyKind::RepoPath(_) => None,
CommitTemplatePropertyKind::RepoPathOpt(property) => {
Some(Box::new(property.map(|opt| opt.is_some())))
Some(property.map(|opt| opt.is_some()).into_dyn())
}
CommitTemplatePropertyKind::CommitOrChangeId(_) => None,
CommitTemplatePropertyKind::ShortestIdPrefix(_) => None,
@ -580,17 +556,17 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::TreeDiff(_) => None,
CommitTemplatePropertyKind::TreeDiffEntry(_) => None,
CommitTemplatePropertyKind::TreeDiffEntryList(property) => {
Some(Box::new(property.map(|l| !l.is_empty())))
Some(property.map(|l| !l.is_empty()).into_dyn())
}
CommitTemplatePropertyKind::TreeEntry(_) => None,
CommitTemplatePropertyKind::DiffStats(_) => None,
CommitTemplatePropertyKind::CryptographicSignatureOpt(property) => {
Some(Box::new(property.map(|sig| sig.is_some())))
Some(property.map(|sig| sig.is_some()).into_dyn())
}
CommitTemplatePropertyKind::AnnotationLine(_) => None,
CommitTemplatePropertyKind::Trailer(_) => None,
CommitTemplatePropertyKind::TrailerList(property) => {
Some(Box::new(property.map(|l| !l.is_empty())))
Some(property.map(|l| !l.is_empty()).into_dyn())
}
}
}
@ -607,7 +583,7 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::Core(property) => property.try_into_plain_text(),
_ => {
let template = self.try_into_template()?;
Some(Box::new(PlainTextFormattedProperty::new(template)))
Some(PlainTextFormattedProperty::new(template).into_dyn())
}
}
}

View File

@ -184,7 +184,7 @@ impl IntoTemplateProperty<'static> for OperationTemplatePropertyKind {
OperationTemplatePropertyKind::Core(property) => property.try_into_plain_text(),
_ => {
let template = self.try_into_template()?;
Some(Box::new(PlainTextFormattedProperty::new(template)))
Some(PlainTextFormattedProperty::new(template).into_dyn())
}
}
}

View File

@ -237,20 +237,20 @@ impl<'a> IntoTemplateProperty<'a> for CoreTemplatePropertyKind<'a> {
fn try_into_boolean(self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'a>> {
match self {
CoreTemplatePropertyKind::String(property) => {
Some(Box::new(property.map(|s| !s.is_empty())))
Some(property.map(|s| !s.is_empty()).into_dyn())
}
CoreTemplatePropertyKind::StringList(property) => {
Some(Box::new(property.map(|l| !l.is_empty())))
Some(property.map(|l| !l.is_empty()).into_dyn())
}
CoreTemplatePropertyKind::Boolean(property) => Some(property),
CoreTemplatePropertyKind::Integer(_) => None,
CoreTemplatePropertyKind::IntegerOpt(property) => {
Some(Box::new(property.map(|opt| opt.is_some())))
Some(property.map(|opt| opt.is_some()).into_dyn())
}
CoreTemplatePropertyKind::ConfigValue(_) => None,
CoreTemplatePropertyKind::Signature(_) => None,
CoreTemplatePropertyKind::Email(property) => {
Some(Box::new(property.map(|e| !e.0.is_empty())))
Some(property.map(|e| !e.0.is_empty()).into_dyn())
}
CoreTemplatePropertyKind::SizeHint(_) => None,
CoreTemplatePropertyKind::Timestamp(_) => None,
@ -267,7 +267,7 @@ impl<'a> IntoTemplateProperty<'a> for CoreTemplatePropertyKind<'a> {
match self {
CoreTemplatePropertyKind::Integer(property) => Some(property),
CoreTemplatePropertyKind::IntegerOpt(property) => {
Some(Box::new(property.try_unwrap("Integer")))
Some(property.try_unwrap("Integer").into_dyn())
}
_ => None,
}
@ -278,7 +278,7 @@ impl<'a> IntoTemplateProperty<'a> for CoreTemplatePropertyKind<'a> {
CoreTemplatePropertyKind::String(property) => Some(property),
_ => {
let template = self.try_into_template()?;
Some(Box::new(PlainTextFormattedProperty::new(template)))
Some(PlainTextFormattedProperty::new(template).into_dyn())
}
}
}
@ -304,22 +304,22 @@ impl<'a> IntoTemplateProperty<'a> for CoreTemplatePropertyKind<'a> {
fn try_into_eq(self, other: Self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'a>> {
match (self, other) {
(CoreTemplatePropertyKind::String(lhs), CoreTemplatePropertyKind::String(rhs)) => {
Some(Box::new((lhs, rhs).map(|(l, r)| l == r)))
Some((lhs, rhs).map(|(l, r)| l == r).into_dyn())
}
(CoreTemplatePropertyKind::String(lhs), CoreTemplatePropertyKind::Email(rhs)) => {
Some(Box::new((lhs, rhs).map(|(l, r)| l == r.0)))
Some((lhs, rhs).map(|(l, r)| l == r.0).into_dyn())
}
(CoreTemplatePropertyKind::Boolean(lhs), CoreTemplatePropertyKind::Boolean(rhs)) => {
Some(Box::new((lhs, rhs).map(|(l, r)| l == r)))
Some((lhs, rhs).map(|(l, r)| l == r).into_dyn())
}
(CoreTemplatePropertyKind::Integer(lhs), CoreTemplatePropertyKind::Integer(rhs)) => {
Some(Box::new((lhs, rhs).map(|(l, r)| l == r)))
Some((lhs, rhs).map(|(l, r)| l == r).into_dyn())
}
(CoreTemplatePropertyKind::Email(lhs), CoreTemplatePropertyKind::Email(rhs)) => {
Some(Box::new((lhs, rhs).map(|(l, r)| l == r)))
Some((lhs, rhs).map(|(l, r)| l == r).into_dyn())
}
(CoreTemplatePropertyKind::Email(lhs), CoreTemplatePropertyKind::String(rhs)) => {
Some(Box::new((lhs, rhs).map(|(l, r)| l.0 == r)))
Some((lhs, rhs).map(|(l, r)| l.0 == r).into_dyn())
}
(CoreTemplatePropertyKind::String(_), _) => None,
(CoreTemplatePropertyKind::StringList(_), _) => None,
@ -343,7 +343,7 @@ impl<'a> IntoTemplateProperty<'a> for CoreTemplatePropertyKind<'a> {
) -> Option<Box<dyn TemplateProperty<Output = Ordering> + 'a>> {
match (self, other) {
(CoreTemplatePropertyKind::Integer(lhs), CoreTemplatePropertyKind::Integer(rhs)) => {
Some(Box::new((lhs, rhs).map(|(l, r)| l.cmp(&r))))
Some((lhs, rhs).map(|(l, r)| l.cmp(&r)).into_dyn())
}
(CoreTemplatePropertyKind::String(_), _) => None,
(CoreTemplatePropertyKind::StringList(_), _) => None,
@ -529,14 +529,8 @@ impl<'a, L: TemplateLanguage<'a> + ?Sized> CoreTemplateBuildFnTable<'a, L> {
let type_name = "Integer";
let table = &self.integer_methods;
let build = template_parser::lookup_method(type_name, table, function)?;
let inner_property = property.try_unwrap(type_name);
build(
language,
diagnostics,
build_ctx,
Box::new(inner_property),
function,
)
let inner_property = property.try_unwrap(type_name).into_dyn();
build(language, diagnostics, build_ctx, inner_property, function)
}
CoreTemplatePropertyKind::ConfigValue(property) => {
let table = &self.config_value_methods;
@ -1394,7 +1388,7 @@ where
})
.collect()
});
Ok(wrap_list(Box::new(out_property)))
Ok(wrap_list(out_property.into_dyn()))
}
/// Builds expression that extracts iterable property and applies template to
@ -1888,7 +1882,7 @@ pub fn expect_isize_expression<'a, L: TemplateLanguage<'a> + ?Sized>(
) -> TemplateParseResult<Box<dyn TemplateProperty<Output = isize> + 'a>> {
let i64_property = expect_integer_expression(language, diagnostics, build_ctx, node)?;
let isize_property = i64_property.and_then(|v| Ok(isize::try_from(v)?));
Ok(Box::new(isize_property))
Ok(isize_property.into_dyn())
}
/// If the given expression `node` is of `Integer` type, converts it to `usize`.
@ -1900,7 +1894,7 @@ pub fn expect_usize_expression<'a, L: TemplateLanguage<'a> + ?Sized>(
) -> TemplateParseResult<Box<dyn TemplateProperty<Output = usize> + 'a>> {
let i64_property = expect_integer_expression(language, diagnostics, build_ctx, node)?;
let usize_property = i64_property.and_then(|v| Ok(usize::try_from(v)?));
Ok(Box::new(usize_property))
Ok(usize_property.into_dyn())
}
pub fn expect_plain_text_expression<'a, L: TemplateLanguage<'a> + ?Sized>(

View File

@ -435,6 +435,14 @@ pub trait TemplatePropertyExt: TemplateProperty {
{
Box::new(FormattablePropertyTemplate::new(self))
}
/// Converts this property into boxed trait object.
fn into_dyn<'a>(self) -> Box<dyn TemplateProperty<Output = Self::Output> + 'a>
where
Self: Sized + 'a,
{
Box::new(self)
}
}
impl<P: TemplateProperty + ?Sized> TemplatePropertyExt for P {}