Skip to content

Commit

Permalink
Scope::getFunctionCallStack()
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jan 7, 2024
1 parent bbd9a68 commit 9be1376
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 1 deletion.
7 changes: 6 additions & 1 deletion src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class MutatingScope implements Scope
* @param array<string, true> $currentlyAssignedExpressions
* @param array<string, true> $currentlyAllowedUndefinedExpressions
* @param array<string, ExpressionTypeHolder> $nativeExpressionTypes
* @param array<MethodReflection|FunctionReflection> $inFunctionCallsStack
* @param list<MethodReflection|FunctionReflection> $inFunctionCallsStack
*/
public function __construct(
private InternalScopeFactory $scopeFactory,
Expand Down Expand Up @@ -2493,6 +2493,11 @@ public function isInClassExists(string $className): bool
return $this->getType($expr)->isTrue()->yes();
}

public function getFunctionCallStack(): array
{
return $this->inFunctionCallsStack;
}

/** @api */
public function isInFunctionExists(string $functionName): bool
{
Expand Down
4 changes: 4 additions & 0 deletions src/Analyser/Scope.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use PHPStan\Reflection\ConstantReflection;
use PHPStan\Reflection\ExtendedMethodReflection;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\NamespaceAnswerer;
use PHPStan\Reflection\ParametersAcceptor;
use PHPStan\Reflection\PropertyReflection;
Expand Down Expand Up @@ -104,6 +105,9 @@ public function isInFunctionExists(string $functionName): bool;

public function isInClosureBind(): bool;

/** @return list<FunctionReflection|MethodReflection> */
public function getFunctionCallStack(): array;

public function isParameterValueNullable(Param $parameter): bool;

/**
Expand Down
38 changes: 38 additions & 0 deletions tests/PHPStan/Rules/ScopeFunctionCallStackRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules;

use PhpParser\Node;
use PhpParser\Node\Expr\Throw_;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use function implode;
use function sprintf;

/** @implements Rule<Throw_> */
class ScopeFunctionCallStackRule implements Rule
{

public function getNodeType(): string
{
return Throw_::class;
}

public function processNode(Node $node, Scope $scope): array
{
$messages = [];
foreach ($scope->getFunctionCallStack() as $reflection) {
if ($reflection instanceof FunctionReflection) {
$messages[] = $reflection->getName();
continue;
}

$messages[] = sprintf('%s::%s', $reflection->getDeclaringClass()->getDisplayName(), $reflection->getName());
}

return [
RuleErrorBuilder::message(implode("\n", $messages))->identifier('dummy')->build(),
];
}

}
33 changes: 33 additions & 0 deletions tests/PHPStan/Rules/ScopeFunctionCallStackRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules;

use PHPStan\Testing\RuleTestCase;
use const PHP_VERSION_ID;

/**
* @extends RuleTestCase<ScopeFunctionCallStackRule>
*/
class ScopeFunctionCallStackRuleTest extends RuleTestCase
{

protected function getRule(): Rule
{
return new ScopeFunctionCallStackRule();
}

public function testRule(): void
{
if (PHP_VERSION_ID < 80000) {
$this->markTestSkipped('Test requires PHP 8.0.');
}

$this->analyse([__DIR__ . '/data/scope-function-call-stack.php'], [
[
"var_dump\nprint_r\nsleep",
7,
],
]);
}

}
8 changes: 8 additions & 0 deletions tests/PHPStan/Rules/data/scope-function-call-stack.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php // lint >= 8.0

namespace ScopeFunctionCallStack;

function (): void
{
var_dump(print_r(sleep(throw new \Exception())));
};

0 comments on commit 9be1376

Please sign in to comment.