Skip to content

Commit 6aff3b2

Browse files
committed
Let the running engine keep its word first in the pattern rule
Every message a baseline ever wrote stays: the running engine reports a pattern both judges refuse with its own words, and the analysed engine speaks only for one the running engine compiles and the analysed project refuses - the crash the project meets on its own machine, invisible here. The upgrade section stands on its own and carries the preg_split change.
1 parent de7b130 commit 6aff3b2

3 files changed

Lines changed: 51 additions & 41 deletions

File tree

‎UPGRADING.md‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
Upgrading from PHPStan 1.x to 2.0
2-
=================================
1+
# The regex pipeline reads through the PHPRegex parser
2+
3+
The change log of the pull request that replaces the vendored Hoa PCRE
4+
grammar; the sections below are the standing upgrade guides.
35

46
## PHP version requirements
57

@@ -68,6 +70,10 @@ their shapes; the ones that change, change toward what the engine does:
6870
`preg_match('/^(a|b|c)$/', $x)`).
6971

7072
If an inferred `$matches` type narrows past what your code expects, the
73+
- `preg_split()` with a limit or a flags value no constant names keeps
74+
the generic list type (`non-empty-list<string>|false`, offset pairs
75+
where the flags may ask for them) instead of collapsing to a bare
76+
`false`.
7177
baseline is the place to say so — each change above is verifiable against
7278
the engine with a one-line `preg_match()`.
7379

‎src/Rules/Regexp/RegularExpressionPatternRule.php‎

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -124,22 +124,18 @@ private function extractPatterns(FuncCall $functionCall, Scope $scope): array
124124

125125
private function validatePattern(string $pattern): ?string
126126
{
127-
// the pattern is judged for the analysed PHP and its engine — the
128-
// project crashes on its own machine, whatever the runner takes —
129-
// and the running engine stays a second witness: a construct the
130-
// parser misjudges still reports
131-
$refusal = $this->reader->refusalOfExpression($pattern);
132-
if ($refusal !== null) {
133-
return $refusal;
134-
}
135-
127+
// the running engine keeps its word first: every message a
128+
// baseline ever wrote against stays, and the analysed engine
129+
// speaks only for a pattern the running one compiles and the
130+
// analysed project's engine refuses — the crash the project
131+
// meets on its own machine, invisible here
136132
try {
137133
Strings::match('', $pattern);
138134
} catch (RegexpException $e) {
139135
return $e->getMessage();
140136
}
141137

142-
return null;
138+
return $this->reader->refusalOfExpression($pattern);
143139
}
144140

145141
}

‎tests/PHPStan/Rules/Regexp/RegularExpressionPatternRuleTest.php‎

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,119 +26,127 @@ protected function getRule(): Rule
2626

