templater: add type_name() method to tagged property types

Suppose we add binary comparison operators, we'll probably need an easy way to
get (lhs, rhs) property types to produce a meaningful error message.
This commit is contained in:
Yuya Nishihara 2024-04-24 19:22:13 +09:00
parent 5b769c5c9e
commit 5394f342ce
4 changed files with 72 additions and 16 deletions

View File

@ -115,6 +115,7 @@ impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo> {
property: Self::Property,
function: &FunctionCallNode,
) -> TemplateParseResult<Self::Property> {
let type_name = property.type_name();
match property {
CommitTemplatePropertyKind::Core(property) => {
let table = &self.build_fn_table.core;
@ -122,12 +123,13 @@ impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo> {
}
CommitTemplatePropertyKind::Commit(property) => {
let table = &self.build_fn_table.commit_methods;
let build = template_parser::lookup_method("Commit", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
build(self, build_ctx, property, function)
}
CommitTemplatePropertyKind::CommitOpt(property) => {
let type_name = "Commit";
let table = &self.build_fn_table.commit_methods;
let build = template_parser::lookup_method("Commit", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
let inner_property = property.and_then(|opt| {
opt.ok_or_else(|| TemplatePropertyError("No commit available".into()))
});
@ -145,12 +147,13 @@ impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo> {
}
CommitTemplatePropertyKind::RefName(property) => {
let table = &self.build_fn_table.ref_name_methods;
let build = template_parser::lookup_method("RefName", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
build(self, build_ctx, property, function)
}
CommitTemplatePropertyKind::RefNameOpt(property) => {
let type_name = "RefName";
let table = &self.build_fn_table.ref_name_methods;
let build = template_parser::lookup_method("RefName", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
let inner_property = property.and_then(|opt| {
opt.ok_or_else(|| TemplatePropertyError("No RefName available".into()))
});
@ -168,12 +171,12 @@ impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo> {
}
CommitTemplatePropertyKind::CommitOrChangeId(property) => {
let table = &self.build_fn_table.commit_or_change_id_methods;
let build = template_parser::lookup_method("CommitOrChangeId", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
build(self, build_ctx, property, function)
}
CommitTemplatePropertyKind::ShortestIdPrefix(property) => {
let table = &self.build_fn_table.shortest_id_prefix_methods;
let build = template_parser::lookup_method("ShortestIdPrefix", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
build(self, build_ctx, property, function)
}
}
@ -261,6 +264,20 @@ pub enum CommitTemplatePropertyKind<'repo> {
}
impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
fn type_name(&self) -> &'static str {
match self {
CommitTemplatePropertyKind::Core(property) => property.type_name(),
CommitTemplatePropertyKind::Commit(_) => "Commit",
CommitTemplatePropertyKind::CommitOpt(_) => "Option<Commit>",
CommitTemplatePropertyKind::CommitList(_) => "List<Commit>",
CommitTemplatePropertyKind::RefName(_) => "RefName",
CommitTemplatePropertyKind::RefNameOpt(_) => "Option<RefName>",
CommitTemplatePropertyKind::RefNameList(_) => "List<RefName>",
CommitTemplatePropertyKind::CommitOrChangeId(_) => "CommitOrChangeId",
CommitTemplatePropertyKind::ShortestIdPrefix(_) => "ShortestIdPrefix",
}
}
fn try_into_boolean(self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'repo>> {
match self {
CommitTemplatePropertyKind::Core(property) => property.try_into_boolean(),

View File

@ -94,6 +94,7 @@ impl<'a, C: 'a> TemplateLanguage<'a> for GenericTemplateLanguage<'a, C> {
property: Self::Property,
function: &FunctionCallNode,
) -> TemplateParseResult<Self::Property> {
let type_name = property.type_name();
match property {
GenericTemplatePropertyKind::Core(property) => {
let table = &self.build_fn_table.core;
@ -101,7 +102,7 @@ impl<'a, C: 'a> TemplateLanguage<'a> for GenericTemplateLanguage<'a, C> {
}
GenericTemplatePropertyKind::Self_(property) => {
let table = &self.build_fn_table.keywords;
let build = template_parser::lookup_method("Self", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
// For simplicity, only 0-ary method is supported.
template_parser::expect_no_arguments(function)?;
build(property)
@ -124,6 +125,13 @@ pub enum GenericTemplatePropertyKind<'a, C> {
}
impl<'a, C: 'a> IntoTemplateProperty<'a> for GenericTemplatePropertyKind<'a, C> {
fn type_name(&self) -> &'static str {
match self {
GenericTemplatePropertyKind::Core(property) => property.type_name(),
GenericTemplatePropertyKind::Self_(_) => "Self",
}
}
fn try_into_boolean(self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'a>> {
match self {
GenericTemplatePropertyKind::Core(property) => property.try_into_boolean(),

View File

@ -92,6 +92,7 @@ impl TemplateLanguage<'static> for OperationTemplateLanguage {
property: Self::Property,
function: &FunctionCallNode,
) -> TemplateParseResult<Self::Property> {
let type_name = property.type_name();
match property {
OperationTemplatePropertyKind::Core(property) => {
let table = &self.build_fn_table.core;
@ -99,12 +100,12 @@ impl TemplateLanguage<'static> for OperationTemplateLanguage {
}
OperationTemplatePropertyKind::Operation(property) => {
let table = &self.build_fn_table.operation_methods;
let build = template_parser::lookup_method("Operation", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
build(self, build_ctx, property, function)
}
OperationTemplatePropertyKind::OperationId(property) => {
let table = &self.build_fn_table.operation_id_methods;
let build = template_parser::lookup_method("OperationId", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
build(self, build_ctx, property, function)
}
}
@ -136,6 +137,14 @@ pub enum OperationTemplatePropertyKind {
}
impl IntoTemplateProperty<'static> for OperationTemplatePropertyKind {
fn type_name(&self) -> &'static str {
match self {
OperationTemplatePropertyKind::Core(property) => property.type_name(),
OperationTemplatePropertyKind::Operation(_) => "Operation",
OperationTemplatePropertyKind::OperationId(_) => "OperationId",
}
}
fn try_into_boolean(self) -> Option<Box<dyn TemplateProperty<Output = bool>>> {
match self {
OperationTemplatePropertyKind::Core(property) => property.try_into_boolean(),

View File

@ -118,6 +118,9 @@ pub(crate) use {impl_core_wrap_property_fns, impl_wrap_property_fns};
/// Provides access to basic template property types.
pub trait IntoTemplateProperty<'a> {
/// Type name of the property output.
fn type_name(&self) -> &'static str;
fn try_into_boolean(self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'a>>;
fn try_into_integer(self) -> Option<Box<dyn TemplateProperty<Output = i64> + 'a>>;
@ -149,6 +152,20 @@ pub enum CoreTemplatePropertyKind<'a> {
}
impl<'a> IntoTemplateProperty<'a> for CoreTemplatePropertyKind<'a> {
fn type_name(&self) -> &'static str {
match self {
CoreTemplatePropertyKind::String(_) => "String",
CoreTemplatePropertyKind::StringList(_) => "List<String>",
CoreTemplatePropertyKind::Boolean(_) => "Boolean",
CoreTemplatePropertyKind::Integer(_) => "Integer",
CoreTemplatePropertyKind::Signature(_) => "Signature",
CoreTemplatePropertyKind::Timestamp(_) => "Timestamp",
CoreTemplatePropertyKind::TimestampRange(_) => "TimestampRange",
CoreTemplatePropertyKind::Template(_) => "Template",
CoreTemplatePropertyKind::ListTemplate(_) => "ListTemplate",
}
}
fn try_into_boolean(self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'a>> {
match self {
CoreTemplatePropertyKind::String(property) => {
@ -317,10 +334,11 @@ impl<'a, L: TemplateLanguage<'a> + ?Sized> CoreTemplateBuildFnTable<'a, L> {
property: CoreTemplatePropertyKind<'a>,
function: &FunctionCallNode,
) -> TemplateParseResult<L::Property> {
let type_name = property.type_name();
match property {
CoreTemplatePropertyKind::String(property) => {
let table = &self.string_methods;
let build = template_parser::lookup_method("String", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
build(language, build_ctx, property, function)
}
CoreTemplatePropertyKind::StringList(property) => {
@ -331,32 +349,32 @@ impl<'a, L: TemplateLanguage<'a> + ?Sized> CoreTemplateBuildFnTable<'a, L> {
}
CoreTemplatePropertyKind::Boolean(property) => {
let table = &self.boolean_methods;
let build = template_parser::lookup_method("Boolean", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
build(language, build_ctx, property, function)
}
CoreTemplatePropertyKind::Integer(property) => {
let table = &self.integer_methods;
let build = template_parser::lookup_method("Integer", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
build(language, build_ctx, property, function)
}
CoreTemplatePropertyKind::Signature(property) => {
let table = &self.signature_methods;
let build = template_parser::lookup_method("Signature", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
build(language, build_ctx, property, function)
}
CoreTemplatePropertyKind::Timestamp(property) => {
let table = &self.timestamp_methods;
let build = template_parser::lookup_method("Timestamp", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
build(language, build_ctx, property, function)
}
CoreTemplatePropertyKind::TimestampRange(property) => {
let table = &self.timestamp_range_methods;
let build = template_parser::lookup_method("TimestampRange", table, function)?;
let build = template_parser::lookup_method(type_name, table, function)?;
build(language, build_ctx, property, function)
}
CoreTemplatePropertyKind::Template(_) => {
// TODO: migrate to table?
Err(TemplateParseError::no_such_method("Template", function))
Err(TemplateParseError::no_such_method(type_name, function))
}
CoreTemplatePropertyKind::ListTemplate(template) => {
// TODO: migrate to table?
@ -385,6 +403,10 @@ impl<P> Expression<P> {
}
impl<'a, P: IntoTemplateProperty<'a>> Expression<P> {
pub fn type_name(&self) -> &'static str {
self.property.type_name()
}
pub fn try_into_boolean(self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'a>> {
self.property.try_into_boolean()
}