Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e752f28
Parse @pure-unless-callable-is-impure PHPDoc tag
zonuexe Jul 2, 2026
53727b9
Thread pure-unless-callable-is-impure through the reflection layer
zonuexe Jul 2, 2026
7b0f228
Wire pure-unless-callable-is-impure into the analyser
zonuexe Jul 2, 2026
da3fbca
Mark callback-accepting builtins as pure-unless-callable-is-impure
zonuexe Jul 2, 2026
e5f4c50
Add tests for @pure-unless-callable-is-impure
zonuexe Jul 2, 2026
d354666
Fix pure-unless-callable-is-impure parameter flag propagation
zonuexe Jul 2, 2026
3fe1829
Suppress call impure points when pure-unless-callable-is-impure callb…
zonuexe Jul 2, 2026
bd3febf
Fix CI: avoid named arguments, adjust no-effect fixture
zonuexe Jul 2, 2026
03e7ea4
Cover pure-unless-callable-is-impure verdict for maybe-null and maybe…
zonuexe Jul 3, 2026
dbe4eaf
Simplify pure-unless-callable-is-impure metadata reads
zonuexe Jul 3, 2026
498783b
Document the shape of the function metadata array
zonuexe Jul 3, 2026
8d7b559
Mark array_all() and array_any() as pure-unless-callable-is-impure
zonuexe Jul 3, 2026
9bdc1ea
Honor pure-unless-callable-is-impure metadata for stub-reflected func…
zonuexe Jul 3, 2026
4fd839e
Add lint version comment to the PHP 8.4 pure-unless fixture
zonuexe Jul 3, 2026
9d64ec1
Honor @pure-unless-callable-is-impure on methods
zonuexe Jul 5, 2026
d1a253d
Note the two paths that intentionally don't thread pure-unless yet
zonuexe Jul 5, 2026
0a6650a
Honor @pure-unless-callable-is-impure on constructor calls
zonuexe Jul 5, 2026
ae0e28f
Drop the native mixed property type from the pure-unless fixture
zonuexe Jul 5, 2026
1bc68ff
Restructure NewHandler pure-unless branching to match createFromVariant
zonuexe Jul 5, 2026
92e24b2
Cover a union pure-callable|callable argument on a pure-unless constr…
zonuexe Jul 6, 2026
3ec51f1
Return TrinaryLogic from isPureUnlessCallableIsImpureParameter()
zonuexe Jul 7, 2026
33926fe
Check the body of @pure-unless-callable-is-impure functions for purity
zonuexe Jul 7, 2026
160db8c
Report redundant @pure-unless-callable-is-impure on a pure callable
zonuexe Jul 7, 2026
43f61e8
Return TrinaryLogic from getPureUnlessCallableIsImpureParameters()
zonuexe Jul 7, 2026
b6f0d66
Report impure methods overriding @pure-unless-callable-is-impure methods
zonuexe Jul 7, 2026
33f825a
Add a direct unit test for resolvePureUnlessCallableIsImpureVerdict()
zonuexe Jul 7, 2026
f0cf3d4
Make SimpleImpurePointTest a self-contained unit test
zonuexe Jul 7, 2026
4859c2f
Share the pure-unless-callable verdict-to-certainty decision
zonuexe Jul 7, 2026
07722d2
Revert the direct mutation-testing unit test and verdict helper
zonuexe Jul 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 38 additions & 10 deletions bin/functionMetadata_original.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
<?php declare(strict_types = 1);

/**
* Hand-maintained side-effect metadata for built-in functions and methods,
* keyed by lowercase function name or "Class::method". resources/functionMetadata.php
* is generated from this file by bin/generate-function-metadata.php.
*
* Each entry is exactly one of these shapes:
*
* - ['hasSideEffects' => bool]
* false: the call is pure. true: the call has side effects.
* - ['pureUnlessCallableIsImpureParameters' => array<string, true>]
* the call is pure unless one of the listed callable parameters
* (keyed by parameter name) receives an impure callable, e.g. array_map()
* whose only side effects come from its 'callback' argument.
*/

