Skip to content

Commit 718bdf3

Browse files
authored
Merge branch '5.x' into patch-2
2 parents 3496ea1 + 7fe1005 commit 718bdf3

File tree

9 files changed

+79
-37
lines changed

9 files changed

+79
-37
lines changed

dictionaries/ImpureFunctionsList.php

+2
Original file line numberDiff line numberDiff line change
@@ -257,4 +257,6 @@
257257
// xml
258258
'xml_parser_set_option' => true,
259259
'xml_parser_free' => true,
260+
// mail
261+
'mail' => true,
260262
];

src/Psalm/Internal/Codebase/Analyzer.php

-4
Original file line numberDiff line numberDiff line change
@@ -511,10 +511,6 @@ static function (): void {
511511
$this->argument_map[$file_path] = $argument_map;
512512
}
513513
}
514-
515-
if ($pool->didHaveError()) {
516-
exit(1);
517-
}
518514
} else {
519515
$i = 0;
520516

src/Psalm/Internal/Codebase/ClassLikes.php

+6
Original file line numberDiff line numberDiff line change
@@ -1755,6 +1755,12 @@ private function checkMethodReferences(ClassLikeStorage $classlike_storage, Meth
17551755
continue;
17561756
}
17571757

1758+
if ($codebase->classImplements($classlike_storage->name, 'JsonSerializable')
1759+
&& ($method_name === 'jsonserialize')
1760+
) {
1761+
continue;
1762+
}
1763+
17581764
$has_variable_calls = $codebase->analyzer->hasMixedMemberName($method_name)
17591765
|| $codebase->analyzer->hasMixedMemberName(strtolower($classlike_storage->name . '::'));
17601766

src/Psalm/Internal/Codebase/Scanner.php

-4
Original file line numberDiff line numberDiff line change
@@ -417,10 +417,6 @@ function () {
417417
);
418418
}
419419
}
420-
421-
if ($pool->didHaveError()) {
422-
exit(1);
423-
}
424420
} else {
425421
$i = 0;
426422

src/Psalm/Internal/Fork/Pool.php

+24-28
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ final class Pool
8080
/** @var resource[] */
8181
private array $read_streams = [];
8282

83-
private bool $did_have_error = false;
84-
8583
/** @var ?Closure(mixed): void */
8684
private ?Closure $task_done_closure = null;
8785

@@ -297,6 +295,20 @@ private static function streamForChild(array $sockets)
297295
return $for_write;
298296
}
299297

298+
private function killAllChildren(): void
299+
{
300+
foreach ($this->child_pid_list as $child_pid) {
301+
/**
302+
* SIGTERM does not exist on windows
303+
*
304+
* @psalm-suppress UnusedPsalmSuppress
305+
* @psalm-suppress UndefinedConstant
306+
* @psalm-suppress MixedArgument
307+
*/
308+
posix_kill($child_pid, SIGTERM);
309+
}
310+
}
311+
300312
/**
301313
* Read the results that each child process has serialized on their write streams.
302314
* The results are returned in an array, one for each worker. The order of the results
@@ -319,6 +331,7 @@ private function readResultsFromChildren(): array
319331
$content = array_fill_keys(array_keys($streams), '');
320332

321333
$terminationMessages = [];
334+
$done = [];
322335

323336
// Read the data off of all the stream.
324337
while (count($streams) > 0) {
@@ -361,34 +374,25 @@ private function readResultsFromChildren(): array
361374
if ($message instanceof ForkProcessDoneMessage) {
362375
$terminationMessages[] = $message->data;
363376
} elseif ($message instanceof ForkTaskDoneMessage) {
377+
$done[(int)$file] = true;
364378
if ($this->task_done_closure !== null) {
365379
($this->task_done_closure)($message->data);
366380
}
367381
} elseif ($message instanceof ForkProcessErrorMessage) {
368-
// Kill all children
369-
foreach ($this->child_pid_list as $child_pid) {
370-
/**
371-
* SIGTERM does not exist on windows
372-
*
373-
* @psalm-suppress UnusedPsalmSuppress
374-
* @psalm-suppress UndefinedConstant
375-
* @psalm-suppress MixedArgument
376-
*/
377-
posix_kill($child_pid, SIGTERM);
378-
}
382+
$this->killAllChildren();
379383
throw new Exception($message->message);
380384
} else {
381-
error_log('Child should return ForkMessage - response type=' . gettype($message));
382-
$this->did_have_error = true;
385+
$this->killAllChildren();
386+
throw new Exception('Child should return ForkMessage - response type=' . gettype($message));
383387
}
384388
}
385389
}
386390

