Skip to content

Commit 7046180

Browse files
committed
Merge remote-tracking branch 'origin/1.12.x' into 2.0.x
2 parents 76b0a7d + 70448ad commit 7046180

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+864
-276
lines changed

build/baseline-8.0.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
parameters:
22
ignoreErrors:
33
-
4-
message: "#^Strict comparison using \\=\\=\\= between array and false will always evaluate to false\\.$#"
4+
message: "#^Strict comparison using \\=\\=\\= between list<callable\\(string\\): void> and false will always evaluate to false\\.$#"
55
count: 1
66
path: ../src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php
77

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
parameters:
22
ignoreErrors:
33
-
4-
message: "#^PHPDoc tag @var with type array\\<callable\\>\\|false is not subtype of native type array\\.$#"
4+
message: "#^PHPDoc tag @var with type list\\<callable\\(string\\): void\\>\\|false is not subtype of native type list\\<callable\\(string\\): void\\>\\.$#"
55
count: 2
66
path: ../src/Command/CommandHelper.php
Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
parameters:
22
ignoreErrors:
3-
-
4-
message: "#^PHPDoc tag @var with type array\\<callable\\(\\)\\: mixed\\>\\|false is not subtype of native type list\\<callable\\(string\\)\\: void\\>\\|false\\.$#"
5-
count: 2
6-
path: ../src/Command/CommandHelper.php
7-
83
-
94
message: '#^Parameter \#1 \$array \(list<PHPStan\\Type\\Type>\) of array_values is already a list, call has no effect\.$#'
105
path: ../src/Type/TypeCombinator.php

phpstan-baseline.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ parameters:
882882
-
883883
message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#'
884884
identifier: phpstanApi.instanceofType
885-
count: 7
885+
count: 9
886886
path: src/Type/Constant/ConstantArrayType.php
887887

888888
-

resources/RegexGrammar.pp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,16 @@
4242
//
4343