/** @var array<string, array{hasSideEffects: bool}|array{pureUnlessCallableIsImpureParameters: array<string, bool>}> */
return [
'abs' => ['hasSideEffects' => false],
'acos' => ['hasSideEffects' => false],
Expand All @@ -20,6 +36,8 @@
'apcu_key_info' => ['hasSideEffects' => true],
'apcu_sma_info' => ['hasSideEffects' => true],
'apcu_store' => ['hasSideEffects' => true],
'array_all' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'array_any' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'array_change_key_case' => ['hasSideEffects' => false],
'array_chunk' => ['hasSideEffects' => false],
'array_column' => ['hasSideEffects' => false],
Expand All @@ -28,39 +46,44 @@
'array_diff' => ['hasSideEffects' => false],
'array_diff_assoc' => ['hasSideEffects' => false],
'array_diff_key' => ['hasSideEffects' => false],
'array_diff_uassoc' => ['hasSideEffects' => false],
'array_diff_ukey' => ['hasSideEffects' => false],
'array_diff_uassoc' => ['pureUnlessCallableIsImpureParameters' => ['key_compare_func' => true]],
'array_diff_ukey' => ['pureUnlessCallableIsImpureParameters' => ['key_comp_func' => true]],
'array_fill' => ['hasSideEffects' => false],
'array_fill_keys' => ['hasSideEffects' => false],
'array_filter' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'array_find' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'array_find_key' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'array_flip' => ['hasSideEffects' => false],
'array_intersect' => ['hasSideEffects' => false],
'array_intersect_assoc' => ['hasSideEffects' => false],
'array_intersect_key' => ['hasSideEffects' => false],
'array_intersect_uassoc' => ['hasSideEffects' => false],
'array_intersect_ukey' => ['hasSideEffects' => false],
'array_intersect_uassoc' => ['pureUnlessCallableIsImpureParameters' => ['key_compare_func' => true]],
'array_intersect_ukey' => ['pureUnlessCallableIsImpureParameters' => ['key_compare_func' => true]],
'array_key_first' => ['hasSideEffects' => false],
'array_key_last' => ['hasSideEffects' => false],
'array_key_exists' => ['hasSideEffects' => false],
'array_keys' => ['hasSideEffects' => false],
'array_map' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'array_merge' => ['hasSideEffects' => false],
'array_merge_recursive' => ['hasSideEffects' => false],
'array_pad' => ['hasSideEffects' => false],
'array_pop' => ['hasSideEffects' => true],
'array_product' => ['hasSideEffects' => false],
'array_push' => ['hasSideEffects' => true],
'array_rand' => ['hasSideEffects' => false],
'array_reduce' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'array_replace' => ['hasSideEffects' => false],
'array_replace_recursive' => ['hasSideEffects' => false],
'array_reverse' => ['hasSideEffects' => false],
'array_shift' => ['hasSideEffects' => true],
'array_slice' => ['hasSideEffects' => false],
'array_sum' => ['hasSideEffects' => false],
'array_udiff' => ['hasSideEffects' => false],
'array_udiff_assoc' => ['hasSideEffects' => false],
'array_udiff_uassoc' => ['hasSideEffects' => false],
'array_uintersect' => ['hasSideEffects' => false],
'array_uintersect_assoc' => ['hasSideEffects' => false],
'array_uintersect_uassoc' => ['hasSideEffects' => false],
'array_udiff' => ['pureUnlessCallableIsImpureParameters' => ['data_comp_func' => true]],
'array_udiff_assoc' => ['pureUnlessCallableIsImpureParameters' => ['key_comp_func' => true]],
'array_udiff_uassoc' => ['pureUnlessCallableIsImpureParameters' => ['data_comp_func' => true, 'key_comp_func' => true]],
'array_uintersect' => ['pureUnlessCallableIsImpureParameters' => ['data_compare_func' => true]],
'array_uintersect_assoc' => ['pureUnlessCallableIsImpureParameters' => ['data_compare_func' => true]],
'array_uintersect_uassoc' => ['pureUnlessCallableIsImpureParameters' => ['data_compare_func' => true, 'key_compare_func' => true]],
'array_unique' => ['hasSideEffects' => false],
'array_unshift' => ['hasSideEffects' => true],
'array_values' => ['hasSideEffects' => false],
Expand All @@ -81,6 +104,8 @@
'bcround' => ['hasSideEffects' => false],
'bcfloor' => ['hasSideEffects' => false],
'bcceil' => ['hasSideEffects' => false],
'call_user_func' => ['pureUnlessCallableIsImpureParameters' => ['function' => true]],
'call_user_func_array' => ['pureUnlessCallableIsImpureParameters' => ['function' => true]],
// continue functionMap.php, line 424
'chgrp' => ['hasSideEffects' => true],
'chmod' => ['hasSideEffects' => true],
Expand All @@ -97,6 +122,8 @@
'file_put_contents' => ['hasSideEffects' => true],
'flock' => ['hasSideEffects' => true],
'fopen' => ['hasSideEffects' => true],
'forward_static_call' => ['pureUnlessCallableIsImpureParameters' => ['function' => true]],
'forward_static_call_array' => ['pureUnlessCallableIsImpureParameters' => ['function' => true]],
'fpassthru' => ['hasSideEffects' => true],
'fputcsv' => ['hasSideEffects' => true],
'fputs' => ['hasSideEffects' => true],
Expand Down Expand Up @@ -237,6 +264,7 @@
'output_reset_rewrite_vars' => ['hasSideEffects' => true],
'pclose' => ['hasSideEffects' => true],
'popen' => ['hasSideEffects' => true],
'preg_replace_callback' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'readfile' => ['hasSideEffects' => true],
'rename' => ['hasSideEffects' => true],
'rewind' => ['hasSideEffects' => true],
Expand Down
44 changes: 40 additions & 4 deletions bin/generate-function-metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,21 @@ public function enterNode(Node $node)
);
}

