From 5a2f7c0a7140dc35b05e211167299a3b2a2dbd1f Mon Sep 17 00:00:00 2001 From: Yannick Gottschalk Date: Tue, 27 Jun 2023 15:10:03 +0200 Subject: [PATCH 1/4] Use getParts() instead of $parts on PhpParser\Node\Name. also use getFirst(), getLast() and getString() --- examples/plugins/FunctionCasingChecker.php | 2 +- examples/plugins/StringChecker.php | 2 +- src/Psalm/Internal/Analyzer/CanAlias.php | 7 +- src/Psalm/Internal/Analyzer/ClassAnalyzer.php | 4 +- .../Internal/Analyzer/ClassLikeAnalyzer.php | 9 +- src/Psalm/Internal/Analyzer/FileAnalyzer.php | 3 +- .../Internal/Analyzer/NamespaceAnalyzer.php | 3 +- .../Block/IfConditionalAnalyzer.php | 8 +- .../Statements/Block/SwitchCaseAnalyzer.php | 2 +- .../Statements/Block/WhileAnalyzer.php | 3 +- .../Statements/Expression/AssertionFinder.php | 96 +++++++++---------- .../Expression/BinaryOpAnalyzer.php | 2 +- .../Expression/Call/FunctionCallAnalyzer.php | 10 +- .../Expression/Call/NewAnalyzer.php | 11 +-- .../Expression/Call/StaticCallAnalyzer.php | 12 +-- .../StaticMethod/AtomicStaticCallAnalyzer.php | 14 +-- .../ExistingAtomicStaticCallAnalyzer.php | 10 +- .../Statements/Expression/CallAnalyzer.php | 2 +- .../Expression/ClassConstAnalyzer.php | 8 +- .../Expression/ExpressionIdentifier.php | 12 +-- .../Expression/Fetch/ConstFetchAnalyzer.php | 2 +- .../Fetch/StaticPropertyFetchAnalyzer.php | 8 +- .../Statements/Expression/IncludeAnalyzer.php | 4 +- .../Expression/InstanceofAnalyzer.php | 4 +- .../Statements/Expression/MatchAnalyzer.php | 10 +- .../Expression/SimpleTypeInferer.php | 12 +-- .../Internal/Analyzer/StatementsAnalyzer.php | 2 +- .../Internal/Diff/FileStatementsDiffer.php | 4 +- .../Diff/NamespaceStatementsDiffer.php | 4 +- .../Reflector/ExpressionResolver.php | 39 ++++---- .../Reflector/ExpressionScanner.php | 3 +- .../Reflector/FunctionLikeNodeScanner.php | 7 +- .../PhpVisitor/Reflector/TypeHintResolver.php | 5 +- .../Internal/PhpVisitor/ReflectorVisitor.php | 13 ++- .../AddRemoveTaints/HtmlFunctionTainter.php | 8 +- .../Internal/Scanner/PhpStormMetaScanner.php | 15 ++- 36 files changed, 175 insertions(+), 185 deletions(-) diff --git a/examples/plugins/FunctionCasingChecker.php b/examples/plugins/FunctionCasingChecker.php index 9fb1011e1d8..50cfc7358ff 100644 --- a/examples/plugins/FunctionCasingChecker.php +++ b/examples/plugins/FunctionCasingChecker.php @@ -84,7 +84,7 @@ public static function afterFunctionCallAnalysis(AfterFunctionCallAnalysisEvent $function_name_parts = explode('\\', $function_storage->cased_name); - if (end($function_name_parts) !== end($expr->name->parts)) { + if (end($function_name_parts) !== $expr->name->getLast()) { IssueBuffer::maybeAdd( new IncorrectFunctionCasing( 'Function is incorrectly cased, expecting ' . $function_storage->cased_name, diff --git a/examples/plugins/StringChecker.php b/examples/plugins/StringChecker.php index 453a91bad7d..621997dd965 100644 --- a/examples/plugins/StringChecker.php +++ b/examples/plugins/StringChecker.php @@ -50,7 +50,7 @@ public static function afterExpressionAnalysis(AfterExpressionAnalysisEvent $eve && $expr->left->class instanceof PhpParser\Node\Name && $expr->left->name instanceof PhpParser\Node\Identifier && strtolower($expr->left->name->name) === 'class' - && !in_array(strtolower($expr->left->class->parts[0]), ['self', 'static', 'parent']) + && !in_array(strtolower($expr->left->class->getFirst()), ['self', 'static', 'parent']) && $expr->right instanceof PhpParser\Node\Scalar\String_ && preg_match('/^::[A-Za-z0-9]+$/', $expr->right->value) ) { diff --git a/src/Psalm/Internal/Analyzer/CanAlias.php b/src/Psalm/Internal/Analyzer/CanAlias.php index 1e23e08b0a9..3be3d60d7bd 100644 --- a/src/Psalm/Internal/Analyzer/CanAlias.php +++ b/src/Psalm/Internal/Analyzer/CanAlias.php @@ -8,7 +8,6 @@ use Psalm\FileManipulation; use Psalm\Internal\FileManipulation\FileManipulationBuffer; -use function implode; use function strtolower; /** @@ -51,7 +50,7 @@ public function visitUse(PhpParser\Node\Stmt\Use_ $stmt): void $codebase = $this->getCodebase(); foreach ($stmt->uses as $use) { - $use_path = implode('\\', $use->name->parts); + $use_path = $use->name->toString(); $use_path_lc = strtolower($use_path); $use_alias = $use->alias->name ?? $use->name->getLast(); $use_alias_lc = strtolower($use_alias); @@ -106,12 +105,12 @@ public function visitUse(PhpParser\Node\Stmt\Use_ $stmt): void public function visitGroupUse(PhpParser\Node\Stmt\GroupUse $stmt): void { - $use_prefix = implode('\\', $stmt->prefix->parts); + $use_prefix = $stmt->prefix->toString(); $codebase = $this->getCodebase(); foreach ($stmt->uses as $use) { - $use_path = $use_prefix . '\\' . implode('\\', $use->name->parts); + $use_path = $use_prefix . '\\' . $use->name->toString(); $use_alias = $use->alias->name ?? $use->name->getLast(); switch ($use->type !== PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN ? $use->type : $stmt->type) { diff --git a/src/Psalm/Internal/Analyzer/ClassAnalyzer.php b/src/Psalm/Internal/Analyzer/ClassAnalyzer.php index 84d33115fd5..bdb3573260c 100644 --- a/src/Psalm/Internal/Analyzer/ClassAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ClassAnalyzer.php @@ -2021,7 +2021,7 @@ private function checkImplementedInterfaces( . ($interface_name instanceof PhpParser\Node\Name\FullyQualified ? '\\' : $this->getNamespace() . '-') - . implode('\\', $interface_name->parts), + . $interface_name->toString(), ); $interface_location = new CodeLocation($this, $interface_name); @@ -2437,7 +2437,7 @@ private function checkParentClass( . ($extended_class instanceof PhpParser\Node\Name\FullyQualified ? '\\' : $this->getNamespace() . '-') - . implode('\\', $extended_class->parts), + . $extended_class->toString(), ); } diff --git a/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php b/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php index 92e86998d71..a6c909191b8 100644 --- a/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php @@ -40,7 +40,6 @@ use function count; use function explode; use function gettype; -use function implode; use function in_array; use function preg_match; use function preg_replace; @@ -421,15 +420,15 @@ public static function getFQCLNFromNameObject( } if ($class_name instanceof PhpParser\Node\Name\FullyQualified) { - return implode('\\', $class_name->parts); + return $class_name->toString(); } - if (in_array($class_name->parts[0], ['self', 'static', 'parent'], true)) { - return $class_name->parts[0]; + if (in_array($class_name->getFirst(), ['self', 'static', 'parent'], true)) { + return $class_name->getFirst(); } return Type::getFQCLNFromString( - implode('\\', $class_name->parts), + $class_name->toString(), $aliases, ); } diff --git a/src/Psalm/Internal/Analyzer/FileAnalyzer.php b/src/Psalm/Internal/Analyzer/FileAnalyzer.php index 7f6ce4cee76..d9879558922 100644 --- a/src/Psalm/Internal/Analyzer/FileAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/FileAnalyzer.php @@ -32,7 +32,6 @@ use function array_diff_key; use function array_keys; use function count; -use function implode; use function strpos; use function strtolower; @@ -283,7 +282,7 @@ public function populateCheckers(array $stmts): array } elseif ($stmt instanceof PhpParser\Node\Stmt\ClassLike) { $this->populateClassLikeAnalyzers($stmt); } elseif ($stmt instanceof PhpParser\Node\Stmt\Namespace_) { - $namespace_name = $stmt->name ? implode('\\', $stmt->name->parts) : ''; + $namespace_name = $stmt->name ? $stmt->name->toString() : ''; $namespace_analyzer = new NamespaceAnalyzer($stmt, $this); $namespace_analyzer->collectAnalyzableInformation(); diff --git a/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php b/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php index 6b5d280992c..a01318a3e81 100644 --- a/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php @@ -14,7 +14,6 @@ use function assert; use function count; -use function implode; use function is_string; use function preg_replace; use function strpos; @@ -49,7 +48,7 @@ public function __construct(Namespace_ $namespace, FileAnalyzer $source) { $this->source = $source; $this->namespace = $namespace; - $this->namespace_name = $this->namespace->name ? implode('\\', $this->namespace->name->parts) : ''; + $this->namespace_name = $this->namespace->name ? $this->namespace->name->toString() : ''; } public function collectAnalyzableInformation(): void diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php index ea9e450f81e..e1c5e5e4024 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php @@ -238,13 +238,13 @@ private static function getDefinitelyEvaluatedExpressionAfterIf(PhpParser\Node\E || $stmt instanceof PhpParser\Node\Expr\BinaryOp\Identical ) { if ($stmt->left instanceof PhpParser\Node\Expr\ConstFetch - && $stmt->left->name->parts === ['true'] + && $stmt->left->name->getParts() === ['true'] ) { return self::getDefinitelyEvaluatedExpressionAfterIf($stmt->right); } if ($stmt->right instanceof PhpParser\Node\Expr\ConstFetch - && $stmt->right->name->parts === ['true'] + && $stmt->right->name->getParts() === ['true'] ) { return self::getDefinitelyEvaluatedExpressionAfterIf($stmt->left); } @@ -282,13 +282,13 @@ private static function getDefinitelyEvaluatedExpressionInsideIf(PhpParser\Node\ || $stmt instanceof PhpParser\Node\Expr\BinaryOp\Identical ) { if ($stmt->left instanceof PhpParser\Node\Expr\ConstFetch - && $stmt->left->name->parts === ['true'] + && $stmt->left->name->getParts() === ['true'] ) { return self::getDefinitelyEvaluatedExpressionInsideIf($stmt->right); } if ($stmt->right instanceof PhpParser\Node\Expr\ConstFetch - && $stmt->right->name->parts === ['true'] + && $stmt->right->name->getParts() === ['true'] ) { return self::getDefinitelyEvaluatedExpressionInsideIf($stmt->left); } diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php index 5fd9b4b1483..e116f1173f7 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php @@ -209,7 +209,7 @@ public static function analyze( } if ($switch_condition instanceof PhpParser\Node\Expr\ConstFetch - && $switch_condition->name->parts === ['true'] + && $switch_condition->name->getParts() === ['true'] ) { $case_equality_expr = $case->cond; } elseif (($switch_condition_type = $statements_analyzer->node_data->getType($switch_condition)) diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php index a1fd1707891..bb486123431 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php @@ -26,7 +26,8 @@ public static function analyze( PhpParser\Node\Stmt\While_ $stmt, Context $context ): ?bool { - $while_true = ($stmt->cond instanceof PhpParser\Node\Expr\ConstFetch && $stmt->cond->name->parts === ['true']) + $while_true = ($stmt->cond instanceof PhpParser\Node\Expr\ConstFetch + && $stmt->cond->name->getParts() === ['true']) || (($t = $statements_analyzer->node_data->getType($stmt->cond)) && $t->isAlwaysTruthy()); diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php b/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php index 911cecc4014..fc57f2177c7 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php @@ -830,7 +830,7 @@ public static function processFunctionCall( $if_types[$first_var_name] = [[new IsType(new TCallableString())]]; } } elseif ($expr->name instanceof PhpParser\Node\Name - && strtolower($expr->name->parts[0]) === 'method_exists' + && strtolower($expr->name->getFirst()) === 'method_exists' && isset($expr->getArgs()[1]) && $expr->getArgs()[1]->value instanceof PhpParser\Node\Scalar\String_ ) { @@ -1233,7 +1233,7 @@ protected static function getInstanceOfAssertions( FileSource $source ): array { if ($stmt->class instanceof PhpParser\Node\Name) { - if (!in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true)) { + if (!in_array(strtolower($stmt->class->getFirst()), ['self', 'static', 'parent'], true)) { $instanceof_class = ClassLikeAnalyzer::getFQCLNFromNameObject( $stmt->class, $source->getAliases(), @@ -1248,8 +1248,8 @@ protected static function getInstanceOfAssertions( } if ($this_class_name - && (in_array(strtolower($stmt->class->parts[0]), ['self', 'static'], true))) { - $is_static = $stmt->class->parts[0] === 'static'; + && (in_array(strtolower($stmt->class->getFirst()), ['self', 'static'], true))) { + $is_static = $stmt->class->getFirst() === 'static'; $named_object = new TNamedObject($this_class_name, $is_static); if ($is_static) { @@ -1297,13 +1297,13 @@ protected static function hasNullVariable( FileSource $source ): ?int { if ($conditional->right instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($conditional->right->name->parts[0]) === 'null' + && strtolower($conditional->right->name->getFirst()) === 'null' ) { return self::ASSIGNMENT_TO_RIGHT; } if ($conditional->left instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($conditional->left->name->parts[0]) === 'null' + && strtolower($conditional->left->name->getFirst()) === 'null' ) { return self::ASSIGNMENT_TO_LEFT; } @@ -1325,13 +1325,13 @@ public static function hasFalseVariable( PhpParser\Node\Expr\BinaryOp $conditional ): ?int { if ($conditional->right instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($conditional->right->name->parts[0]) === 'false' + && strtolower($conditional->right->name->getFirst()) === 'false' ) { return self::ASSIGNMENT_TO_RIGHT; } if ($conditional->left instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($conditional->left->name->parts[0]) === 'false' + && strtolower($conditional->left->name->getFirst()) === 'false' ) { return self::ASSIGNMENT_TO_LEFT; } @@ -1346,13 +1346,13 @@ public static function hasTrueVariable( PhpParser\Node\Expr\BinaryOp $conditional ): ?int { if ($conditional->right instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($conditional->right->name->parts[0]) === 'true' + && strtolower($conditional->right->name->getFirst()) === 'true' ) { return self::ASSIGNMENT_TO_RIGHT; } if ($conditional->left instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($conditional->left->name->parts[0]) === 'true' + && strtolower($conditional->left->name->getFirst()) === 'true' ) { return self::ASSIGNMENT_TO_LEFT; } @@ -1390,7 +1390,7 @@ protected static function hasGetTypeCheck( ) { if ($conditional->right instanceof PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof PhpParser\Node\Name - && strtolower($conditional->right->name->parts[0]) === 'gettype' + && strtolower($conditional->right->name->getFirst()) === 'gettype' && $conditional->right->getArgs() && $conditional->left instanceof PhpParser\Node\Scalar\String_ ) { @@ -1399,7 +1399,7 @@ protected static function hasGetTypeCheck( if ($conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name - && strtolower($conditional->left->name->parts[0]) === 'gettype' + && strtolower($conditional->left->name->getFirst()) === 'gettype' && $conditional->left->getArgs() && $conditional->right instanceof PhpParser\Node\Scalar\String_ ) { @@ -1418,7 +1418,7 @@ protected static function hasGetDebugTypeCheck( ) { if ($conditional->right instanceof PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof PhpParser\Node\Name - && strtolower($conditional->right->name->parts[0]) === 'get_debug_type' + && strtolower($conditional->right->name->getFirst()) === 'get_debug_type' && $conditional->right->getArgs() && ($conditional->left instanceof PhpParser\Node\Scalar\String_ || $conditional->left instanceof PhpParser\Node\Expr\ClassConstFetch) @@ -1428,7 +1428,7 @@ protected static function hasGetDebugTypeCheck( if ($conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name - && strtolower($conditional->left->name->parts[0]) === 'get_debug_type' + && strtolower($conditional->left->name->getFirst()) === 'get_debug_type' && $conditional->left->getArgs() && ($conditional->right instanceof PhpParser\Node\Scalar\String_ || $conditional->right instanceof PhpParser\Node\Expr\ClassConstFetch) @@ -1453,11 +1453,11 @@ protected static function hasGetClassCheck( $right_get_class = $conditional->right instanceof PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof PhpParser\Node\Name - && strtolower($conditional->right->name->parts[0]) === 'get_class'; + && strtolower($conditional->right->name->getFirst()) === 'get_class'; $right_static_class = $conditional->right instanceof PhpParser\Node\Expr\ClassConstFetch && $conditional->right->class instanceof PhpParser\Node\Name - && $conditional->right->class->parts === ['static'] + && $conditional->right->class->getParts() === ['static'] && $conditional->right->name instanceof PhpParser\Node\Identifier && strtolower($conditional->right->name->name) === 'class'; @@ -1492,11 +1492,11 @@ protected static function hasGetClassCheck( $left_get_class = $conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name - && strtolower($conditional->left->name->parts[0]) === 'get_class'; + && strtolower($conditional->left->name->getFirst()) === 'get_class'; $left_static_class = $conditional->left instanceof PhpParser\Node\Expr\ClassConstFetch && $conditional->left->class instanceof PhpParser\Node\Name - && $conditional->left->class->parts === ['static'] + && $conditional->left->class->getParts() === ['static'] && $conditional->left->name instanceof PhpParser\Node\Identifier && strtolower($conditional->left->name->name) === 'class'; @@ -1542,7 +1542,7 @@ protected static function hasNonEmptyCountEqualityCheck( ) { if ($conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name - && in_array(strtolower($conditional->left->name->parts[0]), ['count', 'sizeof']) + && in_array(strtolower($conditional->left->name->getFirst()), ['count', 'sizeof']) && $conditional->left->getArgs() && ($conditional instanceof BinaryOp\Greater || $conditional instanceof BinaryOp\GreaterOrEqual) ) { @@ -1551,7 +1551,7 @@ protected static function hasNonEmptyCountEqualityCheck( $comparison_adjustment = $conditional instanceof BinaryOp\Greater ? 1 : 0; } elseif ($conditional->right instanceof PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof PhpParser\Node\Name - && in_array(strtolower($conditional->right->name->parts[0]), ['count', 'sizeof']) + && in_array(strtolower($conditional->right->name->getFirst()), ['count', 'sizeof']) && $conditional->right->getArgs() && ($conditional instanceof BinaryOp\Smaller || $conditional instanceof BinaryOp\SmallerOrEqual) ) { @@ -1584,7 +1584,7 @@ protected static function hasLessThanCountEqualityCheck( ) { $left_count = $conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name - && in_array(strtolower($conditional->left->name->parts[0]), ['count', 'sizeof']) + && in_array(strtolower($conditional->left->name->getFirst()), ['count', 'sizeof']) && $conditional->left->getArgs(); $operator_less_than_or_equal = @@ -1603,7 +1603,7 @@ protected static function hasLessThanCountEqualityCheck( $right_count = $conditional->right instanceof PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof PhpParser\Node\Name - && in_array(strtolower($conditional->right->name->parts[0]), ['count', 'sizeof']) + && in_array(strtolower($conditional->right->name->getFirst()), ['count', 'sizeof']) && $conditional->right->getArgs(); $operator_greater_than_or_equal = @@ -1633,7 +1633,7 @@ protected static function hasCountEqualityCheck( ) { $left_count = $conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name - && in_array(strtolower($conditional->left->name->parts[0]), ['count', 'sizeof']) + && in_array(strtolower($conditional->left->name->getFirst()), ['count', 'sizeof']) && $conditional->left->getArgs(); if ($left_count && $conditional->right instanceof PhpParser\Node\Scalar\LNumber) { @@ -1644,7 +1644,7 @@ protected static function hasCountEqualityCheck( $right_count = $conditional->right instanceof PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof PhpParser\Node\Name - && in_array(strtolower($conditional->right->name->parts[0]), ['count', 'sizeof']) + && in_array(strtolower($conditional->right->name->getFirst()), ['count', 'sizeof']) && $conditional->right->getArgs(); if ($right_count && $conditional->left instanceof PhpParser\Node\Scalar\LNumber) { @@ -1785,7 +1785,7 @@ protected static function hasReconcilableNonEmptyCountEqualityCheck( ) { $left_count = $conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name - && in_array(strtolower($conditional->left->name->parts[0]), ['count', 'sizeof']); + && in_array(strtolower($conditional->left->name->getFirst()), ['count', 'sizeof']); $right_number = $conditional->right instanceof PhpParser\Node\Scalar\LNumber && $conditional->right->value === ( @@ -1841,8 +1841,8 @@ protected static function hasIsACheck( StatementsAnalyzer $source ): bool { if ($stmt->name instanceof PhpParser\Node\Name - && (strtolower($stmt->name->parts[0]) === 'is_a' - || strtolower($stmt->name->parts[0]) === 'is_subclass_of') + && (strtolower($stmt->name->getFirst()) === 'is_a' + || strtolower($stmt->name->getFirst()) === 'is_subclass_of') && isset($stmt->getArgs()[1]) ) { $second_arg = $stmt->getArgs()[1]->value; @@ -1920,7 +1920,7 @@ private static function handleIsTypeCheck( ): array { $if_types = []; if ($stmt->name instanceof PhpParser\Node\Name - && ($function_name = strtolower($stmt->name->parts[0])) + && ($function_name = strtolower($stmt->name->getFirst())) && ($assertion_type = self::getIsAssertion($function_name)) && $source instanceof StatementsAnalyzer && ($source->getNamespace() === null //either the namespace is null @@ -1954,7 +1954,7 @@ private static function handleIsTypeCheck( protected static function hasCallableCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { - return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->parts[0]) === 'is_callable'; + return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'is_callable'; } /** @@ -1963,7 +1963,7 @@ protected static function hasCallableCheck(PhpParser\Node\Expr\FuncCall $stmt): protected static function hasClassExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): int { if ($stmt->name instanceof PhpParser\Node\Name - && strtolower($stmt->name->parts[0]) === 'class_exists' + && strtolower($stmt->name->getFirst()) === 'class_exists' ) { if (!isset($stmt->getArgs()[1])) { return 2; @@ -1972,7 +1972,7 @@ protected static function hasClassExistsCheck(PhpParser\Node\Expr\FuncCall $stmt $second_arg = $stmt->getArgs()[1]->value; if ($second_arg instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($second_arg->name->parts[0]) === 'true' + && strtolower($second_arg->name->getFirst()) === 'true' ) { return 2; } @@ -1989,7 +1989,7 @@ protected static function hasClassExistsCheck(PhpParser\Node\Expr\FuncCall $stmt protected static function hasTraitExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): int { if ($stmt->name instanceof PhpParser\Node\Name - && strtolower($stmt->name->parts[0]) === 'trait_exists' + && strtolower($stmt->name->getFirst()) === 'trait_exists' ) { if (!isset($stmt->getArgs()[1])) { return 2; @@ -1998,7 +1998,7 @@ protected static function hasTraitExistsCheck(PhpParser\Node\Expr\FuncCall $stmt $second_arg = $stmt->getArgs()[1]->value; if ($second_arg instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($second_arg->name->parts[0]) === 'true' + && strtolower($second_arg->name->getFirst()) === 'true' ) { return 2; } @@ -2011,29 +2011,29 @@ protected static function hasTraitExistsCheck(PhpParser\Node\Expr\FuncCall $stmt protected static function hasEnumExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { - return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->parts[0]) === 'enum_exists'; + return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'enum_exists'; } protected static function hasInterfaceExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { - return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->parts[0]) === 'interface_exists'; + return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'interface_exists'; } protected static function hasFunctionExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { - return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->parts[0]) === 'function_exists'; + return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'function_exists'; } protected static function hasInArrayCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { if ($stmt->name instanceof PhpParser\Node\Name - && strtolower($stmt->name->parts[0]) === 'in_array' + && strtolower($stmt->name->getFirst()) === 'in_array' && isset($stmt->getArgs()[2]) ) { $second_arg = $stmt->getArgs()[2]->value; if ($second_arg instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($second_arg->name->parts[0]) === 'true' + && strtolower($second_arg->name->getFirst()) === 'true' ) { return true; } @@ -2045,12 +2045,12 @@ protected static function hasInArrayCheck(PhpParser\Node\Expr\FuncCall $stmt): b protected static function hasNonEmptyCountCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { return $stmt->name instanceof PhpParser\Node\Name && - in_array(strtolower($stmt->name->parts[0]), ['count', 'sizeof']); + in_array(strtolower($stmt->name->getFirst()), ['count', 'sizeof']); } protected static function hasArrayKeyExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { - return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->parts[0]) === 'array_key_exists'; + return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'array_key_exists'; } /** @@ -3550,8 +3550,8 @@ private static function getIsaAssertions( && $expr->getArgs()[0]->value->name instanceof PhpParser\Node\Identifier && strtolower($expr->getArgs()[0]->value->name->name) === 'class' && $expr->getArgs()[0]->value->class instanceof PhpParser\Node\Name - && count($expr->getArgs()[0]->value->class->parts) === 1 - && strtolower($expr->getArgs()[0]->value->class->parts[0]) === 'static' + && count($expr->getArgs()[0]->value->class->getParts()) === 1 + && strtolower($expr->getArgs()[0]->value->class->getFirst()) === 'static' ) { $first_var_name = '$this'; } @@ -3562,14 +3562,14 @@ private static function getIsaAssertions( $third_arg = $expr->getArgs()[2]->value ?? null; if ($third_arg instanceof PhpParser\Node\Expr\ConstFetch) { - if (!in_array(strtolower($third_arg->name->parts[0]), ['true', 'false'])) { + if (!in_array(strtolower($third_arg->name->getFirst()), ['true', 'false'])) { return []; } - $third_arg_value = strtolower($third_arg->name->parts[0]); + $third_arg_value = strtolower($third_arg->name->getFirst()); } else { $third_arg_value = $expr->name instanceof PhpParser\Node\Name - && strtolower($expr->name->parts[0]) === 'is_subclass_of' + && strtolower($expr->name->getFirst()) === 'is_subclass_of' ? 'true' : 'false'; } @@ -3596,18 +3596,18 @@ private static function getIsaAssertions( ) { $class_node = $second_arg->class; - if ($class_node->parts === ['static']) { + if ($class_node->getParts() === ['static']) { if ($this_class_name) { $object = new TNamedObject($this_class_name, true); $if_types[$first_var_name] = [[new IsAClass($object, $third_arg_value === 'true')]]; } - } elseif ($class_node->parts === ['self']) { + } elseif ($class_node->getParts() === ['self']) { if ($this_class_name) { $object = new TNamedObject($this_class_name); $if_types[$first_var_name] = [[new IsAClass($object, $third_arg_value === 'true')]]; } - } elseif ($class_node->parts === ['parent']) { + } elseif ($class_node->getParts() === ['parent']) { // do nothing } else { $object = new TNamedObject( diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php index 58e8ad5ab96..da8e3794b7c 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php @@ -261,7 +261,7 @@ public static function analyze( || $stmt instanceof PhpParser\Node\Expr\BinaryOp\NotIdentical) && $stmt->left instanceof PhpParser\Node\Expr\FuncCall && $stmt->left->name instanceof PhpParser\Node\Name - && $stmt->left->name->parts === ['substr'] + && $stmt->left->name->getParts() === ['substr'] && isset($stmt->left->getArgs()[1]) && $stmt_right_type && $stmt_right_type->hasLiteralString() diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php index 7ecfff037a3..59bb1a746c8 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php @@ -102,7 +102,7 @@ public static function analyze( && isset($stmt->getArgs()[0]) && !$stmt->getArgs()[0]->unpack ) { - $original_function_id = implode('\\', $function_name->parts); + $original_function_id = implode('\\', $function_name->getParts()); if ($original_function_id === 'call_user_func') { $other_args = array_slice($stmt->getArgs(), 1); @@ -160,7 +160,7 @@ public static function analyze( $set_inside_conditional = false; if ($function_name instanceof PhpParser\Node\Name - && $function_name->parts === ['assert'] + && $function_name->getParts() === ['assert'] && !$context->inside_conditional ) { $context->inside_conditional = true; @@ -319,7 +319,7 @@ public static function analyze( } if ($function_name instanceof PhpParser\Node\Name - && $function_name->parts === ['assert'] + && $function_name->getParts() === ['assert'] && isset($stmt->getArgs()[0]) ) { self::processAssertFunctionEffects( @@ -437,7 +437,7 @@ private static function handleNamedFunction( $codebase = $statements_analyzer->getCodebase(); $codebase_functions = $codebase->functions; - $original_function_id = implode('\\', $function_name->parts); + $original_function_id = $function_name->toString(); if (!$function_name instanceof PhpParser\Node\Name\FullyQualified) { $function_call_info->function_id = $codebase_functions->getFullyQualifiedFunctionNameFromString( @@ -487,7 +487,7 @@ private static function handleNamedFunction( $is_predefined = true; $is_maybe_root_function = !$function_name instanceof PhpParser\Node\Name\FullyQualified - && count($function_name->parts) === 1; + && count($function_name->getParts()) === 1; $args = $stmt->isFirstClassCallable() ? [] : $stmt->getArgs(); diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php index b521f8bc0f7..45476ca22b6 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php @@ -58,7 +58,6 @@ use function array_map; use function array_values; -use function implode; use function in_array; use function md5; use function preg_match; @@ -94,7 +93,7 @@ public static function analyze( } if ($stmt->class instanceof PhpParser\Node\Name) { - if (!in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true)) { + if (!in_array(strtolower($stmt->class->getFirst()), ['self', 'static', 'parent'], true)) { $aliases = $statements_analyzer->getAliases(); if ($context->calling_method_id @@ -102,7 +101,7 @@ public static function analyze( ) { $codebase->file_reference_provider->addMethodReferenceToClassMember( $context->calling_method_id, - 'use:' . $stmt->class->parts[0] . ':' . md5($statements_analyzer->getFilePath()), + 'use:' . $stmt->class->getFirst() . ':' . md5($statements_analyzer->getFilePath()), false, ); } @@ -114,7 +113,7 @@ public static function analyze( $fq_class_name = $codebase->classlikes->getUnAliasedName($fq_class_name); } elseif ($context->self !== null) { - switch ($stmt->class->parts[0]) { + switch ($stmt->class->getFirst()) { case 'self': $class_storage = $codebase->classlike_storage_provider->get($context->self); $fq_class_name = $class_storage->name; @@ -152,7 +151,7 @@ public static function analyze( . ($stmt->class instanceof PhpParser\Node\Name\FullyQualified ? '\\' : $statements_analyzer->getNamespace() . '-') - . implode('\\', $stmt->class->parts), + . $stmt->class->toString(), ); } } elseif ($stmt->class instanceof PhpParser\Node\Stmt\Class_) { @@ -174,7 +173,7 @@ public static function analyze( if ($fq_class_name) { if ($codebase->alter_code && $stmt->class instanceof PhpParser\Node\Name - && !in_array($stmt->class->parts[0], ['parent', 'static']) + && !in_array($stmt->class->getFirst(), ['parent', 'static']) ) { $codebase->classlikes->handleClassLikeReferenceInMigration( $codebase, diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php index a79f2760e53..fa7cc498184 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php @@ -56,10 +56,10 @@ public static function analyze( if ($stmt->class instanceof PhpParser\Node\Name) { $fq_class_name = null; - if (count($stmt->class->parts) === 1 - && in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true) + if (count($stmt->class->getParts()) === 1 + && in_array(strtolower($stmt->class->getFirst()), ['self', 'static', 'parent'], true) ) { - if ($stmt->class->parts[0] === 'parent') { + if ($stmt->class->getFirst() === 'parent') { $child_fq_class_name = $context->self; $class_storage = $child_fq_class_name @@ -84,7 +84,7 @@ public static function analyze( $fq_class_name = $class_storage->name; } elseif ($context->self) { - if ($stmt->class->parts[0] === 'static' && isset($context->vars_in_scope['$this'])) { + if ($stmt->class->getFirst() === 'static' && isset($context->vars_in_scope['$this'])) { $fq_class_name = (string) $context->vars_in_scope['$this']; $lhs_type = $context->vars_in_scope['$this']; } else { @@ -93,7 +93,7 @@ public static function analyze( } else { return !IssueBuffer::accepts( new NonStaticSelfCall( - 'Cannot use ' . $stmt->class->parts[0] . ' outside class context', + 'Cannot use ' . $stmt->class->getFirst() . ' outside class context', new CodeLocation($statements_analyzer->getSource(), $stmt), ), $statements_analyzer->getSuppressedIssues(), @@ -111,7 +111,7 @@ public static function analyze( ) { $codebase->file_reference_provider->addMethodReferenceToClassMember( $context->calling_method_id, - 'use:' . $stmt->class->parts[0] . ':' . md5($statements_analyzer->getFilePath()), + 'use:' . $stmt->class->getFirst() . ':' . md5($statements_analyzer->getFilePath()), false, ); } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php index 52a87e9abc9..b0839345418 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php @@ -99,8 +99,8 @@ public static function analyze( $statements_analyzer->getSuppressedIssues(), new ClassLikeNameOptions( $stmt->class instanceof PhpParser\Node\Name - && count($stmt->class->parts) === 1 - && in_array(strtolower($stmt->class->parts[0]), ['self', 'static'], true), + && count($stmt->class->getParts()) === 1 + && in_array(strtolower($stmt->class->getFirst()), ['self', 'static'], true), ), )) { return; @@ -284,7 +284,7 @@ public static function analyze( && $fq_class_name && !$moved_call && $stmt->class instanceof PhpParser\Node\Name - && !in_array($stmt->class->parts[0], ['parent', 'static']) + && !in_array($stmt->class->getFirst(), ['parent', 'static']) ) { $codebase->classlikes->handleClassLikeReferenceInMigration( $codebase, @@ -293,7 +293,7 @@ public static function analyze( $fq_class_name, $context->calling_method_id, false, - $stmt->class->parts[0] === 'self', + $stmt->class->getFirst() === 'self', ); } } @@ -718,7 +718,7 @@ private static function handleNamedCall( if ($pseudo_method_storage->return_type) { return true; } - } elseif ($stmt->class instanceof PhpParser\Node\Name && $stmt->class->parts[0] === 'parent' + } elseif ($stmt->class instanceof PhpParser\Node\Name && $stmt->class->getFirst() === 'parent' && !$codebase->methodExists($method_id) && !$statements_analyzer->isStatic() ) { @@ -846,7 +846,7 @@ private static function handleNamedCall( } if ((!$stmt->class instanceof PhpParser\Node\Name - || $stmt->class->parts[0] !== 'parent' + || $stmt->class->getFirst() !== 'parent' || $statements_analyzer->isStatic()) && ( !$context->self @@ -857,7 +857,7 @@ private static function handleNamedCall( MethodAnalyzer::checkStatic( $method_id, ($stmt->class instanceof PhpParser\Node\Name - && strtolower($stmt->class->parts[0]) === 'self') + && strtolower($stmt->class->getFirst()) === 'self') || $context->self === $fq_class_name, !$statements_analyzer->isStatic(), $codebase, diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php index 0a604e088da..607f521881a 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php @@ -156,7 +156,7 @@ public static function analyze( if ($found_generic_params && $stmt->class instanceof PhpParser\Node\Name - && $stmt->class->parts === ['parent'] + && $stmt->class->getParts() === ['parent'] && $context->self && ($self_class_storage = $codebase->classlike_storage_provider->get($context->self)) && $self_class_storage->template_extended_params @@ -201,7 +201,7 @@ public static function analyze( return; } - $fq_class_name = $stmt->class instanceof PhpParser\Node\Name && $stmt->class->parts === ['parent'] + $fq_class_name = $stmt->class instanceof PhpParser\Node\Name && $stmt->class->getParts() === ['parent'] ? (string) $statements_analyzer->getFQCLN() : $fq_class_name; @@ -371,7 +371,7 @@ public static function analyze( $new_fq_class_name, $context->calling_method_id, strtolower($old_declaring_fq_class_name) !== strtolower($new_fq_class_name), - $stmt->class->parts[0] === 'self', + $stmt->class->getFirst() === 'self', )) { $moved_call = true; } @@ -519,8 +519,8 @@ private static function getMethodReturnType( $lhs_type_part->defining_class, ); } elseif ($stmt->class instanceof PhpParser\Node\Name - && count($stmt->class->parts) === 1 - && in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true) + && count($stmt->class->getParts()) === 1 + && in_array(strtolower($stmt->class->getFirst()), ['self', 'static', 'parent'], true) && $lhs_type_part instanceof TNamedObject && $context->self ) { diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php index 348f528c68e..a547b291cb5 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php @@ -505,7 +505,7 @@ public static function getFunctionIdsFromCallableArg( && $callable_arg->left->class instanceof Name && $callable_arg->left->name instanceof Identifier && strtolower($callable_arg->left->name->name) === 'class' - && !in_array(strtolower($callable_arg->left->class->parts[0]), ['self', 'static', 'parent']) + && !in_array(strtolower($callable_arg->left->class->getFirst()), ['self', 'static', 'parent']) && $callable_arg->right instanceof PhpParser\Node\Scalar\String_ && preg_match('/^::[A-Za-z0-9]+$/', $callable_arg->right->value) ) { diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/ClassConstAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/ClassConstAnalyzer.php index 0af910bdae7..2dec200fc9c 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/ClassConstAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/ClassConstAnalyzer.php @@ -72,7 +72,7 @@ public static function analyzeFetch( $statements_analyzer->node_data->setType($stmt, Type::getMixed()); if ($stmt->class instanceof PhpParser\Node\Name) { - $first_part_lc = strtolower($stmt->class->parts[0]); + $first_part_lc = strtolower($stmt->class->getFirst()); if ($first_part_lc === 'self' || $first_part_lc === 'static') { if (!$context->self) { @@ -128,7 +128,7 @@ public static function analyzeFetch( $moved_class = false; if ($codebase->alter_code - && !in_array($stmt->class->parts[0], ['parent', 'static']) + && !in_array($stmt->class->getFirst(), ['parent', 'static']) ) { $moved_class = $codebase->classlikes->handleClassLikeReferenceInMigration( $codebase, @@ -137,7 +137,7 @@ public static function analyzeFetch( $fq_class_name, $context->calling_method_id, false, - $stmt->class->parts[0] === 'self', + $stmt->class->getFirst() === 'self', ); } @@ -259,7 +259,7 @@ public static function analyzeFetch( $class_visibility, $statements_analyzer, [], - $stmt->class->parts[0] === "static", + $stmt->class->getFirst() === "static", ); } catch (InvalidArgumentException $_) { return true; diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/ExpressionIdentifier.php b/src/Psalm/Internal/Analyzer/Statements/Expression/ExpressionIdentifier.php index 04b808c32ad..53794faa358 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/ExpressionIdentifier.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/ExpressionIdentifier.php @@ -33,11 +33,11 @@ public static function getVarId( && $stmt->name instanceof PhpParser\Node\Identifier && $stmt->class instanceof PhpParser\Node\Name ) { - if (count($stmt->class->parts) === 1 - && in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true) + if (count($stmt->class->getParts()) === 1 + && in_array(strtolower($stmt->class->getFirst()), ['self', 'static', 'parent'], true) ) { if (!$this_class_name) { - $fq_class_name = $stmt->class->parts[0]; + $fq_class_name = $stmt->class->getFirst(); } else { $fq_class_name = $this_class_name; } @@ -47,7 +47,7 @@ public static function getVarId( $stmt->class, $source->getAliases(), ) - : implode('\\', $stmt->class->parts); + : implode('\\', $stmt->class->getParts()); } return $fq_class_name . '::$' . $stmt->name->name; @@ -124,7 +124,7 @@ public static function getExtendedVarId( ) { $offset = '$' . $stmt->dim->name; } elseif ($stmt->dim instanceof PhpParser\Node\Expr\ConstFetch) { - $offset = implode('\\', $stmt->dim->name->parts); + $offset = implode('\\', $stmt->dim->name->getParts()); } elseif ($stmt->dim instanceof PhpParser\Node\Expr\PropertyFetch) { $object_id = self::getExtendedVarId($stmt->dim->var, $this_class_name, $source); @@ -134,7 +134,7 @@ public static function getExtendedVarId( } elseif ($stmt->dim instanceof PhpParser\Node\Expr\ClassConstFetch && $stmt->dim->name instanceof PhpParser\Node\Identifier && $stmt->dim->class instanceof PhpParser\Node\Name - && $stmt->dim->class->parts[0] === 'static' + && $stmt->dim->class->getFirst() === 'static' ) { $offset = 'static::' . $stmt->dim->name; } elseif ($stmt->dim diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ConstFetchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ConstFetchAnalyzer.php index 78076e899f0..8b30a60fc91 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ConstFetchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ConstFetchAnalyzer.php @@ -35,7 +35,7 @@ public static function analyze( PhpParser\Node\Expr\ConstFetch $stmt, Context $context ): void { - $const_name = implode('\\', $stmt->name->parts); + $const_name = $stmt->name->toString(); switch (strtolower($const_name)) { case 'null': diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/StaticPropertyFetchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/StaticPropertyFetchAnalyzer.php index 84ab1558c6e..46a4cf0f414 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/StaticPropertyFetchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/StaticPropertyFetchAnalyzer.php @@ -51,10 +51,10 @@ public static function analyze( $codebase = $statements_analyzer->getCodebase(); - if (count($stmt->class->parts) === 1 - && in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true) + if (count($stmt->class->getParts()) === 1 + && in_array(strtolower($stmt->class->getFirst()), ['self', 'static', 'parent'], true) ) { - if ($stmt->class->parts[0] === 'parent') { + if ($stmt->class->getFirst() === 'parent') { $fq_class_name = $statements_analyzer->getParentFQCLN(); if ($fq_class_name === null) { @@ -81,7 +81,7 @@ public static function analyze( ) { $codebase->file_reference_provider->addMethodReferenceToClassMember( $context->calling_method_id, - 'use:' . $stmt->class->parts[0] . ':' . md5($statements_analyzer->getFilePath()), + 'use:' . $stmt->class->getFirst() . ':' . md5($statements_analyzer->getFilePath()), false, ); } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php index 1a5220275dc..e293afabc58 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php @@ -335,7 +335,7 @@ public static function getPathTo( } } elseif ($stmt instanceof PhpParser\Node\Expr\FuncCall && $stmt->name instanceof PhpParser\Node\Name && - $stmt->name->parts === ['dirname'] + $stmt->name->getParts() === ['dirname'] ) { if ($stmt->getArgs()) { $dir_level = 1; @@ -376,7 +376,7 @@ public static function getPathTo( return dirname($evaled_path, $dir_level); } } elseif ($stmt instanceof PhpParser\Node\Expr\ConstFetch) { - $const_name = implode('', $stmt->name->parts); + $const_name = implode('', $stmt->name->getParts()); if (defined($const_name)) { $constant_value = constant($const_name); diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/InstanceofAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/InstanceofAnalyzer.php index 380279b7b1f..83b04cd9478 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/InstanceofAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/InstanceofAnalyzer.php @@ -39,7 +39,7 @@ public static function analyze( if (ExpressionAnalyzer::analyze($statements_analyzer, $stmt->class, $context) === false) { return false; } - } elseif (!in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true)) { + } elseif (!in_array(strtolower($stmt->class->getFirst()), ['self', 'static', 'parent'], true)) { if ($context->check_classes) { $codebase = $statements_analyzer->getCodebase(); @@ -62,7 +62,7 @@ public static function analyze( . ($stmt->class instanceof PhpParser\Node\Name\FullyQualified ? '\\' : $statements_analyzer->getNamespace() . '-') - . implode('\\', $stmt->class->parts), + . implode('\\', $stmt->class->getParts()), ); } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php index 91ec38b469a..a76a199089a 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php @@ -78,11 +78,11 @@ public static function analyze( if (!$switch_var_id) { if ($stmt->cond instanceof PhpParser\Node\Expr\FuncCall && $stmt->cond->name instanceof PhpParser\Node\Name - && ($stmt->cond->name->parts === ['get_class'] - || $stmt->cond->name->parts === ['gettype'] - || $stmt->cond->name->parts === ['get_debug_type'] - || $stmt->cond->name->parts === ['count'] - || $stmt->cond->name->parts === ['sizeof']) + && ($stmt->cond->name->getParts() === ['get_class'] + || $stmt->cond->name->getParts() === ['gettype'] + || $stmt->cond->name->getParts() === ['get_debug_type'] + || $stmt->cond->name->getParts() === ['count'] + || $stmt->cond->name->getParts() === ['sizeof']) && $stmt->cond->getArgs() ) { $first_arg = $stmt->cond->getArgs()[0]; diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php index ddab4d02b66..ab144621edb 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php @@ -260,7 +260,7 @@ public static function infer( } if ($stmt instanceof PhpParser\Node\Expr\ConstFetch) { - $name = strtolower($stmt->name->parts[0]); + $name = strtolower($stmt->name->getFirst()); if ($name === 'false') { return Type::getFalse(); } @@ -273,7 +273,7 @@ public static function infer( return Type::getNull(); } - if ($stmt->name->parts[0] === '__NAMESPACE__') { + if ($stmt->name->getFirst() === '__NAMESPACE__') { return Type::getString($aliases->namespace); } @@ -306,18 +306,18 @@ public static function infer( if ($stmt->class instanceof PhpParser\Node\Name && $stmt->name instanceof PhpParser\Node\Identifier && $fq_classlike_name - && $stmt->class->parts !== ['static'] - && $stmt->class->parts !== ['parent'] + && $stmt->class->getParts() !== ['static'] + && $stmt->class->getParts() !== ['parent'] ) { if (isset($existing_class_constants[$stmt->name->name]) && $existing_class_constants[$stmt->name->name]->type ) { - if ($stmt->class->parts === ['self']) { + if ($stmt->class->getParts() === ['self']) { return $existing_class_constants[$stmt->name->name]->type; } } - if ($stmt->class->parts === ['self']) { + if ($stmt->class->getParts() === ['self']) { $const_fq_class_name = $fq_classlike_name; } else { $const_fq_class_name = ClassLikeAnalyzer::getFQCLNFromNameObject( diff --git a/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php b/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php index 2b43d0857e8..f1d4044bfc1 100644 --- a/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php @@ -304,7 +304,7 @@ private static function hoistConstants( } elseif ($stmt instanceof PhpParser\Node\Stmt\Expression && $stmt->expr instanceof PhpParser\Node\Expr\FuncCall && $stmt->expr->name instanceof PhpParser\Node\Name - && $stmt->expr->name->parts === ['define'] + && $stmt->expr->name->getParts() === ['define'] && isset($stmt->expr->getArgs()[1]) ) { $const_name = ConstFetchAnalyzer::getConstName( diff --git a/src/Psalm/Internal/Diff/FileStatementsDiffer.php b/src/Psalm/Internal/Diff/FileStatementsDiffer.php index d1864043446..797b6f73012 100644 --- a/src/Psalm/Internal/Diff/FileStatementsDiffer.php +++ b/src/Psalm/Internal/Diff/FileStatementsDiffer.php @@ -129,7 +129,7 @@ static function ( if ($use->alias) { $add_or_delete[] = 'use:' . (string) $use->alias; } else { - $name_parts = $use->name->parts; + $name_parts = $use->name->getParts(); $add_or_delete[] = 'use:' . end($name_parts); } @@ -156,7 +156,7 @@ static function ( if ($use->alias) { $add_or_delete[] = 'use:' . (string) $use->alias; } else { - $name_parts = $use->name->parts; + $name_parts = $use->name->getParts(); $add_or_delete[] = 'use:' . end($name_parts); } diff --git a/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php b/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php index 4232a405713..cfeab6123e2 100644 --- a/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php +++ b/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php @@ -114,7 +114,7 @@ static function ( if ($use->alias) { $add_or_delete[] = 'use:' . (string) $use->alias; } else { - $name_parts = $use->name->parts; + $name_parts = $use->name->getParts(); $add_or_delete[] = 'use:' . end($name_parts); } @@ -128,7 +128,7 @@ static function ( if ($use->alias) { $add_or_delete[] = 'use:' . (string) $use->alias; } else { - $name_parts = $use->name->parts; + $name_parts = $use->name->getParts(); $add_or_delete[] = 'use:' . end($name_parts); } diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php b/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php index 93a0ddcecd4..ac05615b4fe 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php @@ -38,7 +38,6 @@ use function class_exists; use function function_exists; use function get_defined_constants; -use function implode; use function in_array; use function interface_exists; use function strtolower; @@ -142,7 +141,7 @@ public static function getUnresolvedClassConstExpr( } if ($stmt instanceof PhpParser\Node\Expr\ConstFetch) { - $part0_lc = strtolower($stmt->name->parts[0]); + $part0_lc = strtolower($stmt->name->getFirst()); if ($part0_lc === 'false') { return new ScalarValue(false); } @@ -160,7 +159,7 @@ public static function getUnresolvedClassConstExpr( } return new Constant( - implode('\\', $stmt->name->parts), + $stmt->name->toString(), $stmt->name instanceof PhpParser\Node\Name\FullyQualified, ); } @@ -193,13 +192,13 @@ public static function getUnresolvedClassConstExpr( if ($stmt->class instanceof PhpParser\Node\Name && $stmt->name instanceof PhpParser\Node\Identifier && $fq_classlike_name - && $stmt->class->parts !== ['static'] - && ($stmt->class->parts !== ['parent'] || $parent_fq_class_name !== null) + && $stmt->class->getParts() !== ['static'] + && ($stmt->class->getParts() !== ['parent'] || $parent_fq_class_name !== null) ) { - if ($stmt->class->parts === ['self']) { + if ($stmt->class->getParts() === ['self']) { $const_fq_class_name = $fq_classlike_name; } else { - if ($stmt->class->parts === ['parent']) { + if ($stmt->class->getParts() === ['parent']) { assert($parent_fq_class_name !== null); $const_fq_class_name = $parent_fq_class_name; } else { @@ -309,15 +308,15 @@ public static function getUnresolvedClassConstExpr( && $stmt->var->name instanceof PhpParser\Node\Identifier && $stmt->name instanceof PhpParser\Node\Identifier && in_array($stmt->name->name, ['name', 'value'], true) - && ($stmt->var->class->parts !== ['self'] || $fq_classlike_name !== null) - && $stmt->var->class->parts !== ['static'] - && ($stmt->var->class->parts !== ['parent'] || $parent_fq_class_name !== null) + && ($stmt->var->class->getParts() !== ['self'] || $fq_classlike_name !== null) + && $stmt->var->class->getParts() !== ['static'] + && ($stmt->var->class->getParts() !== ['parent'] || $parent_fq_class_name !== null) ) { - if ($stmt->var->class->parts === ['self']) { + if ($stmt->var->class->getParts() === ['self']) { assert($fq_classlike_name !== null); $enum_fq_class_name = $fq_classlike_name; } else { - if ($stmt->var->class->parts === ['parent']) { + if ($stmt->var->class->getParts() === ['parent']) { assert($parent_fq_class_name !== null); $enum_fq_class_name = $parent_fq_class_name; } else { @@ -371,18 +370,18 @@ public static function enterConditional( ) && ( ( $expr->left instanceof PhpParser\Node\Expr\ConstFetch - && $expr->left->name->parts === ['PHP_VERSION_ID'] + && $expr->left->name->getParts() === ['PHP_VERSION_ID'] && $expr->right instanceof PhpParser\Node\Scalar\LNumber ) || ( $expr->right instanceof PhpParser\Node\Expr\ConstFetch - && $expr->right->name->parts === ['PHP_VERSION_ID'] + && $expr->right->name->getParts() === ['PHP_VERSION_ID'] && $expr->left instanceof PhpParser\Node\Scalar\LNumber ) ) ) { $php_version_id = $codebase->analysis_php_version_id; $evaluator = new ConstExprEvaluator(static function (Expr $expr) use ($php_version_id) { - if ($expr instanceof ConstFetch && $expr->name->parts === ['PHP_VERSION_ID']) { + if ($expr instanceof ConstFetch && $expr->name->getParts() === ['PHP_VERSION_ID']) { return $php_version_id; } throw new ConstExprEvaluationException('unexpected'); @@ -411,7 +410,7 @@ private static function functionEvaluatesToTrue( return null; } - if ($function->name->parts === ['function_exists'] + if ($function->name->getParts() === ['function_exists'] && isset($function->getArgs()[0]) && $function->getArgs()[0]->value instanceof PhpParser\Node\Scalar\String_ && function_exists($function->getArgs()[0]->value->value) @@ -425,7 +424,7 @@ private static function functionEvaluatesToTrue( return false; } - if ($function->name->parts === ['class_exists'] + if ($function->name->getParts() === ['class_exists'] && isset($function->getArgs()[0]) ) { $string_value = null; @@ -455,7 +454,7 @@ private static function functionEvaluatesToTrue( return false; } - if ($function->name->parts === ['interface_exists'] + if ($function->name->getParts() === ['interface_exists'] && isset($function->getArgs()[0]) ) { $string_value = null; @@ -485,7 +484,7 @@ private static function functionEvaluatesToTrue( return false; } - if ($function->name->parts === ['enum_exists'] + if ($function->name->getParts() === ['enum_exists'] && isset($function->getArgs()[0]) ) { $string_value = null; @@ -517,7 +516,7 @@ private static function functionEvaluatesToTrue( return false; } - if ($function->name->parts === ['defined'] + if ($function->name->getParts() === ['defined'] && isset($function->getArgs()[0]) && $function->getArgs()[0]->value instanceof PhpParser\Node\Scalar\String_ ) { diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php b/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php index d37bd9a9141..e0add3a00e4 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php @@ -23,7 +23,6 @@ use function defined; use function dirname; use function explode; -use function implode; use function in_array; use function preg_match; use function strpos; @@ -80,7 +79,7 @@ public static function scan( $file_storage->referenced_classlikes[strtolower($fq_classlike_name)] = $fq_classlike_name; } } elseif ($node instanceof PhpParser\Node\Expr\FuncCall && $node->name instanceof PhpParser\Node\Name) { - $function_id = implode('\\', $node->name->parts); + $function_id = $node->name->toString(); if (InternalCallMapHandler::inCallMap($function_id)) { self::registerClassMapFunctionCall( diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php index ed3463b94c0..e0ba4e3478b 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php @@ -57,7 +57,6 @@ use function count; use function end; use function explode; -use function implode; use function in_array; use function is_string; use function spl_object_id; @@ -371,7 +370,7 @@ public function start(PhpParser\Node\FunctionLike $stmt, bool $fake_method = fal && $function_stmt->expr->expr instanceof PhpParser\Node\Expr\FuncCall && $function_stmt->expr->expr->name instanceof PhpParser\Node\Name ) { - $inner_function_id = implode('\\', $function_stmt->expr->expr->name->parts); + $inner_function_id = $function_stmt->expr->expr->name->toString(); if ($inner_function_id === 'func_get_arg' || $inner_function_id === 'func_get_args' @@ -385,7 +384,7 @@ public function start(PhpParser\Node\FunctionLike $stmt, bool $fake_method = fal && $function_stmt->cond->left->left instanceof PhpParser\Node\Expr\FuncCall && $function_stmt->cond->left->left->name instanceof PhpParser\Node\Name ) { - $inner_function_id = implode('\\', $function_stmt->cond->left->left->name->parts); + $inner_function_id = $function_stmt->cond->left->left->name->toString(); if ($inner_function_id === 'func_get_arg' || $inner_function_id === 'func_get_args' @@ -806,7 +805,7 @@ private function getTranslatedFunctionParam( $param_type = null; $is_nullable = $param->default instanceof PhpParser\Node\Expr\ConstFetch && - strtolower($param->default->name->parts[0]) === 'null'; + strtolower($param->default->name->getFirst()) === 'null'; $param_typehint = $param->type; diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/TypeHintResolver.php b/src/Psalm/Internal/PhpVisitor/Reflector/TypeHintResolver.php index 7ae1e78ee10..3e5fcef5d45 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/TypeHintResolver.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/TypeHintResolver.php @@ -21,7 +21,6 @@ use Psalm\Type\Union; use UnexpectedValueException; -use function implode; use function strtolower; /** @@ -137,7 +136,7 @@ public static function resolve( $codebase->scanner->queueClassLikeForScanning($fq_type_string); $file_storage->referenced_classlikes[strtolower($fq_type_string)] = $fq_type_string; } else { - $lower_hint = strtolower($hint->parts[0]); + $lower_hint = strtolower($hint->getFirst()); if ($classlike_storage && ($lower_hint === 'self' || $lower_hint === 'static') @@ -149,7 +148,7 @@ public static function resolve( $fq_type_string .= '&static'; } } else { - $type_string = implode('\\', $hint->parts); + $type_string = $hint->toString(); $fq_type_string = ClassLikeAnalyzer::getFQCLNFromNameObject($hint, $aliases); $codebase->scanner->queueClassLikeForScanning($fq_type_string); diff --git a/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php b/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php index 989bae6e232..734c14d8b11 100644 --- a/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php @@ -39,7 +39,6 @@ use function end; use function explode; use function get_class; -use function implode; use function in_array; use function is_string; use function reset; @@ -395,7 +394,7 @@ private function handleNamespace(PhpParser\Node\Stmt\Namespace_ $node): void $this->namespace_name = $node->name; $this->aliases = new Aliases( - $node->name ? implode('\\', $node->name->parts) : '', + $node->name ? $node->name->toString() : '', $this->aliases->uses, $this->aliases->functions, $this->aliases->constants, @@ -414,7 +413,7 @@ private function handleNamespace(PhpParser\Node\Stmt\Namespace_ $node): void private function handleUse(PhpParser\Node\Stmt\Use_ $node): void { foreach ($node->uses as $use) { - $use_path = implode('\\', $use->name->parts); + $use_path = $use->name->toString(); $use_alias = $use->alias->name ?? $use->name->getLast(); @@ -445,10 +444,10 @@ private function handleUse(PhpParser\Node\Stmt\Use_ $node): void private function handleGroupUse(PhpParser\Node\Stmt\GroupUse $node): void { - $use_prefix = implode('\\', $node->prefix->parts); + $use_prefix = $node->prefix->toString(); foreach ($node->uses as $use) { - $use_path = $use_prefix . '\\' . implode('\\', $use->name->parts); + $use_path = $use_prefix . '\\' . $use->name->toString(); $use_alias = $use->alias->name ?? $use->name->getLast(); switch ($use->type !== PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN ? $use->type : $node->type) { @@ -490,13 +489,13 @@ public function leaveNode(PhpParser\Node $node) if ($this->codebase->register_stub_files && $node->name - && $node->name->parts === ['PHPSTORM_META'] + && $node->name->getParts() === ['PHPSTORM_META'] ) { foreach ($node->stmts as $meta_stmt) { if ($meta_stmt instanceof PhpParser\Node\Stmt\Expression && $meta_stmt->expr instanceof PhpParser\Node\Expr\FuncCall && $meta_stmt->expr->name instanceof Name - && $meta_stmt->expr->name->parts === ['override'] + && $meta_stmt->expr->name->getParts() === ['override'] ) { PhpStormMetaScanner::handleOverride($meta_stmt->expr->getArgs(), $this->codebase); } diff --git a/src/Psalm/Internal/Provider/AddRemoveTaints/HtmlFunctionTainter.php b/src/Psalm/Internal/Provider/AddRemoveTaints/HtmlFunctionTainter.php index c96a50f1d52..1f862278d48 100644 --- a/src/Psalm/Internal/Provider/AddRemoveTaints/HtmlFunctionTainter.php +++ b/src/Psalm/Internal/Provider/AddRemoveTaints/HtmlFunctionTainter.php @@ -32,13 +32,13 @@ public static function addTaints(AddRemoveTaintsEvent $event): array || !$item instanceof PhpParser\Node\Expr\FuncCall || $item->isFirstClassCallable() || !$item->name instanceof PhpParser\Node\Name - || count($item->name->parts) !== 1 + || count($item->name->getParts()) !== 1 || count($item->getArgs()) === 0 ) { return []; } - $function_id = strtolower($item->name->parts[0]); + $function_id = strtolower($item->name->getFirst()); if ($function_id === 'html_entity_decode' || $function_id === 'htmlspecialchars_decode' @@ -84,13 +84,13 @@ public static function removeTaints(AddRemoveTaintsEvent $event): array || !$item instanceof PhpParser\Node\Expr\FuncCall || $item->isFirstClassCallable() || !$item->name instanceof PhpParser\Node\Name - || count($item->name->parts) !== 1 + || count($item->name->getParts()) !== 1 || count($item->getArgs()) === 0 ) { return []; } - $function_id = strtolower($item->name->parts[0]); + $function_id = strtolower($item->name->getFirst()); if ($function_id === 'htmlentities' || $function_id === 'htmlspecialchars' diff --git a/src/Psalm/Internal/Scanner/PhpStormMetaScanner.php b/src/Psalm/Internal/Scanner/PhpStormMetaScanner.php index 5058e67ce8e..b812456d7af 100644 --- a/src/Psalm/Internal/Scanner/PhpStormMetaScanner.php +++ b/src/Psalm/Internal/Scanner/PhpStormMetaScanner.php @@ -15,7 +15,6 @@ use ReflectionProperty; use function count; -use function implode; use function is_string; use function str_replace; use function strpos; @@ -45,7 +44,7 @@ public static function handleOverride(array $args, Codebase $codebase): void $map = []; - if ($args[1]->value->name->parts === ['map'] + if ($args[1]->value->name->getParts() === ['map'] && $args[1]->value->getArgs() && $args[1]->value->getArgs()[0]->value instanceof PhpParser\Node\Expr\Array_ ) { @@ -59,7 +58,7 @@ public static function handleOverride(array $args, Codebase $codebase): void && strtolower($array_item->value->name->name) ) { $map[$array_item->key->value] = new Union([ - new TNamedObject(implode('\\', $array_item->value->class->parts)), + new TNamedObject($array_item->value->class->toString()), ]); } elseif ($array_item->value instanceof PhpParser\Node\Scalar\String_) { $map[$array_item->key->value] = $array_item->value->value; @@ -93,7 +92,7 @@ public static function handleOverride(array $args, Codebase $codebase): void && strtolower($array_item->value->name->name) ) { $map[$meta_key] = new Union([ - new TNamedObject(implode('\\', $array_item->value->class->parts)), + new TNamedObject($array_item->value->class->toString()), ]); } elseif ($array_item->value instanceof PhpParser\Node\Scalar\String_) { $map[$meta_key] = $array_item->value->value; @@ -104,7 +103,7 @@ public static function handleOverride(array $args, Codebase $codebase): void $type_offset = null; - if ($args[1]->value->name->parts === ['type'] + if ($args[1]->value->name->getParts() === ['type'] && $args[1]->value->getArgs() && $args[1]->value->getArgs()[0]->value instanceof PhpParser\Node\Scalar\LNumber ) { @@ -113,7 +112,7 @@ public static function handleOverride(array $args, Codebase $codebase): void $element_type_offset = null; - if ($args[1]->value->name->parts === ['elementType'] + if ($args[1]->value->name->getParts() === ['elementType'] && $args[1]->value->getArgs() && $args[1]->value->getArgs()[0]->value instanceof PhpParser\Node\Scalar\LNumber ) { @@ -128,7 +127,7 @@ public static function handleOverride(array $args, Codebase $codebase): void || $identifier->getArgs()[0]->value instanceof PhpParser\Node\Scalar\LNumber ) ) { - $meta_fq_classlike_name = implode('\\', $identifier->class->parts); + $meta_fq_classlike_name = $identifier->class->toString(); $meta_method_name = strtolower($identifier->name->name); @@ -280,7 +279,7 @@ static function ( || $identifier->getArgs()[0]->value instanceof PhpParser\Node\Scalar\LNumber ) ) { - $function_id = strtolower(implode('\\', $identifier->name->parts)); + $function_id = strtolower($identifier->name->toString()); if ($map) { $offset = 0; From 7aac142a440a6befc5abcbf0e0077d810450e1ac Mon Sep 17 00:00:00 2001 From: Yannick Gottschalk Date: Wed, 28 Jun 2023 02:04:45 +0200 Subject: [PATCH 2/4] Added stub for PhpParser\Node\Name --- stubs/phpparser.phpstub | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/stubs/phpparser.phpstub b/stubs/phpparser.phpstub index 856cd2feccc..18fd86b35fd 100644 --- a/stubs/phpparser.phpstub +++ b/stubs/phpparser.phpstub @@ -20,3 +20,21 @@ abstract class CallLike extends Expr { */ public function getArgs(): array {} } + + +namespace PhpParser\Node; + +use PhpParser\NodeAbstract; + +class Name extends NodeAbstract { + /** + * @param string|string[]|self $name + * @param array $attributes + */ + public function __construct($name, array $attributes = []) {} + + /** + * @return non-empty-string + */ + public function toString(): string {} +} From 539aa4c64489fb6b64c44ef7cdd2f374f4134743 Mon Sep 17 00:00:00 2001 From: Yannick Gottschalk Date: Mon, 3 Jul 2023 10:58:59 +0200 Subject: [PATCH 3/4] Update version of phpparser --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index cfca11919a2..7f4a9f9c8a9 100644 --- a/composer.json +++ b/composer.json @@ -23,9 +23,9 @@ "ext-libxml": "*", "ext-mbstring": "*", "ext-tokenizer": "*", + "composer-runtime-api": "^2", "amphp/amp": "^2.4.2", "amphp/byte-stream": "^1.5", - "composer-runtime-api": "^2", "composer/semver": "^1.4 || ^2.0 || ^3.0", "composer/xdebug-handler": "^2.0 || ^3.0", "dnoegel/php-xdg-base-dir": "^0.1.1", @@ -33,7 +33,7 @@ "felixfbecker/language-server-protocol": "^1.5.2", "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1", "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.14", + "nikic/php-parser": "^4.16", "sebastian/diff": "^4.0 || ^5.0", "spatie/array-to-xml": "^2.17.0 || ^3.0", "symfony/console": "^4.1.6 || ^5.0 || ^6.0", From bfd3cb889b8188ca550a7da81c4ebe57db992d0b Mon Sep 17 00:00:00 2001 From: Yannick Gottschalk Date: Mon, 3 Jul 2023 10:59:13 +0200 Subject: [PATCH 4/4] Added issue suppression because constructor analysis of stubbed classes seems unsupported --- psalm.xml.dist | 1 + 1 file changed, 1 insertion(+) diff --git a/psalm.xml.dist b/psalm.xml.dist index ee746e54871..1452823757e 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -93,6 +93,7 @@ +