diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-08-18 01:57:02 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-08-18 01:57:02 +0900 |
| commit | 6aeda8b237fcbf7a56ca0e8c0fff415477d31d22 (patch) | |
| tree | 13942695ae0e7c749cfcdb12d5824daf7134c008 /crates/shirabe | |
| parent | fed0a6e7ac361af9b963c1f62411b1a85478230c (diff) | |
| download | php-shirabe-6aeda8b237fcbf7a56ca0e8c0fff415477d31d22.tar.gz php-shirabe-6aeda8b237fcbf7a56ca0e8c0fff415477d31d22.tar.zst php-shirabe-6aeda8b237fcbf7a56ca0e8c0fff415477d31d22.zip | |
refactor(preg): make preg_match_all yield matches per occurrence
PHP's PREG_PATTERN_ORDER is column-oriented, but 7 of the 10 call sites
read it row-wise, rebuilding each occurrence by indexing every column at
the same offset. Return an iterator of PregMatches instead, which is also
what the set-order and offset-capture variants were carrying, so the
three functions collapse into one and PregMatchesAll,
PregMatchesAllWithOffsets, CaptureKey and preg_match_map! all go away.
The offset-capture call sites are served by the new PregMatches
get_offset/name_offset accessors.
The search stays eager: regex::Captures borrows only the subject, so the
matches outlive the pattern resolved for the call, and PHP's
preg_match_all is eager too.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe')
| -rw-r--r-- | crates/shirabe/src/command/init_command.rs | 26 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/git_downloader.rs | 45 | ||||
| -rw-r--r-- | crates/shirabe/src/package/version/version_bumper.rs | 32 |
3 files changed, 49 insertions, 54 deletions
diff --git a/crates/shirabe/src/command/init_command.rs b/crates/shirabe/src/command/init_command.rs index 54ebc995..add7c237 100644 --- a/crates/shirabe/src/command/init_command.rs +++ b/crates/shirabe/src/command/init_command.rs @@ -21,7 +21,7 @@ use crate::util::Silencer; use indexmap::IndexMap; use shirabe_php_shim::Catch as _; use shirabe_php_shim::{ - CaptureKey, FILE_IGNORE_NEW_LINES, InvalidArgumentException, PHP_EOL, PHP_SERVER, PhpMixed, + 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_is_match, preg_match, preg_match_all, preg_quote, @@ -167,21 +167,15 @@ impl InitCommand { ) == 0 { *self.git_config.borrow_mut() = Some(IndexMap::new()); - let m = preg_match_all(php_regex!(r"{^([^=]+)=(.*)$}m"), &output); - if m.occurrence_count() > 0 { - let keys: Vec<Option<String>> = - m.get(&CaptureKey::ByIndex(1)).cloned().unwrap_or_default(); - let values: Vec<Option<String>> = - m.get(&CaptureKey::ByIndex(2)).cloned().unwrap_or_default(); - for (key, value) in keys.iter().zip(values.iter()) { - self.git_config.borrow_mut().as_mut().unwrap().insert( - key.clone() - .expect("group 1 participates whenever the pattern matches"), - value - .clone() - .expect("group 2 participates whenever the pattern matches"), - ); - } + for m in preg_match_all(php_regex!(r"{^([^=]+)=(.*)$}m"), &output) { + self.git_config.borrow_mut().as_mut().unwrap().insert( + m.get(1) + .expect("group 1 participates whenever the pattern matches") + .to_string(), + m.get(2) + .expect("group 2 participates whenever the pattern matches") + .to_string(), + ); } return self.git_config.borrow().clone().unwrap_or_default(); diff --git a/crates/shirabe/src/downloader/git_downloader.rs b/crates/shirabe/src/downloader/git_downloader.rs index a8a4344d..2d506fdf 100644 --- a/crates/shirabe/src/downloader/git_downloader.rs +++ b/crates/shirabe/src/downloader/git_downloader.rs @@ -18,10 +18,9 @@ use crate::util::ProcessExecutor; 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_is_match, preg_match, preg_match_all, - preg_quote, preg_replace, preg_split, realpath, rtrim, strlen, strpos, substr, trim, - version_compare, + CmpOp, PhpMixed, RuntimeException, array_map, basename, dirname, impl_php_class, implode, + in_array_strict, is_dir, php_regex, preg_is_match, preg_match, preg_match_all, preg_quote, + preg_replace, preg_split, realpath, rtrim, strlen, strpos, substr, trim, version_compare, }; #[derive(Debug)] @@ -101,21 +100,21 @@ impl GitDownloader { }; let head_ref = head_match.get(1).unwrap_or_default().to_string(); - let branches_match = preg_match_all( + let candidate_branches: Vec<String> = preg_match_all( format!("{{^{} refs/heads/(.+)$}}mi", preg_quote(&head_ref, None)), &refs, - ); - if branches_match.occurrence_count() == 0 { + ) + .map(|branch_match| { + branch_match + .get(1) + .expect("group 1 participates whenever the pattern matches") + .to_string() + }) + .collect(); + if candidate_branches.is_empty() { // not on a branch, we are either on a not-modified tag or some sort of detached head, so skip this return Ok(None); } - let candidate_branches: Vec<String> = branches_match - .get(&CaptureKey::ByIndex(1)) - .cloned() - .unwrap_or_default() - .into_iter() - .map(|branch| branch.expect("group 1 participates whenever the pattern matches")) - .collect(); // use the first match as branch name for now let mut branch = candidate_branches[0].clone(); @@ -128,21 +127,23 @@ impl GitDownloader { // try to find matching branch names in remote repos for candidate in &candidate_branches { - let m = preg_match_all( + let matches: Vec<String> = preg_match_all( format!( "{{^[a-f0-9]+ refs/remotes/((?:[^/]+)/{})$}}mi", preg_quote(candidate, None) ), &refs, - ); - if m.occurrence_count() > 0 { - let matches: Vec<Option<String>> = - m.get(&CaptureKey::ByIndex(1)).cloned().unwrap_or_default(); + ) + .map(|m| { + m.get(1) + .expect("group 1 participates whenever the pattern matches") + .to_string() + }) + .collect(); + if !matches.is_empty() { for match_ in matches { branch = candidate.clone(); - remote_branches.push( - match_.expect("group 1 participates whenever the pattern matches"), - ); + remote_branches.push(match_); } break; } diff --git a/crates/shirabe/src/package/version/version_bumper.rs b/crates/shirabe/src/package/version/version_bumper.rs index 075663d4..4bb95ef1 100644 --- a/crates/shirabe/src/package/version/version_bumper.rs +++ b/crates/shirabe/src/package/version/version_bumper.rs @@ -5,9 +5,7 @@ use crate::package::dumper::ArrayDumper; use crate::package::loader::ArrayLoader; use crate::package::version::VersionParser; use crate::util::Platform; -use shirabe_php_shim::{ - CaptureKey, php_regex, preg_is_match, preg_match_all_offset_capture, preg_replace, -}; +use shirabe_php_shim::{php_regex, preg_is_match, preg_match_all, preg_replace}; use shirabe_semver::Intervals; use shirabe_semver::constraint::AnyConstraint; @@ -78,19 +76,21 @@ impl VersionBumper { major = major ); - let matches = preg_match_all_offset_capture(&pattern, &pretty_constraint); - if matches.occurrence_count() > 0 { - let mut modified = pretty_constraint.clone(); - let constraint_matches = matches - .get(&CaptureKey::ByName("constraint".to_string())) - .cloned() - .unwrap_or_default(); - for match_ in constraint_matches.iter().rev() { - let match_str = match_ - .0 - .as_deref() + // Collected eagerly: a match borrows `pretty_constraint`, which the returns below move. + let constraint_matches: Vec<(String, i64)> = preg_match_all(&pattern, &pretty_constraint) + .map(|match_| { + let constraint = match_ + .name("constraint") + .expect("the `constraint` group participates whenever the pattern matches"); + let offset = match_ + .name_offset("constraint") .expect("the `constraint` group participates whenever the pattern matches"); - let match_offset = match_.1; + (constraint.to_string(), offset as i64) + }) + .collect(); + if !constraint_matches.is_empty() { + let mut modified = pretty_constraint.clone(); + for (match_str, match_offset) in constraint_matches.into_iter().rev() { let suffix = if match_str.matches('.').count() == 2 && version_without_suffix.matches('.').count() == 1 { @@ -119,7 +119,7 @@ impl VersionBumper { &modified, &replacement, match_offset, - Some(Platform::strlen(match_str)), + Some(Platform::strlen(&match_str)), ); } |