2727
public function testValidRegexPattern(): void
2828
{
29+
$messagePart = 'alphanumeric or backslash';
30+
if (PHP_VERSION_ID >= 80200) {
31+
$messagePart = 'alphanumeric, backslash, or NUL';
32+
}
33+
if (PHP_VERSION_ID >= 80400) {
34+
$messagePart = 'alphanumeric, backslash, or NUL byte';
35+
}
36+
2937
$this->analyse(
3038
[__DIR__ . '/data/valid-regex-pattern.php'],
3139
[
3240
[
33-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nonok#.',
41+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok', $messagePart),
3442
6,
3543
],
3644
[
37-
'Regex pattern is invalid: Expected ) at end of input (found eof) at offset 1',
45+
'Regex pattern is invalid: Compilation failed: missing closing parenthesis at offset 1 in pattern: ~(~',
3846
7,
3947
],
4048
[
41-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nonok#.',
49+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok', $messagePart),
4250
11,
4351
],
4452
[
45-
'Regex pattern is invalid: Expected ) at end of input (found eof) at offset 1',
53+
'Regex pattern is invalid: Compilation failed: missing closing parenthesis at offset 1 in pattern: ~(~',
4654
12,
4755
],
4856
[
49-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nonok#.',
57+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok', $messagePart),
5058
16,
5159
],
5260
[
53-
'Regex pattern is invalid: Expected ) at end of input (found eof) at offset 1',
61+
'Regex pattern is invalid: Compilation failed: missing closing parenthesis at offset 1 in pattern: ~(~',
5462
17,
5563
],
5664
[
57-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nonok#.',
65+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok', $messagePart),
5866
21,
5967
],
6068
[
61-
'Regex pattern is invalid: Expected ) at end of input (found eof) at offset 1',
69+
'Regex pattern is invalid: Compilation failed: missing closing parenthesis at offset 1 in pattern: ~(~',
6270
22,
6371
],
6472
[
65-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nonok#.',
73+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok', $messagePart),
6674
26,
6775
],
6876
[
69-
'Regex pattern is invalid: Expected ) at end of input (found eof) at offset 1',
77+
'Regex pattern is invalid: Compilation failed: missing closing parenthesis at offset 1 in pattern: ~(~',
7078
27,
7179
],
7280
[
73-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nonok#.',
81+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok', $messagePart),
7482
29,
7583
],
7684
[
77-
'Regex pattern is invalid: Expected ) at end of input (found eof) at offset 1',
85+
'Regex pattern is invalid: Compilation failed: missing closing parenthesis at offset 1 in pattern: ~(~',
7886
29,
7987
],
8088
[
81-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nonok#.',
89+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok', $messagePart),
8290
32,
8391
],
8492
[
85-
'Regex pattern is invalid: Expected ) at end of input (found eof) at offset 1',
93+
'Regex pattern is invalid: Compilation failed: missing closing parenthesis at offset 1 in pattern: ~(~',
8694
33,
8795
],
8896
[
89-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nonok#.',
97+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok', $messagePart),
9098
35,
9199
],
92100
[
93-
'Regex pattern is invalid: Expected ) at end of input (found eof) at offset 1',
101+
'Regex pattern is invalid: Compilation failed: missing closing parenthesis at offset 1 in pattern: ~(~',
94102
35,
95103
],
96104
[
97-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nonok#.',
105+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok', $messagePart),
98106
38,
99107
],
100108
[
101-
'Regex pattern is invalid: Expected ) at end of input (found eof) at offset 1',
109+
'Regex pattern is invalid: Compilation failed: missing closing parenthesis at offset 1 in pattern: ~(~',
102110
39,
103111
],
104112
[
105-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nonok#.',
113+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok', $messagePart),
106114
41,
107115
],
108116
[
109-
'Regex pattern is invalid: Expected ) at end of input (found eof) at offset 1',
117+
'Regex pattern is invalid: Compilation failed: missing closing parenthesis at offset 1 in pattern: ~(~',
110118
41,
111119
],
112120
[
113-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nonok#.',
121+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok', $messagePart),
114122
43,
115123
],
116124
[
117-
'Regex pattern is invalid: Expected ) at end of input (found eof) at offset 1',
125+
'Regex pattern is invalid: Compilation failed: missing closing parenthesis at offset 1 in pattern: ~(~',
118126
43,
119127
],
120128
[
121-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nok(?:.*nok(?:.*)#.',
129+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok(?:.*)', $messagePart),
122130
57,
123131
],
124132
[
125-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nok(?:.*nok(?:.*)#.',
133+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok(?:.*)', $messagePart),
126134
58,
127135
],
128136
[
129-
'Regex pattern is invalid: Expected ) at end of input (found eof) at offset 7',
137+
'Regex pattern is invalid: Compilation failed: missing closing parenthesis at offset 7 in pattern: ~((?:.*)~',
130138
59,
131139
],
132140
[
133-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nok(?:.*)nono#.',
141+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok(?:.*)nono', $messagePart),
134142
61,
135143
],
136144
[
137-
'Regex pattern is invalid: Invalid delimiter "n". Delimiters must not be alphanumeric, backslash, or NUL byte. Try #nok(?:.*)nope#.',
145+
sprintf('Regex pattern is invalid: Delimiter must not be %s in pattern: nok(?:.*)nope', $messagePart),
138146
62,
139147
],
140148
[
141-
'Regex pattern is invalid: Expected ) at end of input (found eof) at offset 7',
149+
'Regex pattern is invalid: Compilation failed: missing closing parenthesis at offset 7 in pattern: ~((?:.*)~',
142150
63,
143151
],
144152
],
@@ -168,7 +176,7 @@ public static function dataArrayShapePatterns(): iterable
168176
__DIR__ . '/../../Analyser/nsrt/preg_match_shapes.php',
169177
[
170178
[
171-
"Regex pattern is invalid: Unknown regex flag(s) found: \"y\", \"z\" at offset 17",
179+
"Regex pattern is invalid: Unknown modifier 'y' in pattern: /(foo)(bar)(baz)/xyz",
172180
124,
173181
],
174182
],

0 commit comments

Comments
 (0)