387391
// If the stream has closed, stop trying to select on it.
388392
if (feof($file)) {
389-
if ($content[(int)$file] !== '') {
390-
error_log('Child did not send full message before closing the connection');
391-
$this->did_have_error = true;
393+
if ($content[(int)$file] !== '' || !isset($done[(int)$file])) {
394+
$this->killAllChildren();
395+
throw new Exception('Child did not send full message before closing the connection');
392396
}
393397

394398
fclose($file);
@@ -450,21 +454,13 @@ public function wait(): array
450454
* @psalm-suppress UndefinedConstant
451455
*/
452456
if ($term_sig !== SIGALRM) {
453-
$this->did_have_error = true;
454-
error_log("Child terminated with return code $return_code and signal $term_sig");
457+
$this->killAllChildren();
458+
throw new Exception("Child terminated with return code $return_code and signal $term_sig");
455459
}
456460
}
457461
}
458462
}
459463

460464
return $content;
461465
}
462-
463-
/**
464-
* Returns true if this had an error, e.g. due to memory limits or due to a child process crashing.
465-
*/
466-
public function didHaveError(): bool
467-
{
468-
return $this->did_have_error;
469-
}
470466
}

src/Psalm/Internal/Fork/PsalmRestarter.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use function array_filter;
88
use function array_merge;
99
use function array_splice;
10+
use function assert;
11+
use function count;
1012
use function extension_loaded;
1113
use function file_get_contents;
1214
use function file_put_contents;
@@ -125,7 +127,7 @@ private static function toBytes(string $value): int
125127
/**
126128
* No type hint to allow xdebug-handler v1 and v2 usage
127129
*
128-
* @param string[] $command
130+
* @param non-empty-list<string> $command
129131
* @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
130132
*/
131133
protected function restart($command): void
@@ -167,6 +169,7 @@ protected function restart($command): void
167169
0,
168170
$additional_options,
169171
);
172+
assert(count($command) > 1);
170173

171174
parent::restart($command);
172175
}

src/Psalm/Internal/Type/Comparator/ScalarTypeComparator.php

+5
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ public static function isContainedBy(
8686
if ($container_type_part instanceof TNonspecificLiteralString
8787
&& ($input_type_part instanceof TLiteralString || $input_type_part instanceof TNonspecificLiteralString)
8888
) {
89+
if ($container_type_part instanceof TNonEmptyNonspecificLiteralString) {
90+
return ($input_type_part instanceof TLiteralString && $input_type_part->value !== '')
91+
|| $input_type_part instanceof TNonEmptyNonspecificLiteralString;
92+
}
93+
8994
return true;
9095
}
9196

tests/Template/ConditionalReturnTypeTest.php

+28
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,34 @@ final class SpecificObject extends stdClass {}
951951
'ignored_issues' => [],
952952
'php_version' => '8.1',
953953
],
954+
'nonEmptyLiteralString' => [
955+
'code' => '<?php
956+
/**
957+
* @param literal-string $string
958+
* @psalm-return ($string is non-empty-literal-string ? string : int)
959+
*/
960+
function getSomething(string $string)
961+
{
962+
if (!$string) {
963+
return 1;
964+
}
965+
966+
return "";
967+
}
968+
969+
/** @var literal-string $literalString */
970+
$literalString;
971+
$something = getSomething($literalString);
972+
/** @var non-empty-literal-string $nonEmptyliteralString */
973+
$nonEmptyliteralString;
974+
$something2 = getSomething($nonEmptyliteralString);
975+
',
976+
'assertions' => [
977+
'$something' => 'int|string',
978+
'$something2' => 'string',
979+
],
980+
'ignored_issues' => [],
981+
],
954982
];
955983
}
956984
}

tests/UnusedCodeTest.php

+10
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,16 @@ function getArg(string $method) : void {
757757
}
758758
}',
759759
],
760+
'ignoreJsonSerialize' => [
761+
'code' => '<?php
762+
class Foo implements JsonSerializable {
763+
public function jsonSerialize() : array {
764+
return [];
765+
}
766+
}
767+
768+
new Foo();',
769+
],
760770
'ignoreSerializerSerialize' => [
761771
'code' => '<?php
762772
class Foo implements Serializable {

0 commit comments

Comments
 (0)