forked from mirrors/jj
templater: implement expect_*_arguments() as methods
I'm thinking of moving them to dsl_util, but we'll probably want to avoid importing dsl_util at call sites.
This commit is contained in:
parent
06f488a8f6
commit
04efac3a51
7 changed files with 139 additions and 142 deletions
|
@ -117,7 +117,7 @@ impl CommitTemplateLanguageExtension for HexCounter {
|
|||
table.commit_methods.insert(
|
||||
"has_most_digits",
|
||||
|language, _build_context, property, call| {
|
||||
template_parser::expect_no_arguments(call)?;
|
||||
call.expect_no_arguments()?;
|
||||
let most_digits = language
|
||||
.cache_extension::<MostDigitsInId>()
|
||||
.unwrap()
|
||||
|
@ -130,7 +130,7 @@ impl CommitTemplateLanguageExtension for HexCounter {
|
|||
table.commit_methods.insert(
|
||||
"num_digits_in_id",
|
||||
|_language, _build_context, property, call| {
|
||||
template_parser::expect_no_arguments(call)?;
|
||||
call.expect_no_arguments()?;
|
||||
Ok(L::wrap_integer(
|
||||
property.map(|commit| num_digits_in_id(commit.id())),
|
||||
))
|
||||
|
@ -139,7 +139,7 @@ impl CommitTemplateLanguageExtension for HexCounter {
|
|||
table.commit_methods.insert(
|
||||
"num_char_in_id",
|
||||
|_language, _build_context, property, call| {
|
||||
let [string_arg] = template_parser::expect_exact_arguments(call)?;
|
||||
let [string_arg] = call.expect_exact_arguments()?;
|
||||
let char_arg =
|
||||
template_parser::expect_string_literal_with(string_arg, |string, span| {
|
||||
let chars: Vec<_> = string.chars().collect();
|
||||
|
|
|
@ -53,7 +53,7 @@ impl OperationTemplateLanguageExtension for HexCounter {
|
|||
table.operation_methods.insert(
|
||||
"num_digits_in_id",
|
||||
|_language, _build_context, property, call| {
|
||||
template_parser::expect_no_arguments(call)?;
|
||||
call.expect_no_arguments()?;
|
||||
Ok(L::wrap_integer(
|
||||
property.map(|operation| num_digits_in_id(operation.id())),
|
||||
))
|
||||
|
@ -62,7 +62,7 @@ impl OperationTemplateLanguageExtension for HexCounter {
|
|||
table.operation_methods.insert(
|
||||
"num_char_in_id",
|
||||
|_language, _build_context, property, call| {
|
||||
let [string_arg] = template_parser::expect_exact_arguments(call)?;
|
||||
let [string_arg] = call.expect_exact_arguments()?;
|
||||
let char_arg =
|
||||
template_parser::expect_string_literal_with(string_arg, |string, span| {
|
||||
let chars: Vec<_> = string.chars().collect();
|
||||
|
|
|
@ -435,7 +435,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"description",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property =
|
||||
self_property.map(|commit| text_util::complete_newline(commit.description()));
|
||||
Ok(L::wrap_string(out_property))
|
||||
|
@ -444,7 +444,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"change_id",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property =
|
||||
self_property.map(|commit| CommitOrChangeId::Change(commit.change_id().to_owned()));
|
||||
Ok(L::wrap_commit_or_change_id(out_property))
|
||||
|
@ -453,7 +453,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"commit_id",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property =
|
||||
self_property.map(|commit| CommitOrChangeId::Commit(commit.id().to_owned()));
|
||||
Ok(L::wrap_commit_or_change_id(out_property))
|
||||
|
@ -462,7 +462,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"parents",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property =
|
||||
self_property.and_then(|commit| Ok(commit.parents().try_collect()?));
|
||||
Ok(L::wrap_commit_list(out_property))
|
||||
|
@ -471,7 +471,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"author",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|commit| commit.author().clone());
|
||||
Ok(L::wrap_signature(out_property))
|
||||
},
|
||||
|
@ -479,13 +479,13 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"committer",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|commit| commit.committer().clone());
|
||||
Ok(L::wrap_signature(out_property))
|
||||
},
|
||||
);
|
||||
map.insert("mine", |language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let user_email = language.revset_parse_context.user_email().to_owned();
|
||||
let out_property = self_property.map(move |commit| commit.author().email == user_email);
|
||||
Ok(L::wrap_boolean(out_property))
|
||||
|
@ -493,7 +493,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"working_copies",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let repo = language.repo;
|
||||
let out_property = self_property.map(|commit| extract_working_copies(repo, &commit));
|
||||
Ok(L::wrap_string(out_property))
|
||||
|
@ -502,7 +502,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"current_working_copy",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let repo = language.repo;
|
||||
let workspace_id = language.workspace_id.clone();
|
||||
let out_property = self_property.map(move |commit| {
|
||||
|
@ -514,7 +514,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"branches",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let index = language.keyword_cache.branches_index(language.repo).clone();
|
||||
let out_property = self_property.map(move |commit| {
|
||||
index
|
||||
|
@ -530,7 +530,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"local_branches",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let index = language.keyword_cache.branches_index(language.repo).clone();
|
||||
let out_property = self_property.map(move |commit| {
|
||||
index
|
||||
|
@ -546,7 +546,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"remote_branches",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let index = language.keyword_cache.branches_index(language.repo).clone();
|
||||
let out_property = self_property.map(move |commit| {
|
||||
index
|
||||
|
@ -560,7 +560,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
},
|
||||
);
|
||||
map.insert("tags", |language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let index = language.keyword_cache.tags_index(language.repo).clone();
|
||||
let out_property = self_property.map(move |commit| index.get(commit.id()).to_vec());
|
||||
Ok(L::wrap_ref_name_list(out_property))
|
||||
|
@ -568,7 +568,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"git_refs",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let index = language.keyword_cache.git_refs_index(language.repo).clone();
|
||||
let out_property = self_property.map(move |commit| index.get(commit.id()).to_vec());
|
||||
Ok(L::wrap_ref_name_list(out_property))
|
||||
|
@ -577,7 +577,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"git_head",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let repo = language.repo;
|
||||
let out_property = self_property.map(|commit| extract_git_head(repo, &commit));
|
||||
Ok(L::wrap_ref_name_opt(out_property))
|
||||
|
@ -586,7 +586,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"divergent",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let repo = language.repo;
|
||||
let out_property = self_property.map(|commit| {
|
||||
// The given commit could be hidden in e.g. obslog.
|
||||
|
@ -597,7 +597,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
},
|
||||
);
|
||||
map.insert("hidden", |language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let repo = language.repo;
|
||||
let out_property = self_property.map(|commit| {
|
||||
let maybe_entries = repo.resolve_change_id(commit.change_id());
|
||||
|
@ -608,7 +608,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"immutable",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let is_immutable = language
|
||||
.keyword_cache
|
||||
.is_immutable_fn(language, function.name_span)?
|
||||
|
@ -620,7 +620,7 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"contained_in",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
let [revset_node] = template_parser::expect_exact_arguments(function)?;
|
||||
let [revset_node] = function.expect_exact_arguments()?;
|
||||
|
||||
let is_contained =
|
||||
template_parser::expect_string_literal_with(revset_node, |revset, span| {
|
||||
|
@ -634,19 +634,19 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
map.insert(
|
||||
"conflict",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.and_then(|commit| Ok(commit.has_conflict()?));
|
||||
Ok(L::wrap_boolean(out_property))
|
||||
},
|
||||
);
|
||||
map.insert("empty", |language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let repo = language.repo;
|
||||
let out_property = self_property.and_then(|commit| Ok(commit.is_empty(repo)?));
|
||||
Ok(L::wrap_boolean(out_property))
|
||||
});
|
||||
map.insert("root", |language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let repo = language.repo;
|
||||
let out_property = self_property.map(|commit| commit.id() == repo.store().root_commit_id());
|
||||
Ok(L::wrap_boolean(out_property))
|
||||
|
@ -909,14 +909,14 @@ fn builtin_ref_name_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Rc
|
|||
// code completion inside macro is quite restricted.
|
||||
let mut map = CommitTemplateBuildMethodFnMap::<Rc<RefName>>::new();
|
||||
map.insert("name", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|ref_name| ref_name.name.clone());
|
||||
Ok(L::wrap_string(out_property))
|
||||
});
|
||||
map.insert(
|
||||
"remote",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property =
|
||||
self_property.map(|ref_name| ref_name.remote.clone().unwrap_or_default());
|
||||
Ok(L::wrap_string(out_property))
|
||||
|
@ -925,7 +925,7 @@ fn builtin_ref_name_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Rc
|
|||
map.insert(
|
||||
"present",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|ref_name| ref_name.is_present());
|
||||
Ok(L::wrap_boolean(out_property))
|
||||
},
|
||||
|
@ -933,7 +933,7 @@ fn builtin_ref_name_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Rc
|
|||
map.insert(
|
||||
"conflict",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|ref_name| ref_name.has_conflict());
|
||||
Ok(L::wrap_boolean(out_property))
|
||||
},
|
||||
|
@ -941,7 +941,7 @@ fn builtin_ref_name_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Rc
|
|||
map.insert(
|
||||
"normal_target",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let repo = language.repo;
|
||||
let out_property = self_property.and_then(|ref_name| {
|
||||
let maybe_id = ref_name.target.as_normal();
|
||||
|
@ -953,7 +953,7 @@ fn builtin_ref_name_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Rc
|
|||
map.insert(
|
||||
"removed_targets",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let repo = language.repo;
|
||||
let out_property = self_property.and_then(|ref_name| {
|
||||
let ids = ref_name.target.removed_ids();
|
||||
|
@ -965,7 +965,7 @@ fn builtin_ref_name_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Rc
|
|||
map.insert(
|
||||
"added_targets",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let repo = language.repo;
|
||||
let out_property = self_property.and_then(|ref_name| {
|
||||
let ids = ref_name.target.added_ids();
|
||||
|
@ -977,7 +977,7 @@ fn builtin_ref_name_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Rc
|
|||
map.insert(
|
||||
"tracked",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|ref_name| ref_name.is_tracked());
|
||||
Ok(L::wrap_boolean(out_property))
|
||||
},
|
||||
|
@ -985,7 +985,7 @@ fn builtin_ref_name_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Rc
|
|||
map.insert(
|
||||
"tracking_present",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|ref_name| ref_name.is_tracking_present());
|
||||
Ok(L::wrap_boolean(out_property))
|
||||
},
|
||||
|
@ -993,7 +993,7 @@ fn builtin_ref_name_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Rc
|
|||
map.insert(
|
||||
"tracking_ahead_count",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let repo = language.repo;
|
||||
let out_property =
|
||||
self_property.and_then(|ref_name| ref_name.tracking_ahead_count(repo));
|
||||
|
@ -1003,7 +1003,7 @@ fn builtin_ref_name_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Rc
|
|||
map.insert(
|
||||
"tracking_behind_count",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let repo = language.repo;
|
||||
let out_property =
|
||||
self_property.and_then(|ref_name| ref_name.tracking_behind_count(repo));
|
||||
|
@ -1135,7 +1135,7 @@ fn builtin_commit_or_change_id_methods<'repo>(
|
|||
// code completion inside macro is quite restricted.
|
||||
let mut map = CommitTemplateBuildMethodFnMap::<CommitOrChangeId>::new();
|
||||
map.insert("short", |language, build_ctx, self_property, function| {
|
||||
let ([], [len_node]) = template_parser::expect_arguments(function)?;
|
||||
let ([], [len_node]) = function.expect_arguments()?;
|
||||
let len_property = len_node
|
||||
.map(|node| template_builder::expect_usize_expression(language, build_ctx, node))
|
||||
.transpose()?;
|
||||
|
@ -1147,7 +1147,7 @@ fn builtin_commit_or_change_id_methods<'repo>(
|
|||
"shortest",
|
||||
|language, build_ctx, self_property, function| {
|
||||
let id_prefix_context = &language.id_prefix_context;
|
||||
let ([], [len_node]) = template_parser::expect_arguments(function)?;
|
||||
let ([], [len_node]) = function.expect_arguments()?;
|
||||
let len_property = len_node
|
||||
.map(|node| template_builder::expect_usize_expression(language, build_ctx, node))
|
||||
.transpose()?;
|
||||
|
@ -1196,23 +1196,23 @@ fn builtin_shortest_id_prefix_methods<'repo>(
|
|||
map.insert(
|
||||
"prefix",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|id| id.prefix);
|
||||
Ok(L::wrap_string(out_property))
|
||||
},
|
||||
);
|
||||
map.insert("rest", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|id| id.rest);
|
||||
Ok(L::wrap_string(out_property))
|
||||
});
|
||||
map.insert("upper", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|id| id.to_upper());
|
||||
Ok(L::wrap_shortest_id_prefix(out_property))
|
||||
});
|
||||
map.insert("lower", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|id| id.to_lower());
|
||||
Ok(L::wrap_shortest_id_prefix(out_property))
|
||||
});
|
||||
|
|
|
@ -104,7 +104,7 @@ impl<'a, C: 'a> TemplateLanguage<'a> for GenericTemplateLanguage<'a, C> {
|
|||
let table = &self.build_fn_table.keywords;
|
||||
let build = template_parser::lookup_method(type_name, table, function)?;
|
||||
// For simplicity, only 0-ary method is supported.
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
build(property)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ fn builtin_operation_methods() -> OperationTemplateBuildMethodFnMap<Operation> {
|
|||
map.insert(
|
||||
"current_operation",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let current_op_id = language.current_op_id.clone();
|
||||
let out_property = self_property.map(move |op| Some(op.id()) == current_op_id.as_ref());
|
||||
Ok(L::wrap_boolean(out_property))
|
||||
|
@ -238,18 +238,18 @@ fn builtin_operation_methods() -> OperationTemplateBuildMethodFnMap<Operation> {
|
|||
map.insert(
|
||||
"description",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|op| op.metadata().description.clone());
|
||||
Ok(L::wrap_string(out_property))
|
||||
},
|
||||
);
|
||||
map.insert("id", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|op| op.id().clone());
|
||||
Ok(L::wrap_operation_id(out_property))
|
||||
});
|
||||
map.insert("tags", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|op| {
|
||||
// TODO: introduce map type
|
||||
op.metadata()
|
||||
|
@ -263,13 +263,13 @@ fn builtin_operation_methods() -> OperationTemplateBuildMethodFnMap<Operation> {
|
|||
map.insert(
|
||||
"snapshot",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|op| op.metadata().is_snapshot);
|
||||
Ok(L::wrap_boolean(out_property))
|
||||
},
|
||||
);
|
||||
map.insert("time", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|op| TimestampRange {
|
||||
start: op.metadata().start_time.clone(),
|
||||
end: op.metadata().end_time.clone(),
|
||||
|
@ -277,7 +277,7 @@ fn builtin_operation_methods() -> OperationTemplateBuildMethodFnMap<Operation> {
|
|||
Ok(L::wrap_timestamp_range(out_property))
|
||||
});
|
||||
map.insert("user", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|op| {
|
||||
// TODO: introduce dedicated type and provide accessors?
|
||||
format!("{}@{}", op.metadata().username, op.metadata().hostname)
|
||||
|
@ -285,7 +285,7 @@ fn builtin_operation_methods() -> OperationTemplateBuildMethodFnMap<Operation> {
|
|||
Ok(L::wrap_string(out_property))
|
||||
});
|
||||
map.insert("root", |language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let root_op_id = language.root_op_id.clone();
|
||||
let out_property = self_property.map(move |op| op.id() == &root_op_id);
|
||||
Ok(L::wrap_boolean(out_property))
|
||||
|
@ -305,7 +305,7 @@ fn builtin_operation_id_methods() -> OperationTemplateBuildMethodFnMap<Operation
|
|||
// code completion inside macro is quite restricted.
|
||||
let mut map = OperationTemplateBuildMethodFnMap::<OperationId>::new();
|
||||
map.insert("short", |language, build_ctx, self_property, function| {
|
||||
let ([], [len_node]) = template_parser::expect_arguments(function)?;
|
||||
let ([], [len_node]) = function.expect_arguments()?;
|
||||
let len_property = len_node
|
||||
.map(|node| template_builder::expect_usize_expression(language, build_ctx, node))
|
||||
.transpose()?;
|
||||
|
|
|
@ -565,14 +565,14 @@ fn builtin_string_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
// code completion inside macro is quite restricted.
|
||||
let mut map = TemplateBuildMethodFnMap::<L, String>::new();
|
||||
map.insert("len", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.and_then(|s| Ok(s.len().try_into()?));
|
||||
Ok(L::wrap_integer(out_property))
|
||||
});
|
||||
map.insert(
|
||||
"contains",
|
||||
|language, build_ctx, self_property, function| {
|
||||
let [needle_node] = template_parser::expect_exact_arguments(function)?;
|
||||
let [needle_node] = function.expect_exact_arguments()?;
|
||||
// TODO: or .try_into_string() to disable implicit type cast?
|
||||
let needle_property = expect_plain_text_expression(language, build_ctx, needle_node)?;
|
||||
let out_property = (self_property, needle_property)
|
||||
|
@ -583,7 +583,7 @@ fn builtin_string_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
map.insert(
|
||||
"starts_with",
|
||||
|language, build_ctx, self_property, function| {
|
||||
let [needle_node] = template_parser::expect_exact_arguments(function)?;
|
||||
let [needle_node] = function.expect_exact_arguments()?;
|
||||
let needle_property = expect_plain_text_expression(language, build_ctx, needle_node)?;
|
||||
let out_property = (self_property, needle_property)
|
||||
.map(|(haystack, needle)| haystack.starts_with(&needle));
|
||||
|
@ -593,7 +593,7 @@ fn builtin_string_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
map.insert(
|
||||
"ends_with",
|
||||
|language, build_ctx, self_property, function| {
|
||||
let [needle_node] = template_parser::expect_exact_arguments(function)?;
|
||||
let [needle_node] = function.expect_exact_arguments()?;
|
||||
let needle_property = expect_plain_text_expression(language, build_ctx, needle_node)?;
|
||||
let out_property = (self_property, needle_property)
|
||||
.map(|(haystack, needle)| haystack.ends_with(&needle));
|
||||
|
@ -603,7 +603,7 @@ fn builtin_string_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
map.insert(
|
||||
"remove_prefix",
|
||||
|language, build_ctx, self_property, function| {
|
||||
let [needle_node] = template_parser::expect_exact_arguments(function)?;
|
||||
let [needle_node] = function.expect_exact_arguments()?;
|
||||
let needle_property = expect_plain_text_expression(language, build_ctx, needle_node)?;
|
||||
let out_property = (self_property, needle_property).map(|(haystack, needle)| {
|
||||
haystack
|
||||
|
@ -617,7 +617,7 @@ fn builtin_string_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
map.insert(
|
||||
"remove_suffix",
|
||||
|language, build_ctx, self_property, function| {
|
||||
let [needle_node] = template_parser::expect_exact_arguments(function)?;
|
||||
let [needle_node] = function.expect_exact_arguments()?;
|
||||
let needle_property = expect_plain_text_expression(language, build_ctx, needle_node)?;
|
||||
let out_property = (self_property, needle_property).map(|(haystack, needle)| {
|
||||
haystack
|
||||
|
@ -629,7 +629,7 @@ fn builtin_string_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
},
|
||||
);
|
||||
map.insert("substr", |language, build_ctx, self_property, function| {
|
||||
let [start_idx, end_idx] = template_parser::expect_exact_arguments(function)?;
|
||||
let [start_idx, end_idx] = function.expect_exact_arguments()?;
|
||||
let start_idx_property = expect_isize_expression(language, build_ctx, start_idx)?;
|
||||
let end_idx_property = expect_isize_expression(language, build_ctx, end_idx)?;
|
||||
let out_property =
|
||||
|
@ -643,24 +643,24 @@ fn builtin_string_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
map.insert(
|
||||
"first_line",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property =
|
||||
self_property.map(|s| s.lines().next().unwrap_or_default().to_string());
|
||||
Ok(L::wrap_string(out_property))
|
||||
},
|
||||
);
|
||||
map.insert("lines", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|s| s.lines().map(|l| l.to_owned()).collect());
|
||||
Ok(L::wrap_string_list(out_property))
|
||||
});
|
||||
map.insert("upper", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|s| s.to_uppercase());
|
||||
Ok(L::wrap_string(out_property))
|
||||
});
|
||||
map.insert("lower", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|s| s.to_lowercase());
|
||||
Ok(L::wrap_string(out_property))
|
||||
});
|
||||
|
@ -689,19 +689,19 @@ fn builtin_signature_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
// code completion inside macro is quite restricted.
|
||||
let mut map = TemplateBuildMethodFnMap::<L, Signature>::new();
|
||||
map.insert("name", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|signature| signature.name);
|
||||
Ok(L::wrap_string(out_property))
|
||||
});
|
||||
map.insert("email", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|signature| signature.email);
|
||||
Ok(L::wrap_string(out_property))
|
||||
});
|
||||
map.insert(
|
||||
"username",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|signature| {
|
||||
let (username, _) = text_util::split_email(&signature.email);
|
||||
username.to_owned()
|
||||
|
@ -712,7 +712,7 @@ fn builtin_signature_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
map.insert(
|
||||
"timestamp",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|signature| signature.timestamp);
|
||||
Ok(L::wrap_timestamp(out_property))
|
||||
},
|
||||
|
@ -726,18 +726,18 @@ fn builtin_size_hint_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
// code completion inside macro is quite restricted.
|
||||
let mut map = TemplateBuildMethodFnMap::<L, SizeHint>::new();
|
||||
map.insert("lower", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.and_then(|(lower, _)| Ok(i64::try_from(lower)?));
|
||||
Ok(L::wrap_integer(out_property))
|
||||
});
|
||||
map.insert("upper", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property =
|
||||
self_property.and_then(|(_, upper)| Ok(upper.map(i64::try_from).transpose()?));
|
||||
Ok(L::wrap_integer_opt(out_property))
|
||||
});
|
||||
map.insert("exact", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.and_then(|(lower, upper)| {
|
||||
let exact = (Some(lower) == upper).then_some(lower);
|
||||
Ok(exact.map(i64::try_from).transpose()?)
|
||||
|
@ -745,7 +745,7 @@ fn builtin_size_hint_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
Ok(L::wrap_integer_opt(out_property))
|
||||
});
|
||||
map.insert("zero", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|(_, upper)| upper == Some(0));
|
||||
Ok(L::wrap_boolean(out_property))
|
||||
});
|
||||
|
@ -758,7 +758,7 @@ fn builtin_timestamp_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
// code completion inside macro is quite restricted.
|
||||
let mut map = TemplateBuildMethodFnMap::<L, Timestamp>::new();
|
||||
map.insert("ago", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let now = Timestamp::now();
|
||||
let format = timeago::Formatter::new();
|
||||
let out_property = self_property
|
||||
|
@ -769,7 +769,7 @@ fn builtin_timestamp_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
"format",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
// No dynamic string is allowed as the templater has no runtime error type.
|
||||
let [format_node] = template_parser::expect_exact_arguments(function)?;
|
||||
let [format_node] = function.expect_exact_arguments()?;
|
||||
let format =
|
||||
template_parser::expect_string_literal_with(format_node, |format, span| {
|
||||
time_util::FormattingItems::parse(format)
|
||||
|
@ -785,7 +785,7 @@ fn builtin_timestamp_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
},
|
||||
);
|
||||
map.insert("utc", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|mut timestamp| {
|
||||
timestamp.tz_offset = 0;
|
||||
timestamp
|
||||
|
@ -793,7 +793,7 @@ fn builtin_timestamp_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
Ok(L::wrap_timestamp(out_property))
|
||||
});
|
||||
map.insert("local", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let tz_offset = std::env::var("JJ_TZ_OFFSET_MINS")
|
||||
.ok()
|
||||
.and_then(|tz_string| tz_string.parse::<i32>().ok())
|
||||
|
@ -813,19 +813,19 @@ fn builtin_timestamp_range_methods<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
// code completion inside macro is quite restricted.
|
||||
let mut map = TemplateBuildMethodFnMap::<L, TimestampRange>::new();
|
||||
map.insert("start", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|time_range| time_range.start);
|
||||
Ok(L::wrap_timestamp(out_property))
|
||||
});
|
||||
map.insert("end", |_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|time_range| time_range.end);
|
||||
Ok(L::wrap_timestamp(out_property))
|
||||
});
|
||||
map.insert(
|
||||
"duration",
|
||||
|_language, _build_ctx, self_property, function| {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.and_then(|time_range| Ok(time_range.duration()?));
|
||||
Ok(L::wrap_string(out_property))
|
||||
},
|
||||
|
@ -841,7 +841,7 @@ fn build_list_template_method<'a, L: TemplateLanguage<'a> + ?Sized>(
|
|||
) -> TemplateParseResult<L::Property> {
|
||||
let property = match function.name {
|
||||
"join" => {
|
||||
let [separator_node] = template_parser::expect_exact_arguments(function)?;
|
||||
let [separator_node] = function.expect_exact_arguments()?;
|
||||
let separator = expect_template_expression(language, build_ctx, separator_node)?;
|
||||
L::wrap_template(self_template.join(separator))
|
||||
}
|
||||
|
@ -866,12 +866,12 @@ where
|
|||
{
|
||||
let property = match function.name {
|
||||
"len" => {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.and_then(|items| Ok(items.len().try_into()?));
|
||||
L::wrap_integer(out_property)
|
||||
}
|
||||
"join" => {
|
||||
let [separator_node] = template_parser::expect_exact_arguments(function)?;
|
||||
let [separator_node] = function.expect_exact_arguments()?;
|
||||
let separator = expect_template_expression(language, build_ctx, separator_node)?;
|
||||
let template =
|
||||
ListPropertyTemplate::new(self_property, separator, |formatter, item| {
|
||||
|
@ -898,7 +898,7 @@ where
|
|||
{
|
||||
let property = match function.name {
|
||||
"len" => {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.and_then(|items| Ok(items.len().try_into()?));
|
||||
L::wrap_integer(out_property)
|
||||
}
|
||||
|
@ -928,7 +928,7 @@ where
|
|||
{
|
||||
// Build an item template with placeholder property, then evaluate it
|
||||
// for each item.
|
||||
let [lambda_node] = template_parser::expect_exact_arguments(function)?;
|
||||
let [lambda_node] = function.expect_exact_arguments()?;
|
||||
let item_placeholder = PropertyPlaceholder::new();
|
||||
let item_template = template_parser::expect_lambda_with(lambda_node, |lambda, _span| {
|
||||
let item_fn = || wrap_item(item_placeholder.clone());
|
||||
|
@ -962,7 +962,7 @@ fn builtin_functions<'a, L: TemplateLanguage<'a> + ?Sized>() -> TemplateBuildFun
|
|||
// code completion inside macro is quite restricted.
|
||||
let mut map = TemplateBuildFunctionFnMap::<L>::new();
|
||||
map.insert("fill", |language, build_ctx, function| {
|
||||
let [width_node, content_node] = template_parser::expect_exact_arguments(function)?;
|
||||
let [width_node, content_node] = function.expect_exact_arguments()?;
|
||||
let width = expect_usize_expression(language, build_ctx, width_node)?;
|
||||
let content = expect_template_expression(language, build_ctx, content_node)?;
|
||||
let template =
|
||||
|
@ -973,7 +973,7 @@ fn builtin_functions<'a, L: TemplateLanguage<'a> + ?Sized>() -> TemplateBuildFun
|
|||
Ok(L::wrap_template(Box::new(template)))
|
||||
});
|
||||
map.insert("indent", |language, build_ctx, function| {
|
||||
let [prefix_node, content_node] = template_parser::expect_exact_arguments(function)?;
|
||||
let [prefix_node, content_node] = function.expect_exact_arguments()?;
|
||||
let prefix = expect_template_expression(language, build_ctx, prefix_node)?;
|
||||
let content = expect_template_expression(language, build_ctx, content_node)?;
|
||||
let template = ReformatTemplate::new(content, move |formatter, recorded| {
|
||||
|
@ -985,7 +985,7 @@ fn builtin_functions<'a, L: TemplateLanguage<'a> + ?Sized>() -> TemplateBuildFun
|
|||
Ok(L::wrap_template(Box::new(template)))
|
||||
});
|
||||
map.insert("label", |language, build_ctx, function| {
|
||||
let [label_node, content_node] = template_parser::expect_exact_arguments(function)?;
|
||||
let [label_node, content_node] = function.expect_exact_arguments()?;
|
||||
let label_property = expect_plain_text_expression(language, build_ctx, label_node)?;
|
||||
let content = expect_template_expression(language, build_ctx, content_node)?;
|
||||
let labels =
|
||||
|
@ -995,8 +995,7 @@ fn builtin_functions<'a, L: TemplateLanguage<'a> + ?Sized>() -> TemplateBuildFun
|
|||
))))
|
||||
});
|
||||
map.insert("if", |language, build_ctx, function| {
|
||||
let ([condition_node, true_node], [false_node]) =
|
||||
template_parser::expect_arguments(function)?;
|
||||
let ([condition_node, true_node], [false_node]) = function.expect_arguments()?;
|
||||
let condition = expect_boolean_expression(language, build_ctx, condition_node)?;
|
||||
let true_template = expect_template_expression(language, build_ctx, true_node)?;
|
||||
let false_template = false_node
|
||||
|
@ -1022,7 +1021,7 @@ fn builtin_functions<'a, L: TemplateLanguage<'a> + ?Sized>() -> TemplateBuildFun
|
|||
Ok(L::wrap_template(Box::new(ConcatTemplate(contents))))
|
||||
});
|
||||
map.insert("separate", |language, build_ctx, function| {
|
||||
let ([separator_node], content_nodes) = template_parser::expect_some_arguments(function)?;
|
||||
let ([separator_node], content_nodes) = function.expect_some_arguments()?;
|
||||
let separator = expect_template_expression(language, build_ctx, separator_node)?;
|
||||
let contents = content_nodes
|
||||
.iter()
|
||||
|
@ -1033,8 +1032,7 @@ fn builtin_functions<'a, L: TemplateLanguage<'a> + ?Sized>() -> TemplateBuildFun
|
|||
))))
|
||||
});
|
||||
map.insert("surround", |language, build_ctx, function| {
|
||||
let [prefix_node, suffix_node, content_node] =
|
||||
template_parser::expect_exact_arguments(function)?;
|
||||
let [prefix_node, suffix_node, content_node] = function.expect_exact_arguments()?;
|
||||
let prefix = expect_template_expression(language, build_ctx, prefix_node)?;
|
||||
let suffix = expect_template_expression(language, build_ctx, suffix_node)?;
|
||||
let content = expect_template_expression(language, build_ctx, content_node)?;
|
||||
|
|
|
@ -681,59 +681,58 @@ pub fn parse<'i>(
|
|||
expand_aliases(node, aliases_map)
|
||||
}
|
||||
|
||||
pub fn expect_no_arguments(function: &FunctionCallNode) -> TemplateParseResult<()> {
|
||||
if function.args.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(TemplateParseError::invalid_arguments(
|
||||
function,
|
||||
"Expected 0 arguments",
|
||||
))
|
||||
impl<'i> FunctionCallNode<'i> {
|
||||
pub fn expect_no_arguments(&self) -> TemplateParseResult<()> {
|
||||
if self.args.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(TemplateParseError::invalid_arguments(
|
||||
self,
|
||||
"Expected 0 arguments",
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts exactly N required arguments.
|
||||
pub fn expect_exact_arguments<'a, 'i, const N: usize>(
|
||||
function: &'a FunctionCallNode<'i>,
|
||||
) -> TemplateParseResult<&'a [ExpressionNode<'i>; N]> {
|
||||
function.args.as_slice().try_into().map_err(|_| {
|
||||
TemplateParseError::invalid_arguments(function, format!("Expected {N} arguments"))
|
||||
})
|
||||
}
|
||||
|
||||
/// Extracts N required arguments and remainders.
|
||||
pub fn expect_some_arguments<'a, 'i, const N: usize>(
|
||||
function: &'a FunctionCallNode<'i>,
|
||||
) -> TemplateParseResult<(&'a [ExpressionNode<'i>; N], &'a [ExpressionNode<'i>])> {
|
||||
if function.args.len() >= N {
|
||||
let (required, rest) = function.args.split_at(N);
|
||||
Ok((required.try_into().unwrap(), rest))
|
||||
} else {
|
||||
Err(TemplateParseError::invalid_arguments(
|
||||
function,
|
||||
format!("Expected at least {N} arguments"),
|
||||
))
|
||||
/// Extracts exactly N required arguments.
|
||||
pub fn expect_exact_arguments<const N: usize>(
|
||||
&self,
|
||||
) -> TemplateParseResult<&[ExpressionNode<'i>; N]> {
|
||||
self.args.as_slice().try_into().map_err(|_| {
|
||||
TemplateParseError::invalid_arguments(self, format!("Expected {N} arguments"))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts N required arguments and M optional arguments.
|
||||
pub fn expect_arguments<'a, 'i, const N: usize, const M: usize>(
|
||||
function: &'a FunctionCallNode<'i>,
|
||||
) -> TemplateParseResult<(
|
||||
&'a [ExpressionNode<'i>; N],
|
||||
[Option<&'a ExpressionNode<'i>>; M],
|
||||
)> {
|
||||
let count_range = N..=(N + M);
|
||||
if count_range.contains(&function.args.len()) {
|
||||
let (required, rest) = function.args.split_at(N);
|
||||
let mut optional = rest.iter().map(Some).collect_vec();
|
||||
optional.resize(M, None);
|
||||
Ok((required.try_into().unwrap(), optional.try_into().unwrap()))
|
||||
} else {
|
||||
Err(TemplateParseError::invalid_arguments(
|
||||
function,
|
||||
format!("Expected {min} to {max} arguments", min = N, max = N + M),
|
||||
))
|
||||
/// Extracts N required arguments and remainders.
|
||||
pub fn expect_some_arguments<const N: usize>(
|
||||
&self,
|
||||
) -> TemplateParseResult<(&[ExpressionNode<'i>; N], &[ExpressionNode<'i>])> {
|
||||
if self.args.len() >= N {
|
||||
let (required, rest) = self.args.split_at(N);
|
||||
Ok((required.try_into().unwrap(), rest))
|
||||
} else {
|
||||
Err(TemplateParseError::invalid_arguments(
|
||||
self,
|
||||
format!("Expected at least {N} arguments"),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts N required arguments and M optional arguments.
|
||||
pub fn expect_arguments<const N: usize, const M: usize>(
|
||||
&self,
|
||||
) -> TemplateParseResult<(&[ExpressionNode<'i>; N], [Option<&ExpressionNode<'i>>; M])> {
|
||||
let count_range = N..=(N + M);
|
||||
if count_range.contains(&self.args.len()) {
|
||||
let (required, rest) = self.args.split_at(N);
|
||||
let mut optional = rest.iter().map(Some).collect_vec();
|
||||
optional.resize(M, None);
|
||||
Ok((required.try_into().unwrap(), optional.try_into().unwrap()))
|
||||
} else {
|
||||
Err(TemplateParseError::invalid_arguments(
|
||||
self,
|
||||
format!("Expected {min} to {max} arguments", min = N, max = N + M),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue