From 79b504e55cd4c4d1da102c3a076dc2a2e1edcd65 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Mon, 17 Aug 2026 08:05:42 +0900 Subject: refactor(pcre): return the Preg $matches instead of filling an out-param `Composer\Pcre\Preg` fills `$matches` through a by-ref parameter, and the port mirrored that with a `&mut` (or `Option<&mut>`) out-param plus a bool or count return. Callers had to declare an empty map one line ahead of the call, and the type never said the map is only meaningful when the call matched. Return the matches instead: - match3/match4/is_match3/is_match4 -> Option - is_match_named -> Option - match_all2/is_match_all -> PregMatchesAll - is_match_all_with_offsets3 -> PregMatchesAllWithOffsets Nothing is lost: the bool is `Option::is_some()`, and the occurrence count is the length of any one column of a PREG_PATTERN_ORDER map, now spelled `PregMatchesAll::occurrence_count()`. is_match() still answers the bool question directly for callers that want no groups. Co-Authored-By: Claude Opus 5 (1M context) --- .../src/class_map_generator.rs | 6 ++---- .../src/php_file_cleaner.rs | 21 +++++++-------------- .../src/php_file_parser.rs | 5 ++--- 3 files changed, 11 insertions(+), 21 deletions(-) (limited to 'crates/shirabe-class-map-generator/src') diff --git a/crates/shirabe-class-map-generator/src/class_map_generator.rs b/crates/shirabe-class-map-generator/src/class_map_generator.rs index 478781c8..670f8448 100644 --- a/crates/shirabe-class-map-generator/src/class_map_generator.rs +++ b/crates/shirabe-class-map-generator/src/class_map_generator.rs @@ -3,7 +3,7 @@ use crate::class_map::ClassMap; use crate::file_list::FileList; use crate::php_file_parser::PhpFileParser; -use shirabe_pcre::{CaptureKey, Preg, PregMatchedGroups}; +use shirabe_pcre::{CaptureKey, Preg}; use shirabe_php_shim::{ InvalidArgumentException, LogicException, PATHINFO_EXTENSION, RuntimeException, explode, getcwd, implode, is_dir, is_file, pathinfo, php_regex, preg_quote, realpath, str_replace, @@ -347,11 +347,9 @@ impl ClassMapGenerator { } // extract a prefix being a protocol://, protocol:, protocol://drive: or simply drive: - let mut r#match = PregMatchedGroups::new(); - if Preg::is_match3( + if let Some(r#match) = Preg::is_match3( php_regex!(r"{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix"), &path, - Some(&mut r#match), ) { prefix = r#match .get(&CaptureKey::ByIndex(1)) diff --git a/crates/shirabe-class-map-generator/src/php_file_cleaner.rs b/crates/shirabe-class-map-generator/src/php_file_cleaner.rs index 78041061..5731dbd4 100644 --- a/crates/shirabe-class-map-generator/src/php_file_cleaner.rs +++ b/crates/shirabe-class-map-generator/src/php_file_cleaner.rs @@ -97,15 +97,13 @@ impl PhpFileCleaner { } if char == '<' && self.peek('<') { - let mut r#match = PregMatchedGroups::new(); // Regex pattern compatibility: // PHP matches `<<<`, an optional quote, the identifier, then requires the // closing quote to be the exact same character via `\1`. The `regex` crate has // no backreferences, so the three quote states (none, `'`, `"`) are expanded // into separate alternatives, each capturing the identifier in its own group. - if self.r#match( + if let Some(r#match) = self.r#match( r#"{<<<[ \t]*(?:"([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)"|'([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)'|([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*))(?:\r\n|\n|\r)}A"#, - Some(&mut r#match), ) { self.index += r#match.get(&CaptureKey::ByIndex(0)).map(|s| s.len()).unwrap_or(0); let delimiter = [1, 2, 3] @@ -144,13 +142,9 @@ impl PhpFileCleaner { let end = self.index + entry.length; if end <= self.len && self.contents[self.index..end] == entry.name { let offset = if self.index > 0 { self.index - 1 } else { 0 }; - let mut r#match = PregMatchedGroups::new(); - if Preg::is_match4( - &entry.pattern, - &self.contents, - Some(&mut r#match), - offset, - ) { + if let Some(r#match) = + Preg::is_match4(&entry.pattern, &self.contents, offset) + { return clean + r#match .get(&CaptureKey::ByIndex(0)) @@ -164,8 +158,7 @@ impl PhpFileCleaner { self.index += 1; let rest_pattern = REST_PATTERN.lock().unwrap().clone(); if let Some(rest_pattern) = rest_pattern { - let mut r#match = PregMatchedGroups::new(); - if self.r#match(&rest_pattern, Some(&mut r#match)) { + if let Some(r#match) = self.r#match(&rest_pattern) { let m0 = r#match .get(&CaptureKey::ByIndex(0)) .cloned() @@ -292,7 +285,7 @@ impl PhpFileCleaner { self.index + 1 < self.len && self.contents.as_bytes()[self.index + 1] as char == char } - fn r#match(&self, regex: &str, r#match: Option<&mut PregMatchedGroups>) -> bool { - Preg::is_match4(regex, &self.contents, r#match, self.index) + fn r#match(&self, regex: &str) -> Option { + Preg::is_match4(regex, &self.contents, self.index) } } 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 a1207140..e05f4f1a 100644 --- a/crates/shirabe-class-map-generator/src/php_file_parser.rs +++ b/crates/shirabe-class-map-generator/src/php_file_parser.rs @@ -1,7 +1,7 @@ //! ref: composer/vendor/composer/class-map-generator/src/PhpFileParser.php use crate::php_file_cleaner::PhpFileCleaner; -use shirabe_pcre::{CaptureKey, Preg, PregMatchesAll}; +use shirabe_pcre::{CaptureKey, Preg}; use shirabe_php_shim::{ PHP_EOL, RuntimeException, file_exists, file_get_contents, function_exists, is_file, is_readable, ltrim, php_strip_whitespace, str_replace_array, strrpos, substr, trim, @@ -84,8 +84,7 @@ impl PhpFileParser { }}ix", et = extra_types ); - let mut matches = PregMatchesAll::new(); - Preg::match_all2(&pattern2, &contents, &mut matches); + let matches = Preg::match_all2(&pattern2, &contents); let mut classes = vec![]; let mut namespace = String::new(); -- cgit v1.3.1-4-g156e