aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-class-map-generator/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe-class-map-generator/src')
-rw-r--r--crates/shirabe-class-map-generator/src/class_map_generator.rs9
-rw-r--r--crates/shirabe-class-map-generator/src/php_file_cleaner.rs12
-rw-r--r--crates/shirabe-class-map-generator/src/php_file_parser.rs17
3 files changed, 32 insertions, 6 deletions
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 5359f12..f591811 100644
--- a/crates/shirabe-class-map-generator/src/class_map_generator.rs
+++ b/crates/shirabe-class-map-generator/src/class_map_generator.rs
@@ -181,7 +181,14 @@ impl ClassMapGenerator {
file_path = format!("{}/{}", cwd, file_path);
file_path = Self::normalize_path(&file_path);
} else {
- file_path = Preg::replace(r"{(?<!:)[\\/]{2,}}", "/", &file_path);
+ // Regex pattern compatibility:
+ // PHP collapses runs of 2+ slashes/backslashes into one, except when the run is
+ // immediately preceded by `:` (to preserve scheme separators like `phar://`). The
+ // `regex` crate has no look-behind, so the `(?<!:)` guard is turned into a consuming
+ // optional leading group `(^|[^:])` that is re-emitted in the replacement. Slash runs
+ // are always separated by path-segment characters, so consuming the single preceding
+ // char never prevents an adjacent run from matching.
+ file_path = Preg::replace(r"{(^|[^:])[\\/]{2,}}", "${1}/", &file_path);
}
if file_path.is_empty() {
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 2b97d34..22e37a9 100644
--- a/crates/shirabe-class-map-generator/src/php_file_cleaner.rs
+++ b/crates/shirabe-class-map-generator/src/php_file_cleaner.rs
@@ -34,8 +34,18 @@ impl PhpFileCleaner {
TypeConfigEntry {
name: r#type.clone(),
length: r#type.len(),
+ // Regex pattern compatibility:
+ // PHP uses `.\b(?<![$:>])<type>` anchored (`A`): it consumes the single char
+ // before the keyword (`.`), requires a word boundary there (`\b`) and forbids
+ // that char being `$`, `:` or `>`. The `regex` crate has no look-behind, so the
+ // consumed char plus both guards collapse into one negated class
+ // `[^a-zA-Z0-9_$:>]` (the `\w` set reproducing `\b`, plus the three operators).
+ // The possessive quantifiers (`++`, `*+`) are performance-only and become plain
+ // `+`/`*`. The leftmost-match semantics of `captures_at(.., offset)` stand in for
+ // the dropped `A` (anchored) modifier, since the keyword is known to sit exactly
+ // one char past the search offset.
pattern: format!(
- "{{.\\b(?<![$:>]){}\\s++[a-zA-Z_\\x7f-\\xff:][a-zA-Z0-9_\\x7f-\\xff:\\-]*+}}Ais",
+ "{{[^a-zA-Z0-9_$:>]{}\\s+[a-zA-Z_\\x7f-\\xff:][a-zA-Z0-9_\\x7f-\\xff:\\-]*}}is",
r#type
),
},
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 ae98a5c..7d7c722 100644
--- a/crates/shirabe-class-map-generator/src/php_file_parser.rs
+++ b/crates/shirabe-class-map-generator/src/php_file_parser.rs
@@ -77,12 +77,21 @@ impl PhpFileParser {
let contents = p.clean();
drop(p);
+ // Regex pattern compatibility:
+ // PHP uses `\b(?<![\\$:>])<keyword>` to require the keyword to start at a word boundary and
+ // not be preceded by `\`, `$`, `:` or `>` (so `MyClass::class`, `$class`, `\class`,
+ // `Foo->class` are skipped). The `regex` crate has no look-behind, so `\b` + the negative
+ // look-behind are fused into a single consuming class `(?:^|[^...])` that excludes both the
+ // identifier characters (reproducing `\b`) and the four operator characters. The consumed
+ // separator lands in match group 0 only; the named groups are unaffected. The PCRE
+ // possessive quantifiers (`++`, `*+`) are performance-only and become plain `+`/`*`.
let pattern2 = format!(
- r"(?ix)
+ r"{{
(?:
- \b(?<![\\$:>])(?P<type>class|interface|trait{et}) \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
- | \b(?<![\\$:>])(?P<ns>namespace) (?P<nsname>\s++[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\s*+\\\\\s*+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+)? \s*+ [\{{;]
- )",
+ (?:^|[^\\$:>a-zA-Z0-9_\x7f-\xff])(?P<type>class|interface|trait{et}) \s+ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*)
+ | (?:^|[^\\$:>a-zA-Z0-9_\x7f-\xff])(?P<ns>namespace) (?P<nsname>\s+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\s*\\\s*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*)? \s* [\{{;]
+ )
+ }}ix",
et = extra_types
);
let mut matches: IndexMap<_, _> = IndexMap::new();