/** @var array<string, array{hasSideEffects: bool}> $metadata */
/** @var array<string, array{hasSideEffects?: bool, pureUnlessCallableIsImpureParameters?: array<string, bool>}> $metadata */
$metadata = require __DIR__ . '/functionMetadata_original.php';
foreach ($visitor->functions as $functionName) {
if (array_key_exists($functionName, $metadata)) {
if ($metadata[$functionName]['hasSideEffects']) {
if (isset($metadata[$functionName]['hasSideEffects']) && $metadata[$functionName]['hasSideEffects']) {
throw new ShouldNotHappenException($functionName);
}

if (isset($metadata[$functionName]['pureUnlessCallableIsImpureParameters'])) {
$metadata[$functionName] = [
'pureUnlessCallableIsImpureParameters' => $metadata[$functionName]['pureUnlessCallableIsImpureParameters'],
];

continue;
}
}
$metadata[$functionName] = ['hasSideEffects' => false];
}
Expand Down Expand Up @@ -177,19 +185,47 @@ public function enterNode(Node $node)
* 2) Contribute the functions that have 'hasSideEffects' => true as a modification to bin/functionMetadata_original.php.
* 3) Contribute the #[Pure] functions without side effects to https://github.com/JetBrains/phpstorm-stubs
* 4) Once the PR from 3) is merged, please update the package here and run ./bin/generate-function-metadata.php.
*
* The array is keyed by lowercase function name or "Class::method". Each entry is
* exactly one of:
* - ['hasSideEffects' => bool] - false: pure, true: has side effects.
* - ['pureUnlessCallableIsImpureParameters' => array<string, true>] - pure unless
* one of the listed callable parameters (keyed by parameter name) receives an
* impure callable, e.g. array_map()'s 'callback'.
*/

/** @var array<string, array{hasSideEffects: bool}|array{pureUnlessCallableIsImpureParameters: array<string, bool>}> */
return [
%s
];
php;
$content = '';
$escape = static fn (mixed $value): string => var_export($value, true);
$encodeHasSideEffects = static fn (array $meta) => [$escape('hasSideEffects'), $escape($meta['hasSideEffects'])];
$encodePureUnlessCallableIsImpureParameters = static fn (array $meta) => [
$escape('pureUnlessCallableIsImpureParameters'),
sprintf(
'[%s]',
implode(
' ,',
array_map(
static fn ($key, $param) => sprintf('%s => %s', $escape($key), $escape($param)),
array_keys($meta['pureUnlessCallableIsImpureParameters']),
$meta['pureUnlessCallableIsImpureParameters'],
),
),
),
];

foreach ($metadata as $name => $meta) {
$content .= sprintf(
"\t%s => [%s => %s],\n",
var_export($name, true),
var_export('hasSideEffects', true),
var_export($meta['hasSideEffects'], true),
...match (true) {
isset($meta['hasSideEffects']) => $encodeHasSideEffects($meta),
isset($meta['pureUnlessCallableIsImpureParameters']) => $encodePureUnlessCallableIsImpureParameters($meta),
default => throw new ShouldNotHappenException($escape($meta)),
},
);
}

