From abffae07ed350ebb1de98edd2ae246ccddfa6085 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Mon, 17 Aug 2026 03:23:52 +0900 Subject: refactor(preg): merge preg_match_all_offset_capture2() into its sibling The two functions ran the same search and differed only in how they reported a non-participating group: one as ("", 0) in a bespoke struct, the other as (null, -1) in a capture-key map. Neither shape covered both callers, because PHP reaches preg_match_all() with different flags from each: Preg::matchAllWithOffsets() always ORs in PREG_UNMATCHED_AS_NULL, while OutputFormatter::formatAndWrap() passes PREG_OFFSET_CAPTURE alone. Keep the capture-key map, which also exposes named groups, and take the flags that decide between null and "" for an unmatched group. The offset is -1 either way, so the ("", 0) approximation is gone. Co-Authored-By: Claude Opus 5 (1M context) --- .../src/formatter/output_formatter.rs | 33 ++++++++++++++-------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'crates/shirabe-symfony-console/src/formatter/output_formatter.rs') diff --git a/crates/shirabe-symfony-console/src/formatter/output_formatter.rs b/crates/shirabe-symfony-console/src/formatter/output_formatter.rs index 4943e65b..6ce96875 100644 --- a/crates/shirabe-symfony-console/src/formatter/output_formatter.rs +++ b/crates/shirabe-symfony-console/src/formatter/output_formatter.rs @@ -7,8 +7,8 @@ use crate::formatter::output_formatter_style_interface::OutputFormatterStyleInte use crate::formatter::output_formatter_style_stack::OutputFormatterStyleStack; use crate::formatter::wrappable_output_formatter_interface::WrappableOutputFormatterInterface; use shirabe_php_shim::{ - php_regex, preg_match, preg_match_all, preg_match_all_offset_capture, preg_match_all_set_order, - preg_replace, + CaptureKey, php_regex, preg_match, preg_match_all, preg_match_all_offset_capture, + preg_match_all_set_order, preg_replace, }; use shirabe_symfony_string::b; @@ -290,16 +290,24 @@ impl WrappableOutputFormatterInterface for OutputFormatter { let open_tag_regex = "[a-z](?:[^\\\\<>]* | \\\\.)*"; let close_tag_regex = "[a-z][^<>]*"; let mut current_line_length: i64 = 0; - let mut matches: shirabe_php_shim::PregOffsetCaptureMatches = Default::default(); + let mut matches: indexmap::IndexMap, i64)>> = + indexmap::IndexMap::new(); preg_match_all_offset_capture( format!("#<(({open_tag_regex}) | /({close_tag_regex})?)>#ix"), message, &mut matches, + 0, ); - let count = matches.group(0).len(); - for i in 0..count { - let (text, pos) = matches.group(0)[i].clone(); - let pos = pos as i64; + let full_matches = matches + .get(&CaptureKey::ByIndex(0)) + .cloned() + .unwrap_or_default(); + for (i, match_) in full_matches.iter().enumerate() { + let pos = match_.1; + let text = match_ + .0 + .clone() + .expect("group 0 participates whenever the pattern matches"); if pos != 0 && shirabe_php_shim::byte_at(message, (pos - 1) as usize) == b'\\' { continue; @@ -315,12 +323,15 @@ impl WrappableOutputFormatterInterface for OutputFormatter { // opening tag? let open = shirabe_php_shim::byte_at(&text, 1) != b'/'; let tag = if open { - matches.group(1)[i].0.clone() + matches[&CaptureKey::ByIndex(1)][i] + .0 + .clone() + .expect("group 1 participates whenever the pattern matches") } else { matches - .group(3) - .get(i) - .map(|m| m.0.clone()) + .get(&CaptureKey::ByIndex(3)) + .and_then(|group| group.get(i)) + .and_then(|m| m.0.clone()) .unwrap_or_default() }; -- cgit v1.3.1-4-g156e