4444
// Character classes.
45+
// tokens suffixed with "fc_" are the same as without such suffix but followed by "class:_class"
46+
%token negative_class_fc_ \[\^(?=\]) -> class_fc
47+
%token class_fc_ \[(?=\]) -> class_fc
48+
%token class_fc:_class \] -> class
4549
%token negative_class_ \[\^ -> class
4650
%token class_ \[ -> class
4751
%token class:posix_class \[:\^?[a-z]+:\]
4852
%token class:class_ \[
49-
%token class:_class_literal (?<=[^\\]\[|[^\\]\[\^)\]
5053
%token class:_class \] -> default
5154
%token class:range \-
52-
%token class:escaped_end_class \\\]
5355
// taken over from literals but class:character has \b support on top (backspace in character classes)
5456
%token class:character \\([aefnrtb]|c[\x00-\x7f])
5557
%token class:dynamic_character \\([0-7]{3}|x[0-9a-zA-Z]{2}|x{[0-9a-zA-Z]+})
@@ -58,7 +60,8 @@
5860

5961
// Internal options.
6062
// See https://www.regular-expressions.info/refmodifiers.html
61-
%token internal_option \(\?([imsxnJUX^]|xx)?-?([imsxnJUX^]|xx)\)
63+
// and https://www.php.net/manual/en/regexp.reference.internal-options.php
64+
%token internal_option \(\?[imsxnJUX^]*-?[imsxnJUX^]+\)
6265

6366
// Lookahead and lookbehind assertions.
6467
%token lookahead_ \(\?=
@@ -88,7 +91,7 @@
8891
%token nc:_named_capturing > -> default
8992
%token nc:capturing_name .+?(?=(?<!\\)>)
9093
%token non_capturing_ \(\?:
91-
%token non_capturing_internal_option \(\?([imsxnJUX^]|xx)?-?([imsxnJUX^]|xx):
94+
%token non_capturing_internal_option \(\?[imsxnJUX^]*-?[imsxnJUX^]+:
9295
%token non_capturing_reset_ \(\?\|
9396
%token atomic_group_ \(\?>
9497
%token capturing_ \(
@@ -177,10 +180,14 @@
177180

178181
#class:
179182
(
180-
::negative_class_:: #negativeclass
183+
::negative_class_fc_:: #negativeclass
184+
<_class>
185+
| ::class_fc_::
186+
<_class>
187+
| ::negative_class_:: #negativeclass
181188
| ::class_::
182189
)
183-
( <range> | <_class_literal> )? ( <posix_class> | <class_> | range() | literal() | <escaped_end_class> )* <range>?
190+
<range>? ( <posix_class> | <class_> | range() <range>? | literal() )* <range>?
184191
::_class::
185192

186193
#range:

resources/functionMap.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,7 +1497,7 @@
14971497
'curl_multi_close' => ['void', 'mh'=>'resource'],
14981498
'curl_multi_errno' => ['int', 'mh'=>'resource'],
14991499
'curl_multi_exec' => ['int', 'mh'=>'resource', '&w_still_running'=>'int'],
1500-
'curl_multi_getcontent' => ['string', 'ch'=>'resource'],
1500+
'curl_multi_getcontent' => ['string|null', 'ch'=>'resource'],
15011501
'curl_multi_info_read' => ['array|false', 'mh'=>'resource', '&w_msgs_in_queue='=>'int'],
15021502
'curl_multi_init' => ['resource'],
15031503
'curl_multi_remove_handle' => ['int', 'mh'=>'resource', 'ch'=>'resource'],
@@ -11556,7 +11556,7 @@
1155611556
'SplFileInfo::getMTime' => ['__benevolent<int|false>'],
1155711557
'SplFileInfo::getOwner' => ['__benevolent<int|false>'],
1155811558
'SplFileInfo::getPath' => ['string'],
11559-
'SplFileInfo::getPathInfo' => ['SplFileInfo', 'class_name='=>'string'],
11559+
'SplFileInfo::getPathInfo' => ['__benevolent<SplFileInfo|null>', 'class_name='=>'string'],
1156011560
'SplFileInfo::getPathname' => ['string'],
1156111561
'SplFileInfo::getPerms' => ['__benevolent<int|false>'],
1156211562
'SplFileInfo::getRealPath' => ['__benevolent<string|false>'],
@@ -12606,7 +12606,7 @@
1260612606
'timezone_version_get' => ['string'],
1260712607
'tmpfile' => ['__benevolent<resource|false>'],
1260812608
'token_get_all' => ['list<string|array{0:int,1:string,2:int}>', 'source'=>'string', 'flags='=>'int'],
12609-
'token_name' => ['string', 'type'=>'int'],
12609+
'token_name' => ['non-empty-string', 'type'=>'int'],
1261012610
'TokyoTyrant::__construct' => ['void', 'host='=>'string', 'port='=>'int', 'options='=>'array'],
1261112611
'TokyoTyrant::add' => ['int|float', 'key'=>'string', 'increment'=>'float', 'type='=>'int'],
1261212612
'TokyoTyrant::connect' => ['TokyoTyrant', 'host'=>'string', 'port='=>'int', 'options='=>'array'],

resources/functionMap_php80delta.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
'socket_addrinfo_lookup' => ['AddressInfo[]', 'node'=>'string', 'service='=>'mixed', 'hints='=>'array'],
103103
'socket_select' => ['int|false', '&w_read'=>'Socket[]|null', '&w_write'=>'Socket[]|null', '&w_except'=>'Socket[]|null', 'seconds'=>'int|null', 'microseconds='=>'int'],
104104
'sodium_crypto_aead_chacha20poly1305_ietf_decrypt' => ['string|false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'],
105+
'spl_autoload_functions' => ['list<callable(string):void>'],
105106
'str_contains' => ['bool', 'haystack'=>'string', 'needle'=>'string'],
106107
'str_split' => ['non-empty-list<string>', 'str'=>'string', 'split_length='=>'positive-int'],
107108
'str_ends_with' => ['bool', 'haystack'=>'string', 'needle'=>'string'],

src/Command/CommandHelper.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ public static function begin(
163163
$currentWorkingDirectoryFileHelper = new FileHelper($currentWorkingDirectory);
164164
$currentWorkingDirectory = $currentWorkingDirectoryFileHelper->getWorkingDirectory();
165165

166-
/** @var array<callable>|false $autoloadFunctionsBefore */
166+
/** @var list<callable(string): void>|false $autoloadFunctionsBefore */
167167
$autoloadFunctionsBefore = spl_autoload_functions();
168168

169169
if ($autoloadFile !== null) {
@@ -458,7 +458,7 @@ public static function begin(
458458
self::executeBootstrapFile($bootstrapFileFromArray, $container, $errorOutput, $debugEnabled);
459459
}
460460

461-
/** @var array<callable>|false $autoloadFunctionsAfter */
461+
/** @var list<callable(string): void>|false $autoloadFunctionsAfter */
462462
$autoloadFunctionsAfter = spl_autoload_functions();
463463

464464
if ($autoloadFunctionsBefore !== false && $autoloadFunctionsAfter !== false) {

src/Rules/DeadCode/UnusedPrivateMethodRule.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,16 @@ public function processNode(Node $node, Scope $scope): array
8484
$methodNameType = $callScope->getType($methodCallNode->name);
8585
$strings = $methodNameType->getConstantStrings();
8686
if (count($strings) === 0) {
87-
return [];
87+
// handle subtractions of a dynamic method call
88+
foreach ($methods as $lowerMethodName => $method) {
89+
if ((new ConstantStringType($method->getNode()->name->toString()))->isSuperTypeOf($methodNameType)->no()) {
90+
continue;
91+
}
92+
93+
unset($methods[$lowerMethodName]);
94+
}
95+
96+
continue;
8897
}
8998

9099
$methodNames = array_map(static fn (ConstantStringType $type): string => $type->getValue(), $strings);

src/Rules/DeadCode/UnusedPrivatePropertyRule.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,16 @@ public function processNode(Node $node, Scope $scope): array
120120
$propertyNameType = $usage->getScope()->getType($fetch->name);
121121
$strings = $propertyNameType->getConstantStrings();
122122
if (count($strings) === 0) {
123-
return [];
123+
// handle subtractions of a dynamic property fetch
124+
foreach ($properties as $propertyName => $data) {
125+
if ((new ConstantStringType($propertyName))->isSuperTypeOf($propertyNameType)->no()) {
126+
continue;
127+
}
128+
129+
unset($properties[$propertyName]);
130+
}
131+
132+
continue;
124133
}
125134

126135
$propertyNames = array_map(static fn (ConstantStringType $type): string => $type->getValue(), $strings);

src/Type/Accessory/AccessoryArrayListType.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,19 @@ public function shuffleArray(): Type
236236
return $this;
237237
}
238238

239+
public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys): Type
240+
{
241+
if ($preserveKeys->no()) {
242+
return $this;
243+
}
244+
245+
if ((new ConstantIntegerType(0))->isSuperTypeOf($offsetType)->yes()) {
246+
return $this;
247+
}
248+
249+
return new MixedType();
250+
}
251+
239252
public function isIterable(): TrinaryLogic
240253
{
241254
return TrinaryLogic::createYes();

src/Type/Accessory/HasOffsetType.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use PHPStan\Type\Constant\ConstantIntegerType;
1313
use PHPStan\Type\Constant\ConstantStringType;
1414
use PHPStan\Type\ErrorType;
15+
use PHPStan\Type\IntegerRangeType;
1516
use PHPStan\Type\IntersectionType;
1617
use PHPStan\Type\MixedType;
1718
use PHPStan\Type\ObjectWithoutClassType;
@@ -25,6 +26,7 @@
2526
use PHPStan\Type\Traits\TruthyBooleanTypeTrait;
2627
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
2728
use PHPStan\Type\Type;
29+
use PHPStan\Type\TypeCombinator;
2830
use PHPStan\Type\UnionType;
2931
use PHPStan\Type\VerbosityLevel;
3032
use function sprintf;
@@ -197,6 +199,20 @@ public function shuffleArray(): Type
197199
return new NonEmptyArrayType();
198200
}
199201

202+
public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys): Type
203+
{
204+
if (
205+
$this->offsetType->isSuperTypeOf($offsetType)->yes()
206+
&& ($lengthType->isNull()->yes() || IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($lengthType)->yes())
207+
) {
208+
return $preserveKeys->yes()
209+
? TypeCombinator::intersect($this, new NonEmptyArrayType())
210+
: new NonEmptyArrayType();
211+
}
212+
213+
return new MixedType();
214+
}
215+
200216
public function isIterableAtLeastOnce(): TrinaryLogic
201217
{
202218
return TrinaryLogic::createYes();

src/Type/Accessory/HasOffsetValueType.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPStan\Type\Constant\ConstantStringType;
1515
use PHPStan\Type\ConstantScalarType;
1616
use PHPStan\Type\ErrorType;
17+
use PHPStan\Type\IntegerRangeType;
1718
use PHPStan\Type\IntersectionType;
1819
use PHPStan\Type\MixedType;
1920
use PHPStan\Type\ObjectWithoutClassType;
@@ -27,6 +28,7 @@
2728
use PHPStan\Type\Traits\TruthyBooleanTypeTrait;
2829
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
2930
use PHPStan\Type\Type;
31+
use PHPStan\Type\TypeCombinator;
3032
use PHPStan\Type\UnionType;
3133
use PHPStan\Type\VerbosityLevel;
3234
use function sprintf;
@@ -254,6 +256,20 @@ public function shuffleArray(): Type
254256
return new NonEmptyArrayType();
255257
}
256258

259+
public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys): Type
260+
{
261+
if (
262+
$this->offsetType->isSuperTypeOf($offsetType)->yes()
263+
&& ($lengthType->isNull()->yes() || IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($lengthType)->yes())
264+
) {
265+
return $preserveKeys->yes()
266+
? TypeCombinator::intersect($this, new NonEmptyArrayType())
267+
: new NonEmptyArrayType();
268+
}
269+
270+
return new MixedType();
271+
}
272+
257273
public function isIterableAtLeastOnce(): TrinaryLogic
258274
{
259275
return TrinaryLogic::createYes();

src/Type/Accessory/NonEmptyArrayType.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,18 @@ public function shuffleArray(): Type
214214
return $this;
215215
}
216216

217+
public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys): Type
218+
{
219+
if (
220+
(new ConstantIntegerType(0))->isSuperTypeOf($offsetType)->yes()
221+
&& ($lengthType->isNull()->yes() || IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($lengthType)->yes())
222+
) {
223+
return $this;
224+
}
225+
226+
return new MixedType();
227+
}
228+
217229
public function isIterable(): TrinaryLogic
218230
{
219231
return TrinaryLogic::createYes();

src/Type/Accessory/OversizedArrayType.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ public function shuffleArray(): Type
210210
return $this;
211211
}
212212

213+
public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys): Type
214+
{
215+
return $this;
216+
}
217+
213218
public function isIterable(): TrinaryLogic
214219
{
215220
return TrinaryLogic::createYes();

src/Type/ArrayType.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,11 @@ public function shuffleArray(): Type
421421
return TypeCombinator::intersect(new self(new IntegerType(), $this->itemType), new AccessoryArrayListType());
422422
}
423423

424+
public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys): Type
425+
{
426+
return $this;
427+
}
428+
424429
public function isCallable(): TrinaryLogic
425430
{
426431
return TrinaryLogic::createMaybe()->and($this->itemType->isString());

src/Type/BenevolentUnionType.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ class BenevolentUnionType extends UnionType
1414
* @api
1515
* @param Type[] $types
1616
*/
17-
public function __construct(array $types)
17+
public function __construct(array $types, bool $normalized = false)
1818
{
19-
parent::__construct($types);
19+
parent::__construct($types, $normalized);
2020
}
2121

2222
public function describe(VerbosityLevel $level): string

0 commit comments

Comments
 (0)