Expand Down
42 changes: 31 additions & 11 deletions resources/functionMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,16 @@
* 2) Contribute the functions that have 'hasSideEffects' => true as a modification to bin/functionMetadata_original.php.
* 3) Contribute the #[Pure] functions without side effects to https://github.com/JetBrains/phpstorm-stubs
* 4) Once the PR from 3) is merged, please update the package here and run ./bin/generate-function-metadata.php.
*
* The array is keyed by lowercase function name or "Class::method". Each entry is
* exactly one of:
* - ['hasSideEffects' => bool] - false: pure, true: has side effects.
* - ['pureUnlessCallableIsImpureParameters' => array<string, true>] - pure unless
* one of the listed callable parameters (keyed by parameter name) receives an
* impure callable, e.g. array_map()'s 'callback'.
*/

/** @var array<string, array{hasSideEffects: bool}|array{pureUnlessCallableIsImpureParameters: array<string, bool>}> */
return [
'BackedEnum::from' => ['hasSideEffects' => false],
'BackedEnum::tryFrom' => ['hasSideEffects' => false],
Expand Down Expand Up @@ -725,6 +733,8 @@
'apcu_key_info' => ['hasSideEffects' => true],
'apcu_sma_info' => ['hasSideEffects' => true],
'apcu_store' => ['hasSideEffects' => true],
'array_all' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'array_any' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'array_change_key_case' => ['hasSideEffects' => false],
'array_chunk' => ['hasSideEffects' => false],
'array_column' => ['hasSideEffects' => false],
Expand All @@ -733,43 +743,48 @@
'array_diff' => ['hasSideEffects' => false],
'array_diff_assoc' => ['hasSideEffects' => false],
'array_diff_key' => ['hasSideEffects' => false],
'array_diff_uassoc' => ['hasSideEffects' => false],
'array_diff_ukey' => ['hasSideEffects' => false],
'array_diff_uassoc' => ['pureUnlessCallableIsImpureParameters' => ['key_compare_func' => true]],
Comment thread
staabm marked this conversation as resolved.
'array_diff_ukey' => ['pureUnlessCallableIsImpureParameters' => ['key_comp_func' => true]],
'array_fill' => ['hasSideEffects' => false],
'array_fill_keys' => ['hasSideEffects' => false],
'array_filter' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'array_find' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'array_find_key' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'array_first' => ['hasSideEffects' => false],
'array_flip' => ['hasSideEffects' => false],
'array_intersect' => ['hasSideEffects' => false],
'array_intersect_assoc' => ['hasSideEffects' => false],
'array_intersect_key' => ['hasSideEffects' => false],
'array_intersect_uassoc' => ['hasSideEffects' => false],
'array_intersect_ukey' => ['hasSideEffects' => false],
'array_intersect_uassoc' => ['pureUnlessCallableIsImpureParameters' => ['key_compare_func' => true]],
'array_intersect_ukey' => ['pureUnlessCallableIsImpureParameters' => ['key_compare_func' => true]],
'array_is_list' => ['hasSideEffects' => false],
'array_key_exists' => ['hasSideEffects' => false],
'array_key_first' => ['hasSideEffects' => false],
'array_key_last' => ['hasSideEffects' => false],
'array_keys' => ['hasSideEffects' => false],
'array_last' => ['hasSideEffects' => false],
'array_map' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'array_merge' => ['hasSideEffects' => false],
'array_merge_recursive' => ['hasSideEffects' => false],
'array_pad' => ['hasSideEffects' => false],
'array_pop' => ['hasSideEffects' => true],
'array_product' => ['hasSideEffects' => false],
'array_push' => ['hasSideEffects' => true],
'array_rand' => ['hasSideEffects' => false],
'array_reduce' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'array_replace' => ['hasSideEffects' => false],
'array_replace_recursive' => ['hasSideEffects' => false],
'array_reverse' => ['hasSideEffects' => false],
'array_search' => ['hasSideEffects' => false],
'array_shift' => ['hasSideEffects' => true],
'array_slice' => ['hasSideEffects' => false],
'array_sum' => ['hasSideEffects' => false],
'array_udiff' => ['hasSideEffects' => false],
'array_udiff_assoc' => ['hasSideEffects' => false],
'array_udiff_uassoc' => ['hasSideEffects' => false],
'array_uintersect' => ['hasSideEffects' => false],
'array_uintersect_assoc' => ['hasSideEffects' => false],
'array_uintersect_uassoc' => ['hasSideEffects' => false],
'array_udiff' => ['pureUnlessCallableIsImpureParameters' => ['data_comp_func' => true]],
'array_udiff_assoc' => ['pureUnlessCallableIsImpureParameters' => ['key_comp_func' => true]],
'array_udiff_uassoc' => ['pureUnlessCallableIsImpureParameters' => ['data_comp_func' => true ,'key_comp_func' => true]],
'array_uintersect' => ['pureUnlessCallableIsImpureParameters' => ['data_compare_func' => true]],
'array_uintersect_assoc' => ['pureUnlessCallableIsImpureParameters' => ['data_compare_func' => true]],
'array_uintersect_uassoc' => ['pureUnlessCallableIsImpureParameters' => ['data_compare_func' => true ,'key_compare_func' => true]],
'array_unique' => ['hasSideEffects' => false],
'array_unshift' => ['hasSideEffects' => true],
'array_values' => ['hasSideEffects' => false],
Expand Down Expand Up @@ -803,6 +818,8 @@
'bzerror' => ['hasSideEffects' => false],
'bzerrstr' => ['hasSideEffects' => false],
'bzopen' => ['hasSideEffects' => false],
'call_user_func' => ['pureUnlessCallableIsImpureParameters' => ['function' => true]],
'call_user_func_array' => ['pureUnlessCallableIsImpureParameters' => ['function' => true]],
'ceil' => ['hasSideEffects' => false],
'checkdate' => ['hasSideEffects' => false],
'checkdnsrr' => ['hasSideEffects' => false],
Expand Down Expand Up @@ -954,6 +971,8 @@
'fmod' => ['hasSideEffects' => false],
'fnmatch' => ['hasSideEffects' => true],
'fopen' => ['hasSideEffects' => true],
'forward_static_call' => ['pureUnlessCallableIsImpureParameters' => ['function' => true]],
'forward_static_call_array' => ['pureUnlessCallableIsImpureParameters' => ['function' => true]],
'fpassthru' => ['hasSideEffects' => true],
'fputcsv' => ['hasSideEffects' => true],
'fputs' => ['hasSideEffects' => true],
Expand Down Expand Up @@ -1616,6 +1635,7 @@
'preg_last_error' => ['hasSideEffects' => true],
'preg_last_error_msg' => ['hasSideEffects' => true],
'preg_quote' => ['hasSideEffects' => false],
'preg_replace_callback' => ['pureUnlessCallableIsImpureParameters' => ['callback' => true]],
'preg_split' => ['hasSideEffects' => false],
'property_exists' => ['hasSideEffects' => false],
'quoted_printable_decode' => ['hasSideEffects' => false],
Expand Down Expand Up @@ -1757,4 +1777,4 @@
'zlib_encode' => ['hasSideEffects' => false],
'zlib_get_coding_type' => ['hasSideEffects' => false],

];
];
8 changes: 8 additions & 0 deletions src/Analyser/ExprHandler/NewHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use PHPStan\DependencyInjection\Type\DynamicThrowTypeExtensionProvider;
use PHPStan\Node\MethodReturnStatementsNode;
use PHPStan\Parser\NewAssignedToPropertyVisitor;
use PHPStan\Reflection\Callables\SimpleImpurePoint;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\Dummy\DummyConstructorReflection;
use PHPStan\Reflection\ExtendedParametersAcceptor;
Expand Down Expand Up @@ -258,6 +259,13 @@
if ($constructorReflection !== null) {
if (!$constructorReflection->hasSideEffects()->no()) {
$certain = $constructorReflection->isPure()->no();
$verdict = SimpleImpurePoint::resolvePureUnlessCallableIsImpureVerdict($parametersAcceptor, $scope, $expr->getArgs());
if ($verdict !== null && $verdict->yes()) {

Check warning on line 263 in src/Analyser/ExprHandler/NewHandler.php

View workflow job for this annotation

GitHub Actions / Mutation Testing (8.4, ubuntu-latest)

Escaped Mutant for Mutator "PHPStan\Infection\TrinaryLogicMutator": @@ @@ if (!$constructorReflection->hasSideEffects()->no()) { $certain = $constructorReflection->isPure()->no(); $verdict = SimpleImpurePoint::resolvePureUnlessCallableIsImpureVerdict($parametersAcceptor, $scope, $expr->getArgs()); - if ($verdict !== null && $verdict->yes()) { + if ($verdict !== null && !$verdict->no()) { return [$constructorReflection, $classReflection, $parametersAcceptor, $impurePoints]; } if ($verdict !== null && $verdict->no()) {
return [$constructorReflection, $classReflection, $parametersAcceptor, $impurePoints];
}
if ($verdict !== null && $verdict->no()) {

Check warning on line 266 in src/Analyser/ExprHandler/NewHandler.php

View workflow job for this annotation

GitHub Actions / Mutation Testing (8.4, ubuntu-latest)

Escaped Mutant for Mutator "PHPStan\Infection\TrinaryLogicMutator": @@ @@ if ($verdict !== null && $verdict->yes()) { return [$constructorReflection, $classReflection, $parametersAcceptor, $impurePoints]; } - if ($verdict !== null && $verdict->no()) { + if ($verdict !== null && !$verdict->yes()) { $certain = true; } $impurePoints[] = new ImpurePoint(
$certain = true;
}
$impurePoints[] = new ImpurePoint(
$scope,
$expr,
Expand Down
7 changes: 7 additions & 0 deletions src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -1555,6 +1555,7 @@ public function enterTrait(ClassReflection $traitReflection): self
* @param Type[] $parameterOutTypes
* @param array<string, bool> $immediatelyInvokedCallableParameters
* @param array<string, Type> $phpDocClosureThisTypeParameters
* @param array<string, bool> $phpDocPureUnlessCallableIsImpureParameters
*/
public function enterClassMethod(
Node\Stmt\ClassMethod $classMethod,
Expand All @@ -1576,6 +1577,7 @@ public function enterClassMethod(
array $phpDocClosureThisTypeParameters = [],
bool $isConstructor = false,
?ResolvedPhpDocBlock $resolvedPhpDocBlock = null,
array $phpDocPureUnlessCallableIsImpureParameters = [],
): self
{
if (!$this->isInClass()) {
Expand Down Expand Up @@ -1611,6 +1613,7 @@ public function enterClassMethod(
array_map(fn (Type $type): Type => $this->transformStaticType(TemplateTypeHelper::toArgument($type)), $phpDocClosureThisTypeParameters),
$isConstructor,
$this->attributeReflectionFactory->fromAttrGroups($classMethod->attrGroups, InitializerExprContext::fromStubParameter($this->getClassReflection()->getName(), $this->getFile(), $classMethod)),
$phpDocPureUnlessCallableIsImpureParameters,
),
!$classMethod->isStatic(),
);
Expand Down Expand Up @@ -1700,6 +1703,7 @@ public function enterPropertyHook(
[],
false,
$this->attributeReflectionFactory->fromAttrGroups($hook->attrGroups, InitializerExprContext::fromStubParameter($this->getClassReflection()->getName(), $this->getFile(), $hook)),
[],
),
true,
);
Expand Down Expand Up @@ -1776,6 +1780,7 @@ private function getParameterAttributes(ClassMethod|Function_|PropertyHook $func
* @param Type[] $parameterOutTypes
* @param array<string, bool> $immediatelyInvokedCallableParameters
* @param array<string, Type> $phpDocClosureThisTypeParameters
* @param array<string, bool> $pureUnlessCallableIsImpureParameters
*/
public function enterFunction(
Node\Stmt\Function_ $function,
Expand All @@ -1793,6 +1798,7 @@ public function enterFunction(
array $parameterOutTypes = [],
array $immediatelyInvokedCallableParameters = [],
array $phpDocClosureThisTypeParameters = [],
array $pureUnlessCallableIsImpureParameters = [],
): self
{
return $this->enterFunctionLike(
Expand All @@ -1818,6 +1824,7 @@ public function enterFunction(
$immediatelyInvokedCallableParameters,
$phpDocClosureThisTypeParameters,
$this->attributeReflectionFactory->fromAttrGroups($function->attrGroups, InitializerExprContext::fromStubParameter(null, $this->getFile(), $function)),
$pureUnlessCallableIsImpureParameters,
),
false,
);
Expand Down
Loading
Loading