Skip to content

Commit 257911c

Browse files
committed
add exact pattern strings
1 parent cf7ca35 commit 257911c

2 files changed

Lines changed: 88 additions & 0 deletions

File tree

src/ValueObject/PatternCollection.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,19 @@ public function all(): array
3838
return $this->patterns;
3939
}
4040

41+
/**
42+
* @return string[]
43+
*/
44+
public function exactPatternStrings(): array
45+
{
46+
$exactPatterns = $this->byType(\Rector\Behastan\ValueObject\Pattern\ExactPattern::class);
47+
48+
return array_map(
49+
fn (\Rector\Behastan\ValueObject\Pattern\ExactPattern $pattern): string => $pattern->pattern,
50+
$exactPatterns
51+
);
52+
}
53+
4154
/**
4255
* @template TPattern as AbstractPattern
4356
*
@@ -48,4 +61,42 @@ public function byType(string $type): array
4861
{
4962
return array_filter($this->patterns, fn (AbstractPattern $pattern): bool => $pattern instanceof $type);
5063
}
64+
65+
public function regexPatternString(): string
66+
{
67+
$regexPatterns = $this->byType(\Rector\Behastan\ValueObject\Pattern\RegexPattern::class);
68+
69+
$regexPatternStrings = array_map(
70+
fn (\Rector\Behastan\ValueObject\Pattern\RegexPattern $pattern): string => $pattern->pattern,
71+
$regexPatterns
72+
);
73+
74+
return $this->combineRegexes($regexPatternStrings, '#');
75+
}
76+
77+
/**
78+
* @param string[] $regexes Like ['/foo/i', '~bar\d+~', '#baz#u']
79+
*/
80+
private function combineRegexes(array $regexes, string $delimiter = '#'): string
81+
{
82+
$parts = [];
83+
84+
foreach ($regexes as $rx) {
85+
// Very common case: regex is given like "/pattern/flags"
86+
// Parse: delimiter + pattern + delimiter + flags
87+
if (! preg_match('~^(.)(.*)\\1([a-zA-Z]*)$~s', $rx, $m)) {
88+
throw new \InvalidArgumentException("Invalid regex: {$rx}");
89+
}
90+
91+
$pattern = $m[2];
92+
$flags = $m[3];
93+
94+
// If you truly have mixed flags per-regex, you can't naively merge them.
95+
// Best practice: normalize flags beforehand (same for all).
96+
// We'll ignore per-regex flags here and let the caller decide final flags.
97+
$parts[] = '(?:' . $pattern . ')';
98+
}
99+
100+
return $delimiter . '(?:' . implode('|', $parts) . ')' . $delimiter;
101+
}
51102
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Behastan\Tests\ValueObject;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Rector\Behastan\ValueObject\Pattern\ExactPattern;
9+
use Rector\Behastan\ValueObject\Pattern\NamedPattern;
10+
use Rector\Behastan\ValueObject\Pattern\RegexPattern;
11+
use Rector\Behastan\ValueObject\PatternCollection;
12+
13+
final class PatternCollectionTest extends TestCase
14+
{
15+
public function testExactPatterns(): void
16+
{
17+
$patternCollection = new PatternCollection([
18+
new ExactPattern('pattern1', 'file1.php', 10, 'SomeClass', 'someMethod'),
19+
new ExactPattern('pattern2', 'file2.php', 20, 'AnotherClass', 'anotherMethod'),
20+
new NamedPattern('this is :me', 'file1.php', 10, 'SomeClass', 'someMethod'),
21+
]);
22+
23+
$this->assertSame(['pattern1', 'pattern2'], $patternCollection->exactPatternStrings());
24+
}
25+
26+
public function testRegexPatterns(): void
27+
{
28+
$patternCollection = new PatternCollection([
29+
new ExactPattern('pattern1', 'file1.php', 10, 'SomeClass', 'someMethod'),
30+
new RegexPattern('#this is it#', 'file1.php', 10, 'SomeClass', 'someMethod'),
31+
new RegexPattern('#here is more#', 'file1.php', 10, 'SomeClass', 'someMethod'),
32+
]);
33+
34+
$this->assertSame('#(?:(?:this is it)|(?:here is more))#', $patternCollection->regexPatternString());
35+
36+
}
37+
}

0 commit comments

Comments
 (0)