From 1d4b5fd8a76205cb0f52507ad446f7a5c0c5e2b3 Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Tue, 1 Nov 2022 20:18:01 +0900 Subject: [PATCH] revset: add helper functions that extracts function arguments These functions doesn't return inner Pairs but Pair so that the Span of the matching tokens can be easily obtained. --- lib/src/revset.rs | 254 ++++++++++++++++------------------------------ 1 file changed, 87 insertions(+), 167 deletions(-) diff --git a/lib/src/revset.rs b/lib/src/revset.rs index 8b203c10a..3b69f0502 100644 --- a/lib/src/revset.rs +++ b/lib/src/revset.rs @@ -22,7 +22,7 @@ use std::rc::Rc; use std::sync::Arc; use itertools::Itertools; -use pest::iterators::Pairs; +use pest::iterators::{Pair, Pairs}; use pest::Parser; use pest_derive::Parser; use thiserror::Error; @@ -591,212 +591,88 @@ fn parse_symbol_rule(mut pairs: Pairs) -> Result, Rev fn parse_function_expression( name: String, - mut argument_pairs: Pairs, + argument_pairs: Pairs, workspace_ctx: Option<&RevsetWorkspaceContext>, ) -> Result, RevsetParseError> { let arg_count = argument_pairs.clone().count(); match name.as_str() { "parents" => { - if arg_count == 1 { - Ok(parse_expression_rule( - argument_pairs.next().unwrap().into_inner(), - workspace_ctx, - )? - .parents()) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 1 argument".to_string(), - }) - } + let arg = expect_one_argument(&name, argument_pairs)?; + let expression = parse_expression_rule(arg.into_inner(), workspace_ctx)?; + Ok(expression.parents()) } "children" => { - if arg_count == 1 { - let expression = parse_expression_rule( - argument_pairs.next().unwrap().into_inner(), - workspace_ctx, - )?; - Ok(expression.children()) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 1 argument".to_string(), - }) - } + let arg = expect_one_argument(&name, argument_pairs)?; + let expression = parse_expression_rule(arg.into_inner(), workspace_ctx)?; + Ok(expression.children()) } "ancestors" => { - if arg_count == 1 { - Ok(parse_expression_rule( - argument_pairs.next().unwrap().into_inner(), - workspace_ctx, - )? - .ancestors()) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 1 argument".to_string(), - }) - } + let arg = expect_one_argument(&name, argument_pairs)?; + let expression = parse_expression_rule(arg.into_inner(), workspace_ctx)?; + Ok(expression.ancestors()) } "descendants" => { - if arg_count == 1 { - let expression = parse_expression_rule( - argument_pairs.next().unwrap().into_inner(), - workspace_ctx, - )?; - Ok(expression.descendants()) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 1 argument".to_string(), - }) - } + let arg = expect_one_argument(&name, argument_pairs)?; + let expression = parse_expression_rule(arg.into_inner(), workspace_ctx)?; + Ok(expression.descendants()) } "connected" => { - if arg_count == 1 { - let candidates = parse_expression_rule( - argument_pairs.next().unwrap().into_inner(), - workspace_ctx, - )?; - Ok(candidates.connected()) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 1 argument".to_string(), - }) - } + let arg = expect_one_argument(&name, argument_pairs)?; + let candidates = parse_expression_rule(arg.into_inner(), workspace_ctx)?; + Ok(candidates.connected()) } "none" => { - if arg_count == 0 { - Ok(RevsetExpression::none()) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 0 arguments".to_string(), - }) - } + expect_no_arguments(&name, argument_pairs)?; + Ok(RevsetExpression::none()) } "all" => { - if arg_count == 0 { - Ok(RevsetExpression::all()) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 0 arguments".to_string(), - }) - } + expect_no_arguments(&name, argument_pairs)?; + Ok(RevsetExpression::all()) } "heads" => { - if arg_count == 0 { - Ok(RevsetExpression::visible_heads()) - } else if arg_count == 1 { - let candidates = parse_expression_rule( - argument_pairs.next().unwrap().into_inner(), - workspace_ctx, - )?; + if let Some(arg) = expect_one_optional_argument(&name, argument_pairs)? { + let candidates = parse_expression_rule(arg.into_inner(), workspace_ctx)?; Ok(candidates.heads()) } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 0 or 1 arguments".to_string(), - }) + Ok(RevsetExpression::visible_heads()) } } "roots" => { - if arg_count == 1 { - let candidates = parse_expression_rule( - argument_pairs.next().unwrap().into_inner(), - workspace_ctx, - )?; - Ok(candidates.roots()) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 1 argument".to_string(), - }) - } + let arg = expect_one_argument(&name, argument_pairs)?; + let candidates = parse_expression_rule(arg.into_inner(), workspace_ctx)?; + Ok(candidates.roots()) } "public_heads" => { - if arg_count == 0 { - Ok(RevsetExpression::public_heads()) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 0 arguments".to_string(), - }) - } + expect_no_arguments(&name, argument_pairs)?; + Ok(RevsetExpression::public_heads()) } "branches" => { - if arg_count == 0 { - Ok(RevsetExpression::branches()) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 0 arguments".to_string(), - }) - } + expect_no_arguments(&name, argument_pairs)?; + Ok(RevsetExpression::branches()) } "remote_branches" => { - if arg_count == 0 { - Ok(RevsetExpression::remote_branches()) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 0 arguments".to_string(), - }) - } + expect_no_arguments(&name, argument_pairs)?; + Ok(RevsetExpression::remote_branches()) } "tags" => { - if arg_count == 0 { - Ok(RevsetExpression::tags()) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 0 arguments".to_string(), - }) - } + expect_no_arguments(&name, argument_pairs)?; + Ok(RevsetExpression::tags()) } "git_refs" => { - if arg_count == 0 { - Ok(RevsetExpression::git_refs()) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 0 arguments".to_string(), - }) - } + expect_no_arguments(&name, argument_pairs)?; + Ok(RevsetExpression::git_refs()) } "git_head" => { - if arg_count == 0 { - Ok(RevsetExpression::git_head()) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 0 arguments".to_string(), - }) - } + expect_no_arguments(&name, argument_pairs)?; + Ok(RevsetExpression::git_head()) } "merges" => { - if arg_count == 0 { - Ok(RevsetExpression::all().with_parent_count(2..u32::MAX)) - } else { - Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 0 arguments".to_string(), - }) - } + expect_no_arguments(&name, argument_pairs)?; + Ok(RevsetExpression::all().with_parent_count(2..u32::MAX)) } "description" | "author" | "committer" => { - if arg_count != 1 { - return Err(RevsetParseError::InvalidFunctionArguments { - name, - message: "Expected 1 argument".to_string(), - }); - } - let needle = parse_function_argument_to_string( - &name, - argument_pairs.next().unwrap().into_inner(), - )?; + let arg = expect_one_argument(&name, argument_pairs)?; + let needle = parse_function_argument_to_string(&name, arg.into_inner())?; let candidates = RevsetExpression::all(); match name.as_str() { "description" => Ok(candidates.with_description(needle)), @@ -831,6 +707,50 @@ fn parse_function_expression( } } +fn expect_no_arguments( + name: &str, + mut argument_pairs: Pairs, +) -> Result<(), RevsetParseError> { + if argument_pairs.next().is_none() { + Ok(()) + } else { + Err(RevsetParseError::InvalidFunctionArguments { + name: name.to_owned(), + message: "Expected 0 arguments".to_string(), + }) + } +} + +fn expect_one_argument<'i>( + name: &str, + argument_pairs: Pairs<'i, Rule>, +) -> Result, RevsetParseError> { + let mut argument_pairs = argument_pairs.fuse(); + if let (Some(arg), None) = (argument_pairs.next(), argument_pairs.next()) { + Ok(arg) + } else { + Err(RevsetParseError::InvalidFunctionArguments { + name: name.to_owned(), + message: "Expected 1 argument".to_string(), + }) + } +} + +fn expect_one_optional_argument<'i>( + name: &str, + argument_pairs: Pairs<'i, Rule>, +) -> Result>, RevsetParseError> { + let mut argument_pairs = argument_pairs.fuse(); + if let (opt_arg, None) = (argument_pairs.next(), argument_pairs.next()) { + Ok(opt_arg) + } else { + Err(RevsetParseError::InvalidFunctionArguments { + name: name.to_owned(), + message: "Expected 0 or 1 arguments".to_string(), + }) + } +} + fn parse_function_argument_to_string( name: &str, pairs: Pairs,