From a01330572b985007acae339817d171a6505bb16b Mon Sep 17 00:00:00 2001 From: nsfisis Date: Tue, 18 Aug 2026 01:57:02 +0900 Subject: refactor(preg): drop the Vec-returning preg_match_all The two preg_match_all variants took the same arguments and differed only in what they returned: a Vec of columns, or the named-and-numbered PregMatchesAll. The latter is the one all but two call sites already used, so preg_match_all2 takes over the plain PHP name and the Vec variant goes away. Its remaining readers only ever wanted group 0's column, which they now take through CaptureKey::ByIndex(0); in the formatter this replaces the array_shift that popped that column off the PREG_PATTERN_ORDER array. Co-Authored-By: Claude Opus 5 (1M context) --- .../src/php_file_parser.rs | 6 +++--- crates/shirabe-php-shim/src/preg.rs | 22 +++------------------- .../src/completion/completion_input.rs | 6 ++++-- .../src/formatter/output_formatter.rs | 8 +++++--- crates/shirabe/src/command/init_command.rs | 4 ++-- crates/shirabe/src/downloader/git_downloader.rs | 6 +++--- 6 files changed, 20 insertions(+), 32 deletions(-) (limited to 'crates') diff --git a/crates/shirabe-class-map-generator/src/php_file_parser.rs b/crates/shirabe-class-map-generator/src/php_file_parser.rs index 0ed78c7f..7cc96228 100644 --- a/crates/shirabe-class-map-generator/src/php_file_parser.rs +++ b/crates/shirabe-class-map-generator/src/php_file_parser.rs @@ -3,7 +3,7 @@ use crate::php_file_cleaner::PhpFileCleaner; use shirabe_php_shim::{ CaptureKey, PHP_EOL, RuntimeException, file_exists, file_get_contents, function_exists, - is_file, is_readable, ltrim, php_strip_whitespace, preg_match_all2, str_replace_array, strrpos, + is_file, is_readable, ltrim, php_strip_whitespace, preg_match_all, str_replace_array, strrpos, substr, trim, }; use std::sync::OnceLock; @@ -58,7 +58,7 @@ impl PhpFileParser { // return early if there is no chance of matching anything in this file let pattern = format!("{{\\b(?:class|interface|trait{})\\s}}i", extra_types); - let max_matches = preg_match_all2(&pattern, &contents).occurrence_count(); + let max_matches = preg_match_all(&pattern, &contents).occurrence_count(); if max_matches == 0 { return Ok(vec![]); } @@ -84,7 +84,7 @@ impl PhpFileParser { }}ix", et = extra_types ); - let matches = preg_match_all2(&pattern2, &contents); + let matches = preg_match_all(&pattern2, &contents); let mut classes = vec![]; let mut namespace = String::new(); diff --git a/crates/shirabe-php-shim/src/preg.rs b/crates/shirabe-php-shim/src/preg.rs index d8bdcc10..e84f8463 100644 --- a/crates/shirabe-php-shim/src/preg.rs +++ b/crates/shirabe-php-shim/src/preg.rs @@ -175,24 +175,9 @@ pub fn preg_match2<'h>( Some(PregMatches::new(caps)) } -// PREG_PATTERN_ORDER: the outer vec is indexed by capture group, the inner by -// match occurrence. A non-participating group is reported as None. -pub fn preg_match_all(pattern: impl PregPattern, subject: &str) -> Vec>> { - let __resolved = pattern.resolve(); - let (re, _anchored) = __resolved.parts(); - let group_count = re.captures_len(); - let mut groups: Vec>> = vec![Vec::new(); group_count]; - for caps in re.captures_iter(subject) { - for (g, group) in groups.iter_mut().enumerate() { - group.push(caps.get(g).map(|m| m.as_str().to_string())); - } - } - groups -} - // The number of occurrences the caller would get from PHP's return value is the length of any // one column, as `PregMatchesAll::occurrence_count` reports it. -pub fn preg_match_all2(pattern: impl PregPattern, subject: &str) -> PregMatchesAll { +pub fn preg_match_all(pattern: impl PregPattern, subject: &str) -> PregMatchesAll { let __resolved = pattern.resolve(); let (re, _anchored) = __resolved.parts(); let group_count = re.captures_len(); @@ -473,9 +458,8 @@ fn translate_php_pattern(pattern: &str) -> anyhow::Result<(String, bool)> { .collect(); // PCRE's `A` (PCRE_ANCHORED) modifier requires the match to start exactly at the search offset. - // The `regex` crate has no per-search anchoring, so the offset-based callers - // (`preg_match2`/`preg_match_all2`) honour it by searching a sub-slice that begins at the offset; - // here we only surface the flag. + // The `regex` crate has no per-search anchoring, so `preg_match2` honours it by searching a + // sub-slice that begins at the offset; here we only surface the flag. let anchored = modifiers.contains('A'); let inner = translate_pcre_literals(inner); diff --git a/crates/shirabe-symfony-console/src/completion/completion_input.rs b/crates/shirabe-symfony-console/src/completion/completion_input.rs index aafa7c8a..41c15ec5 100644 --- a/crates/shirabe-symfony-console/src/completion/completion_input.rs +++ b/crates/shirabe-symfony-console/src/completion/completion_input.rs @@ -3,7 +3,7 @@ use crate::input::ArgvInput; use crate::input::InputDefinition; use crate::input::InputOption; -use shirabe_php_shim::{PhpMixed, php_regex, preg_match_all}; +use shirabe_php_shim::{CaptureKey, PhpMixed, php_regex, preg_match_all}; /// An input specialized for shell completion. /// @@ -35,7 +35,9 @@ impl CompletionInput { ); Self::from_tokens( - tokens[0] + tokens + .get(&CaptureKey::ByIndex(0)) + .expect("group 0 is always present") .iter() .map(|token| { token diff --git a/crates/shirabe-symfony-console/src/formatter/output_formatter.rs b/crates/shirabe-symfony-console/src/formatter/output_formatter.rs index 256fade1..f4c55573 100644 --- a/crates/shirabe-symfony-console/src/formatter/output_formatter.rs +++ b/crates/shirabe-symfony-console/src/formatter/output_formatter.rs @@ -135,12 +135,14 @@ impl OutputFormatter { let url = preg_replace(php_regex!("{\\\\([<>])}"), "$1", &r#match[1]); style.set_href(&url); } else if r#match[0] == "options" { - let mut options = preg_match_all( + let options = preg_match_all( php_regex!("([^,;]+)"), &shirabe_php_shim::strtolower(&r#match[1]), ); - let options = shirabe_php_shim::array_shift(&mut options).unwrap_or_default(); - for option in &options { + let options = options + .get(&CaptureKey::ByIndex(0)) + .expect("group 0 is always present"); + for option in options { style.set_option( option .as_deref() diff --git a/crates/shirabe/src/command/init_command.rs b/crates/shirabe/src/command/init_command.rs index 96bdc58d..b316e4fe 100644 --- a/crates/shirabe/src/command/init_command.rs +++ b/crates/shirabe/src/command/init_command.rs @@ -24,7 +24,7 @@ use shirabe_php_shim::{ CaptureKey, FILE_IGNORE_NEW_LINES, InvalidArgumentException, PHP_EOL, PHP_SERVER, PhpMixed, array_flip_strings, array_intersect_key, array_map, basename, empty, explode, file, file_exists, file_get_contents, file_put_contents, get_current_user, impl_php_class, implode, - is_dir, is_string, php_regex, preg_match_all2, preg_match2, preg_quote, preg_replace, realpath, + is_dir, is_string, php_regex, preg_match_all, preg_match2, preg_quote, preg_replace, realpath, str_replace, strpos, strtolower, trim, ucwords, }; use shirabe_spdx_licenses::SpdxLicenses; @@ -168,7 +168,7 @@ impl InitCommand { ) == 0 { *self.git_config.borrow_mut() = Some(IndexMap::new()); - let m = preg_match_all2(php_regex!(r"{^([^=]+)=(.*)$}m"), &output); + let m = preg_match_all(php_regex!(r"{^([^=]+)=(.*)$}m"), &output); if m.occurrence_count() > 0 { let keys: Vec> = m.get(&CaptureKey::ByIndex(1)).cloned().unwrap_or_default(); diff --git a/crates/shirabe/src/downloader/git_downloader.rs b/crates/shirabe/src/downloader/git_downloader.rs index d3dea453..6e79576d 100644 --- a/crates/shirabe/src/downloader/git_downloader.rs +++ b/crates/shirabe/src/downloader/git_downloader.rs @@ -19,7 +19,7 @@ use crate::util::Url; use indexmap::IndexMap; use shirabe_php_shim::{ CaptureKey, CmpOp, PhpMixed, RuntimeException, array_map, basename, dirname, impl_php_class, - implode, in_array_strict, is_dir, php_regex, preg_match_all2, preg_match2, preg_quote, + implode, in_array_strict, is_dir, php_regex, preg_match_all, preg_match2, preg_quote, preg_replace, preg_split, realpath, rtrim, strlen, strpos, substr, trim, version_compare, }; @@ -100,7 +100,7 @@ impl GitDownloader { }; let head_ref = head_match.get(1).unwrap_or_default().to_string(); - let branches_match = preg_match_all2( + let branches_match = preg_match_all( format!("{{^{} refs/heads/(.+)$}}mi", preg_quote(&head_ref, None)), &refs, ); @@ -127,7 +127,7 @@ impl GitDownloader { // try to find matching branch names in remote repos for candidate in &candidate_branches { - let m = preg_match_all2( + let m = preg_match_all( format!( "{{^[a-f0-9]+ refs/remotes/((?:[^/]+)/{})$}}mi", preg_quote(candidate, None) -- cgit v1.3.1-4-g156e