Skip to content

Commit e69a630

Browse files
bbralamglaman
andauthored
Fix false positive when deprecation helper is inside functioncall (#989)
* chore: DeprecationHelper can now also appear inside a function call. This should be handled by the DeprecationHelperScope * test: add deep stack traversal test for backwardsCompatibleCall --------- Co-authored-by: Matt Glaman <nmd.matt@gmail.com>
1 parent b5b92be commit e69a630

2 files changed

Lines changed: 29 additions & 14 deletions

File tree

src/DeprecatedScope/DeprecationHelperScope.php

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use PHPStan\Reflection\MethodReflection;
1010
use PHPStan\Rules\Deprecations\DeprecatedScopeResolver;
1111
use function class_exists;
12-
use function count;
1312

1413
final class DeprecationHelperScope implements DeprecatedScopeResolver
1514
{
@@ -18,19 +17,19 @@ public function isScopeDeprecated(Scope $scope): bool
1817
if (!class_exists(DeprecationHelper::class)) {
1918
return false;
2019
}
21-
$callStack = $scope->getFunctionCallStackWithParameters();
22-
if (count($callStack) === 0) {
23-
return false;
24-
}
25-
[$function, $parameter] = $callStack[0];
26-
if (!$function instanceof MethodReflection) {
27-
return false;
28-
}
29-
if ($function->getName() !== 'backwardsCompatibleCall'
30-
|| $function->getDeclaringClass()->getName() !== DeprecationHelper::class
31-
) {
32-
return false;
20+
foreach ($scope->getFunctionCallStackWithParameters() as [$function, $parameter]) {
21+
if (!$function instanceof MethodReflection) {
22+
continue;
23+
}
24+
if ($function->getName() !== 'backwardsCompatibleCall'
25+
|| $function->getDeclaringClass()->getName() !== DeprecationHelper::class
26+
) {
27+
continue;
28+
}
29+
if ($parameter !== null && $parameter->getName() === 'deprecatedCallable') {
30+
return true;
31+
}
3332
}
34-
return $parameter !== null && $parameter->getName() === 'deprecatedCallable';
33+
return false;
3534
}
3635
}

tests/src/DeprecatedScope/data/deprecation-helper-test.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,22 @@ function() {
5757
$this->deprecatedCallable(...),
5858
$this->currentCallable(...)
5959
);
60+
61+
// BC wrapper nested inside an outer function call — deprecatedCallable must still be suppressed.
62+
$x = trim(DeprecationHelper::backwardsCompatibleCall(
63+
\Drupal::VERSION,
64+
'10.1.0',
65+
fn() => count([]),
66+
fn() => deprecated_function()
67+
));
68+
69+
// BC wrapper 4 levels deep — stack traversal must find backwardsCompatibleCall at any depth.
70+
$y = trim(strrev(strtolower(DeprecationHelper::backwardsCompatibleCall(
71+
\Drupal::VERSION,
72+
'10.1.0',
73+
fn() => '',
74+
fn() => deprecated_function()
75+
))));
6076
}
6177

6278
/**

0 commit comments

Comments
 (0)