2019-10-13 05:59:52 +00:00
< ? php
2021-05-09 20:15:43 +00:00
declare ( strict_types = 1 );
2022-06-06 17:12:56 +00:00
namespace Rector\NodeTypeResolver\PHPStan\Scope ;
2018-08-03 18:41:30 +00:00
2022-06-06 17:12:56 +00:00
use PhpParser\Node ;
use PhpParser\Node\Arg ;
use PhpParser\Node\Expr ;
2022-11-16 14:19:15 +00:00
use PhpParser\Node\Expr\Array_ ;
2022-07-27 08:02:59 +00:00
use PhpParser\Node\Expr\ArrayItem ;
2022-06-06 17:12:56 +00:00
use PhpParser\Node\Expr\Assign ;
2022-06-19 08:24:30 +00:00
use PhpParser\Node\Expr\AssignOp ;
use PhpParser\Node\Expr\BinaryOp ;
2023-04-12 13:24:05 +00:00
use PhpParser\Node\Expr\Cast ;
2023-02-19 14:50:05 +00:00
use PhpParser\Node\Expr\Closure ;
2022-07-27 08:02:59 +00:00
use PhpParser\Node\Expr\FuncCall ;
2022-06-19 08:24:30 +00:00
use PhpParser\Node\Expr\Ternary ;
2022-06-20 07:09:14 +00:00
use PhpParser\Node\Expr\Variable ;
2023-03-23 23:21:34 +00:00
use PhpParser\Node\Identifier ;
2022-06-06 17:12:56 +00:00
use PhpParser\Node\Name ;
use PhpParser\Node\Stmt ;
use PhpParser\Node\Stmt\Class_ ;
use PhpParser\Node\Stmt\Enum_ ;
2022-07-18 23:37:02 +00:00
use PhpParser\Node\Stmt\EnumCase ;
2022-07-03 17:06:40 +00:00
use PhpParser\Node\Stmt\Expression ;
2022-06-06 17:12:56 +00:00
use PhpParser\Node\Stmt\Finally_ ;
use PhpParser\Node\Stmt\Foreach_ ;
use PhpParser\Node\Stmt\Interface_ ;
use PhpParser\Node\Stmt\Property ;
use PhpParser\Node\Stmt\Return_ ;
use PhpParser\Node\Stmt\Switch_ ;
use PhpParser\Node\Stmt\Trait_ ;
use PhpParser\Node\Stmt\TryCatch ;
use PhpParser\NodeTraverser ;
use PHPStan\AnalysedCodeException ;
use PHPStan\Analyser\MutatingScope ;
use PHPStan\Analyser\NodeScopeResolver ;
use PHPStan\Analyser\ScopeContext ;
use PHPStan\Node\UnreachableStatementNode ;
use PHPStan\Reflection\ClassReflection ;
use PHPStan\Reflection\ReflectionProvider ;
2022-06-25 16:12:40 +00:00
use PHPStan\Type\ObjectType ;
use PHPStan\Type\TypeCombinator ;
2022-06-06 17:12:56 +00:00
use Rector\Caching\Detector\ChangedFilesDetector ;
use Rector\Caching\FileSystem\DependencyResolver ;
use Rector\Core\Exception\ShouldNotHappenException ;
2023-02-19 17:53:18 +00:00
use Rector\Core\NodeAnalyzer\ClassAnalyzer ;
2023-02-19 14:50:05 +00:00
use Rector\Core\PhpParser\Node\BetterNodeFinder ;
2022-09-01 19:30:48 +00:00
use Rector\Core\Util\Reflection\PrivatesAccessor ;
2022-06-20 07:09:14 +00:00
use Rector\NodeNameResolver\NodeNameResolver ;
2022-06-06 17:12:56 +00:00
use Rector\NodeTypeResolver\Node\AttributeKey ;
2023-04-27 18:21:20 +00:00
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\AssignedToNodeVisitor ;
2022-06-06 17:12:56 +00:00
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\RemoveDeepChainMethodCallNodeVisitor ;
2023-05-01 01:36:32 +00:00
use RectorPrefix202305\Webmozart\Assert\Assert ;
2018-08-03 18:41:30 +00:00
/**
* @ inspired by https :// github . com / silverstripe / silverstripe - upgrader / blob / 532182 b23e854d02e0b27e68ebc394f436de0682 / src / UpgradeRule / PHP / Visitor / PHPStanScopeVisitor . php
* - https :// github . com / silverstripe / silverstripe - upgrader / pull / 57 / commits / e5c7cfa166ad940d9d4ff69537d9f7608e992359 #diff-5e0807bb3dc03d6a8d8b6ad049abd774
*/
2020-06-16 19:43:45 +00:00
final class PHPStanNodeScopeResolver
2018-08-03 18:41:30 +00:00
{
2021-11-25 19:08:52 +00:00
/**
* @ var string
*/
private const CONTEXT = 'context' ;
2023-03-28 19:22:16 +00:00
/**
* @ readonly
* @ var \PhpParser\NodeTraverser
*/
private $nodeTraverser ;
2018-08-03 18:41:30 +00:00
/**
2021-12-04 12:47:17 +00:00
* @ readonly
2021-05-10 23:39:21 +00:00
* @ var \Rector\Caching\Detector\ChangedFilesDetector
2018-08-03 18:41:30 +00:00
*/
2021-05-10 23:39:21 +00:00
private $changedFilesDetector ;
2018-08-05 15:11:56 +00:00
/**
2021-12-04 12:47:17 +00:00
* @ readonly
2021-05-10 23:39:21 +00:00
* @ var \Rector\Caching\FileSystem\DependencyResolver
2018-08-05 15:11:56 +00:00
*/
2021-05-10 23:39:21 +00:00
private $dependencyResolver ;
2018-11-06 23:05:21 +00:00
/**
2021-12-04 12:47:17 +00:00
* @ readonly
2021-08-23 00:20:32 +00:00
* @ var \PHPStan\Analyser\NodeScopeResolver
2018-11-06 23:05:21 +00:00
*/
2021-05-10 23:39:21 +00:00
private $nodeScopeResolver ;
2019-05-12 08:19:38 +00:00
/**
2021-12-04 12:47:17 +00:00
* @ readonly
2021-08-23 00:20:32 +00:00
* @ var \PHPStan\Reflection\ReflectionProvider
2019-05-12 08:19:38 +00:00
*/
2021-05-10 23:39:21 +00:00
private $reflectionProvider ;
2020-04-01 01:55:44 +00:00
/**
2021-12-04 12:47:17 +00:00
* @ readonly
2021-05-10 23:39:21 +00:00
* @ var \Rector\NodeTypeResolver\PHPStan\Scope\ScopeFactory
2020-04-01 01:55:44 +00:00
*/
2021-05-10 23:39:21 +00:00
private $scopeFactory ;
2021-06-25 17:38:41 +00:00
/**
2021-12-04 12:47:17 +00:00
* @ readonly
2022-09-01 19:30:48 +00:00
* @ var \Rector\Core\Util\Reflection\PrivatesAccessor
2021-06-25 17:38:41 +00:00
*/
2021-06-26 18:33:28 +00:00
private $privatesAccessor ;
2022-06-20 07:09:14 +00:00
/**
* @ readonly
* @ var \Rector\NodeNameResolver\NodeNameResolver
*/
private $nodeNameResolver ;
2023-02-19 14:50:05 +00:00
/**
* @ readonly
* @ var \Rector\Core\PhpParser\Node\BetterNodeFinder
*/
private $betterNodeFinder ;
2023-02-19 17:53:18 +00:00
/**
* @ readonly
* @ var \Rector\Core\NodeAnalyzer\ClassAnalyzer
*/
private $classAnalyzer ;
2023-04-27 18:21:20 +00:00
public function __construct ( ChangedFilesDetector $changedFilesDetector , DependencyResolver $dependencyResolver , NodeScopeResolver $nodeScopeResolver , ReflectionProvider $reflectionProvider , RemoveDeepChainMethodCallNodeVisitor $removeDeepChainMethodCallNodeVisitor , AssignedToNodeVisitor $assignedToNodeVisitor , \Rector\NodeTypeResolver\PHPStan\Scope\ScopeFactory $scopeFactory , PrivatesAccessor $privatesAccessor , NodeNameResolver $nodeNameResolver , BetterNodeFinder $betterNodeFinder , ClassAnalyzer $classAnalyzer )
2021-05-09 20:15:43 +00:00
{
2021-05-10 23:39:21 +00:00
$this -> changedFilesDetector = $changedFilesDetector ;
$this -> dependencyResolver = $dependencyResolver ;
2020-06-16 19:43:45 +00:00
$this -> nodeScopeResolver = $nodeScopeResolver ;
2020-01-13 13:34:18 +00:00
$this -> reflectionProvider = $reflectionProvider ;
2021-05-10 23:39:21 +00:00
$this -> scopeFactory = $scopeFactory ;
2021-06-26 18:33:28 +00:00
$this -> privatesAccessor = $privatesAccessor ;
2022-06-20 07:09:14 +00:00
$this -> nodeNameResolver = $nodeNameResolver ;
2023-02-19 14:50:05 +00:00
$this -> betterNodeFinder = $betterNodeFinder ;
2023-02-19 17:53:18 +00:00
$this -> classAnalyzer = $classAnalyzer ;
2023-03-28 19:22:16 +00:00
$this -> nodeTraverser = new NodeTraverser ();
$this -> nodeTraverser -> addVisitor ( $removeDeepChainMethodCallNodeVisitor );
2023-04-27 18:21:20 +00:00
$this -> nodeTraverser -> addVisitor ( $assignedToNodeVisitor );
2018-08-03 18:41:30 +00:00
}
/**
2021-10-27 08:50:45 +00:00
* @ param Stmt [] $stmts
2021-06-22 17:07:57 +00:00
* @ return Stmt []
2018-08-03 18:41:30 +00:00
*/
2022-09-01 09:30:44 +00:00
public function processNodes ( array $stmts , string $filePath , ? MutatingScope $formerMutatingScope = null ) : array
2018-08-03 18:41:30 +00:00
{
2022-06-07 08:22:29 +00:00
$isScopeRefreshing = $formerMutatingScope instanceof MutatingScope ;
2022-05-12 09:11:03 +00:00
/**
* The stmts must be array of Stmt , or it will be silently skipped by PHPStan
* @ see vendor / phpstan / phpstan / phpstan . phar / src / Analyser / NodeScopeResolver . php : 282
*/
2022-06-07 08:22:29 +00:00
Assert :: allIsInstanceOf ( $stmts , Stmt :: class );
2023-03-28 19:22:16 +00:00
$this -> nodeTraverser -> traverse ( $stmts );
2022-09-01 09:30:44 +00:00
$scope = $formerMutatingScope ? ? $this -> scopeFactory -> createFromFile ( $filePath );
2018-11-06 23:05:21 +00:00
// skip chain method calls, performance issue: https://github.com/phpstan/phpstan/issues/254
2022-09-01 09:30:44 +00:00
$nodeCallback = function ( Node $node , MutatingScope $mutatingScope ) use ( & $nodeCallback , $isScopeRefreshing , $filePath ) : void {
2023-04-12 13:24:05 +00:00
if (( $node instanceof Expression || $node instanceof Return_ || $node instanceof Assign || $node instanceof EnumCase || $node instanceof AssignOp || $node instanceof Cast ) && $node -> expr instanceof Expr ) {
2022-07-03 17:06:40 +00:00
$node -> expr -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
}
2022-06-19 08:24:30 +00:00
if ( $node instanceof Ternary ) {
$this -> processTernary ( $node , $mutatingScope );
}
if ( $node instanceof BinaryOp ) {
$this -> processBinaryOp ( $node , $mutatingScope );
}
2022-06-07 08:22:29 +00:00
if ( $node instanceof Arg ) {
$node -> value -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
2022-05-29 16:14:19 +00:00
}
2022-06-07 08:22:29 +00:00
if ( $node instanceof Foreach_ ) {
2022-05-04 15:20:50 +00:00
// decorate value as well
2022-06-07 08:22:29 +00:00
$node -> valueVar -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
2022-11-16 14:19:15 +00:00
if ( $node -> valueVar instanceof Array_ ) {
$this -> processArray ( $node -> valueVar , $mutatingScope );
}
}
if ( $node instanceof Array_ ) {
$this -> processArray ( $node , $mutatingScope );
2022-05-04 15:20:50 +00:00
}
2022-06-07 08:22:29 +00:00
if ( $node instanceof Property ) {
2022-06-19 08:24:30 +00:00
$this -> processProperty ( $node , $mutatingScope );
2022-05-12 09:11:03 +00:00
}
2022-06-07 08:22:29 +00:00
if ( $node instanceof Switch_ ) {
2022-07-18 14:32:34 +00:00
$this -> processSwitch ( $node , $mutatingScope );
2022-05-12 09:11:03 +00:00
}
2022-06-19 08:24:30 +00:00
if ( $node instanceof TryCatch ) {
2022-09-01 09:30:44 +00:00
$this -> processTryCatch ( $node , $filePath , $mutatingScope );
2022-05-12 09:11:03 +00:00
}
2022-07-27 08:02:59 +00:00
if ( $node instanceof ArrayItem ) {
$this -> processArrayItem ( $node , $mutatingScope );
}
if ( $node instanceof FuncCall && $node -> name instanceof Expr ) {
$node -> name -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
}
2023-04-12 13:24:05 +00:00
if ( $node instanceof Assign || $node instanceof AssignOp ) {
2022-05-12 09:11:03 +00:00
// decorate value as well
2022-06-07 08:22:29 +00:00
$node -> var -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
2022-05-12 09:11:03 +00:00
}
2022-06-07 08:22:29 +00:00
if ( $node instanceof Trait_ ) {
2021-10-04 21:24:17 +00:00
$traitName = $this -> resolveClassName ( $node );
$traitReflectionClass = $this -> reflectionProvider -> getClass ( $traitName );
2022-04-10 08:30:09 +00:00
$traitScope = clone $mutatingScope ;
2022-06-07 08:22:29 +00:00
$scopeContext = $this -> privatesAccessor -> getPrivatePropertyOfClass ( $traitScope , self :: CONTEXT , ScopeContext :: class );
2021-12-29 23:48:39 +00:00
$traitContext = clone $scopeContext ;
2022-05-12 09:11:03 +00:00
// before entering the class/trait again, we have to tell scope no class was set, otherwise it crashes
2022-06-07 08:22:29 +00:00
$this -> privatesAccessor -> setPrivatePropertyOfClass ( $traitContext , 'classReflection' , $traitReflectionClass , ClassReflection :: class );
$this -> privatesAccessor -> setPrivatePropertyOfClass ( $traitScope , self :: CONTEXT , $traitContext , ScopeContext :: class );
$node -> setAttribute ( AttributeKey :: SCOPE , $traitScope );
2021-10-30 13:43:30 +00:00
$this -> nodeScopeResolver -> processNodes ( $node -> stmts , $traitScope , $nodeCallback );
2022-07-18 14:32:34 +00:00
$this -> decorateTraitAttrGroups ( $node , $traitScope );
2019-08-05 16:52:55 +00:00
return ;
2018-08-03 18:41:30 +00:00
}
2021-03-18 01:48:44 +00:00
// the class reflection is resolved AFTER entering to class node
// so we need to get it from the first after this one
2022-06-07 08:22:29 +00:00
if ( $node instanceof Class_ || $node instanceof Interface_ || $node instanceof Enum_ ) {
2022-04-10 08:30:09 +00:00
/** @var MutatingScope $mutatingScope */
2022-05-12 09:11:03 +00:00
$mutatingScope = $this -> resolveClassOrInterfaceScope ( $node , $mutatingScope , $isScopeRefreshing );
2021-03-18 01:48:44 +00:00
}
2023-02-19 14:50:05 +00:00
if ( $node instanceof Stmt ) {
$this -> setChildOfUnreachableStatementNodeAttribute ( $node );
}
2019-10-02 20:13:37 +00:00
// special case for unreachable nodes
2022-06-07 08:22:29 +00:00
if ( $node instanceof UnreachableStatementNode ) {
2022-09-01 09:30:44 +00:00
$this -> processUnreachableStatementNode ( $node , $filePath , $mutatingScope );
2019-10-02 20:13:37 +00:00
} else {
2022-06-07 08:22:29 +00:00
$node -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
2019-10-02 20:13:37 +00:00
}
2020-09-16 18:11:35 +00:00
};
2022-09-01 09:30:44 +00:00
return $this -> processNodesWithDependentFiles ( $filePath , $stmts , $scope , $nodeCallback );
2021-08-16 08:19:28 +00:00
}
2023-02-19 14:50:05 +00:00
private function setChildOfUnreachableStatementNodeAttribute ( Stmt $stmt ) : void
{
if ( $stmt -> getAttribute ( AttributeKey :: IS_UNREACHABLE ) === \true ) {
return ;
}
$parentStmt = $stmt -> getAttribute ( AttributeKey :: PARENT_NODE );
if ( ! $parentStmt instanceof Node ) {
return ;
}
if ( $parentStmt instanceof Closure ) {
$parentStmt = $this -> betterNodeFinder -> resolveCurrentStatement ( $parentStmt );
}
if ( ! $parentStmt instanceof Stmt ) {
return ;
}
if ( $parentStmt -> getAttribute ( AttributeKey :: IS_UNREACHABLE ) === \true ) {
$stmt -> setAttribute ( AttributeKey :: IS_UNREACHABLE , \true );
}
}
2022-11-16 14:19:15 +00:00
private function processArray ( Array_ $array , MutatingScope $mutatingScope ) : void
{
foreach ( $array -> items as $arrayItem ) {
if ( $arrayItem instanceof ArrayItem ) {
$arrayItem -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
}
}
}
2022-07-27 08:02:59 +00:00
private function processArrayItem ( ArrayItem $arrayItem , MutatingScope $mutatingScope ) : void
{
if ( $arrayItem -> key instanceof Expr ) {
$arrayItem -> key -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
}
$arrayItem -> value -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
}
2022-07-18 14:32:34 +00:00
private function decorateTraitAttrGroups ( Trait_ $trait , MutatingScope $mutatingScope ) : void
{
foreach ( $trait -> attrGroups as $attrGroup ) {
foreach ( $attrGroup -> attrs as $attr ) {
foreach ( $attr -> args as $arg ) {
$arg -> value -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
}
}
}
}
private function processSwitch ( Switch_ $switch , MutatingScope $mutatingScope ) : void
{
// decorate value as well
foreach ( $switch -> cases as $case ) {
$case -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
}
}
2022-09-01 09:30:44 +00:00
private function processTryCatch ( TryCatch $tryCatch , string $filePath , MutatingScope $mutatingScope ) : void
2022-07-18 14:32:34 +00:00
{
foreach ( $tryCatch -> catches as $catch ) {
$varName = $catch -> var instanceof Variable ? $this -> nodeNameResolver -> getName ( $catch -> var ) : null ;
2022-08-23 16:16:02 +00:00
$type = TypeCombinator :: union ( ... \array_map ( static function ( Name $name ) : ObjectType {
return new ObjectType (( string ) $name );
2022-07-18 14:32:34 +00:00
}, $catch -> types ));
$catchMutatingScope = $mutatingScope -> enterCatchType ( $type , $varName );
2022-09-01 09:30:44 +00:00
$this -> processNodes ( $catch -> stmts , $filePath , $catchMutatingScope );
2022-07-18 14:32:34 +00:00
}
if ( $tryCatch -> finally instanceof Finally_ ) {
$tryCatch -> finally -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
}
}
2022-09-01 09:30:44 +00:00
private function processUnreachableStatementNode ( UnreachableStatementNode $unreachableStatementNode , string $filePath , MutatingScope $mutatingScope ) : void
2022-06-19 08:24:30 +00:00
{
$originalStmt = $unreachableStatementNode -> getOriginalStatement ();
$originalStmt -> setAttribute ( AttributeKey :: IS_UNREACHABLE , \true );
$originalStmt -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
2022-09-01 09:30:44 +00:00
$this -> processNodes ([ $originalStmt ], $filePath , $mutatingScope );
2022-08-09 13:39:17 +00:00
$nextNode = $originalStmt -> getAttribute ( AttributeKey :: NEXT_NODE );
while ( $nextNode instanceof Stmt ) {
$nextNode -> setAttribute ( AttributeKey :: IS_UNREACHABLE , \true );
2022-09-01 09:30:44 +00:00
$this -> processNodes ([ $nextNode ], $filePath , $mutatingScope );
2022-08-09 13:39:17 +00:00
$nextNode = $nextNode -> getAttribute ( AttributeKey :: NEXT_NODE );
2022-06-19 08:24:30 +00:00
}
}
private function processProperty ( Property $property , MutatingScope $mutatingScope ) : void
{
foreach ( $property -> props as $propertyProperty ) {
$propertyProperty -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
if ( $propertyProperty -> default instanceof Expr ) {
$propertyProperty -> default -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
}
}
foreach ( $property -> attrGroups as $attrGroup ) {
foreach ( $attrGroup -> attrs as $attribute ) {
$attribute -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
}
}
}
private function processBinaryOp ( BinaryOp $binaryOp , MutatingScope $mutatingScope ) : void
{
$binaryOp -> left -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
$binaryOp -> right -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
}
private function processTernary ( Ternary $ternary , MutatingScope $mutatingScope ) : void
{
if ( $ternary -> if instanceof Expr ) {
$ternary -> if -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
}
$ternary -> else -> setAttribute ( AttributeKey :: SCOPE , $mutatingScope );
}
2021-08-16 08:19:28 +00:00
/**
2021-10-27 08:50:45 +00:00
* @ param Stmt [] $stmts
2022-02-19 18:54:29 +00:00
* @ param callable ( Node $node , MutatingScope $scope ) : void $nodeCallback
2021-08-16 08:19:28 +00:00
* @ return Stmt []
*/
2022-09-01 09:30:44 +00:00
private function processNodesWithDependentFiles ( string $filePath , array $stmts , MutatingScope $mutatingScope , callable $nodeCallback ) : array
2021-08-16 08:19:28 +00:00
{
2021-11-24 20:49:18 +00:00
$this -> nodeScopeResolver -> processNodes ( $stmts , $mutatingScope , $nodeCallback );
2022-09-01 09:30:44 +00:00
$this -> resolveAndSaveDependentFiles ( $stmts , $mutatingScope , $filePath );
2021-10-27 08:50:45 +00:00
return $stmts ;
2018-08-03 18:41:30 +00:00
}
2018-08-10 15:17:09 +00:00
/**
2022-05-12 09:11:03 +00:00
* @ param \PhpParser\Node\Stmt\Class_ | \PhpParser\Node\Stmt\Interface_ | \PhpParser\Node\Stmt\Enum_ $classLike
2018-08-10 15:17:09 +00:00
*/
2022-06-07 08:22:29 +00:00
private function resolveClassOrInterfaceScope ( $classLike , MutatingScope $mutatingScope , bool $isScopeRefreshing ) : MutatingScope
2020-08-27 10:19:22 +00:00
{
2020-07-26 09:00:23 +00:00
$className = $this -> resolveClassName ( $classLike );
// is anonymous class? - not possible to enter it since PHPStan 0.12.33, see https://github.com/phpstan/phpstan-src/commit/e87fb0ec26f9c8552bbeef26a868b1e5d8185e91
2023-02-19 17:53:18 +00:00
if ( $classLike instanceof Class_ && $this -> classAnalyzer -> isAnonymousClass ( $classLike )) {
2021-10-04 21:24:17 +00:00
$classReflection = $this -> reflectionProvider -> getAnonymousClassReflection ( $classLike , $mutatingScope );
2021-05-09 20:15:43 +00:00
} elseif ( ! $this -> reflectionProvider -> hasClass ( $className )) {
2021-10-04 21:24:17 +00:00
return $mutatingScope ;
2021-03-18 01:48:44 +00:00
} else {
$classReflection = $this -> reflectionProvider -> getClass ( $className );
2020-07-26 09:00:23 +00:00
}
2022-05-12 09:11:03 +00:00
// on refresh, remove entered class avoid entering the class again
if ( $isScopeRefreshing && $mutatingScope -> isInClass () && ! $classReflection -> isAnonymous ()) {
$context = $this -> privatesAccessor -> getPrivateProperty ( $mutatingScope , 'context' );
$this -> privatesAccessor -> setPrivateProperty ( $context , 'classReflection' , null );
}
2021-10-04 21:24:17 +00:00
return $mutatingScope -> enterClass ( $classReflection );
2019-03-10 23:47:43 +00:00
}
/**
2022-05-12 09:11:03 +00:00
* @ param \PhpParser\Node\Stmt\Class_ | \PhpParser\Node\Stmt\Interface_ | \PhpParser\Node\Stmt\Trait_ | \PhpParser\Node\Stmt\Enum_ $classLike
2019-03-10 23:47:43 +00:00
*/
2021-05-30 10:12:56 +00:00
private function resolveClassName ( $classLike ) : string
2018-08-10 15:17:09 +00:00
{
2022-06-07 08:22:29 +00:00
if ( $classLike -> namespacedName instanceof Name ) {
2020-02-07 07:46:29 +00:00
return ( string ) $classLike -> namespacedName ;
2018-08-10 15:17:09 +00:00
}
2023-03-23 23:21:34 +00:00
if ( ! $classLike -> name instanceof Identifier ) {
2022-06-07 08:22:29 +00:00
throw new ShouldNotHappenException ();
2018-08-10 15:17:09 +00:00
}
2020-02-07 07:46:29 +00:00
return $classLike -> name -> toString ();
2018-08-10 15:17:09 +00:00
}
2021-06-22 17:07:57 +00:00
/**
* @ param Stmt [] $stmts
*/
2022-09-01 09:30:44 +00:00
private function resolveAndSaveDependentFiles ( array $stmts , MutatingScope $mutatingScope , string $filePath ) : void
2021-06-22 17:07:57 +00:00
{
$dependentFiles = [];
foreach ( $stmts as $stmt ) {
try {
$nodeDependentFiles = $this -> dependencyResolver -> resolveDependencies ( $stmt , $mutatingScope );
$dependentFiles = \array_merge ( $dependentFiles , $nodeDependentFiles );
2022-06-07 08:22:29 +00:00
} catch ( AnalysedCodeException $exception ) {
2021-06-22 17:07:57 +00:00
// @ignoreException
}
}
2023-04-11 08:29:27 +00:00
$this -> changedFilesDetector -> addFileWithDependencies ( $filePath , $dependentFiles );
2021-06-22 17:07:57 +00:00
}
2018-08-03 18:41:30 +00:00
}