Skip to content

Commit

Permalink
Fix
Browse files Browse the repository at this point in the history
  • Loading branch information
VincentLanglet committed Aug 9, 2024
1 parent 8daf529 commit ea8ae0b
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 18 deletions.
4 changes: 2 additions & 2 deletions src/Psalm/CodeLocation/ParseErrorLocation.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ public function __construct(
string $file_path,
string $file_name
) {
/** @psalm-suppress PossiblyUndefinedStringArrayOffset, ImpureMethodCall */
/** @psalm-suppress PossiblyUndefinedStringArrayOffset */
$this->file_start = (int)$error->getAttributes()['startFilePos'];
/** @psalm-suppress PossiblyUndefinedStringArrayOffset, ImpureMethodCall */
/** @psalm-suppress PossiblyUndefinedStringArrayOffset */
$this->file_end = (int)$error->getAttributes()['endFilePos'];
$this->raw_file_start = $this->file_start;
$this->raw_file_end = $this->file_end;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public static function getReturnTypes(
break;
}

if ($stmt instanceof PhpParser\Node\Stmt\Throw_) {
if (BCHelper::isThrowStatement($stmt)) {
$return_types[] = Type::getNever();

break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -691,8 +691,8 @@ private static function simplifyCaseEqualityExpression(
}

/**
* @param array<PhpParser\Node\Expr\ArrayItem> $in_array_values
* @return ?array<PhpParser\Node\Expr\ArrayItem>
* @param array<PhpParser\Node\Expr\ArrayItem|PhpParser\Node\ArrayItem> $in_array_values
* @return array<PhpParser\Node\Expr\ArrayItem|PhpParser\Node\ArrayItem>|null

Check failure on line 695 in src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php

View workflow job for this annotation

GitHub Actions / build

InvalidReturnType

src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php:695:16: InvalidReturnType: The declared return type 'array<array-key, PhpParser\Node\ArrayItem>|null' for Psalm\Internal\Analyzer\Statements\Block\SwitchCaseAnalyzer::getOptionsFromNestedOr is incorrect, got 'array<array-key, PhpParser\Node\ArrayItem|Psalm\Node\Expr\VirtualArrayItem>|null' (see https://psalm.dev/011)
*/
private static function getOptionsFromNestedOr(
PhpParser\Node\Expr $case_equality_expr,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ public static function handleMagicMethod(
$result->existent_method_ids[$method_id->__toString()] = true;

$array_values = array_map(
static fn(PhpParser\Node\Arg $arg): PhpParser\Node\Expr\ArrayItem => new VirtualArrayItem(
/** @return PhpParser\Node\Expr\ArrayItem|PhpParser\Node\ArrayItem */

Check failure on line 204 in src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MissingMethodCallHandler.php

View workflow job for this annotation

GitHub Actions / build

InvalidReturnType

src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MissingMethodCallHandler.php:204:25: InvalidReturnType: The declared return type 'PhpParser\Node\ArrayItem' for /home/runner/work/psalm/psalm/src/psalm/internal/analyzer/statements/expression/call/method/missingmethodcallhandler.php:205:7368:-:closure is incorrect, got 'Psalm\Node\Expr\VirtualArrayItem' (see https://psalm.dev/011)
static fn(PhpParser\Node\Arg $arg) => new VirtualArrayItem(

Check failure on line 205 in src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MissingMethodCallHandler.php

View workflow job for this annotation

GitHub Actions / build

InvalidReturnStatement

src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MissingMethodCallHandler.php:205:51: InvalidReturnStatement: The inferred type 'Psalm\Node\Expr\VirtualArrayItem' does not match the declared return type 'PhpParser\Node\ArrayItem' for /home/runner/work/psalm/psalm/src/psalm/internal/analyzer/statements/expression/call/method/missingmethodcallhandler.php:205:7368:-:closure (see https://psalm.dev/128)
$arg->value,
null,
false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,8 @@ private static function convertCondsToConditional(
}

$array_items = array_map(
static fn(PhpParser\Node\Expr $cond): PhpParser\Node\Expr\ArrayItem =>
/** @return PhpParser\Node\Expr\ArrayItem|PhpParser\Node\ArrayItem */

Check failure on line 335 in src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php

View workflow job for this annotation

GitHub Actions / build

InvalidReturnType

src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php:335:25: InvalidReturnType: The declared return type 'PhpParser\Node\ArrayItem' for /home/runner/work/psalm/psalm/src/psalm/internal/analyzer/statements/expression/matchanalyzer.php:336:11818:-:closure is incorrect, got 'Psalm\Node\Expr\VirtualArrayItem' (see https://psalm.dev/011)
static fn(PhpParser\Node\Expr $cond) =>
new VirtualArrayItem($cond, null, false, $cond->getAttributes()),

Check failure on line 337 in src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php

View workflow job for this annotation

GitHub Actions / build

InvalidReturnStatement

src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php:337:17: InvalidReturnStatement: The inferred type 'Psalm\Node\Expr\VirtualArrayItem' does not match the declared return type 'PhpParser\Node\ArrayItem' for /home/runner/work/psalm/psalm/src/psalm/internal/analyzer/statements/expression/matchanalyzer.php:336:11818:-:closure (see https://psalm.dev/128)
$conds,
);
Expand Down
4 changes: 2 additions & 2 deletions src/Psalm/Internal/Analyzer/Statements/ThrowAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
final class ThrowAnalyzer
{
/**
* @param PhpParser\Node\Stmt\Throw_|PhpParser\Node\Expr\Throw_ $stmt
* @param PhpParser\Node\Expr\Throw_|PhpParser\Node\Stmt\Throw_ $stmt
*/
public static function analyze(
StatementsAnalyzer $statements_analyzer,
PhpParser\Node $stmt,
$stmt,
Context $context
): bool {
$context->inside_throw = true;
Expand Down
3 changes: 2 additions & 1 deletion src/Psalm/Internal/Analyzer/StatementsAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use Psalm\Internal\Analyzer\Statements\ThrowAnalyzer;
use Psalm\Internal\Analyzer\Statements\UnsetAnalyzer;
use Psalm\Internal\Analyzer\Statements\UnusedAssignmentRemover;
use Psalm\Internal\BCHelper;
use Psalm\Internal\Codebase\DataFlowGraph;
use Psalm\Internal\Codebase\TaintFlowGraph;
use Psalm\Internal\Codebase\VariableUseGraph;
Expand Down Expand Up @@ -543,7 +544,7 @@ private static function analyzeStatement(
UnsetAnalyzer::analyze($statements_analyzer, $stmt, $context);
} elseif ($stmt instanceof PhpParser\Node\Stmt\Return_) {
ReturnAnalyzer::analyze($statements_analyzer, $stmt, $context);
} elseif ($stmt instanceof PhpParser\Node\Stmt\Throw_) {
} elseif (BCHelper::isThrowStatement($stmt)) {
ThrowAnalyzer::analyze($statements_analyzer, $stmt, $context);
} elseif ($stmt instanceof PhpParser\Node\Stmt\Switch_) {
SwitchAnalyzer::analyze($statements_analyzer, $stmt, $context);
Expand Down
47 changes: 47 additions & 0 deletions src/Psalm/Internal/BCHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
namespace Psalm\Internal;

use PhpParser;
use PhpParser\Lexer\Emulative;
use PhpParser\Node;
use PhpParser\PhpVersion;

use function class_exists;

Expand All @@ -12,6 +14,28 @@
*/
final class BCHelper
{
private const CLASS_MAP = [
Node\Expr\ArrayItem::class => Node\ArrayItem::class,
Node\Expr\ClosureUse::class => Node\ClosureUse::class,
Node\Scalar\DNumber::class => Node\Scalar\Float_::class,
Node\Scalar\Encapsed::class => Node\Scalar\InterpolatedString::class,
Node\Scalar\EncapsedStringPart::class => Node\InterpolatedStringPart::class,
Node\Scalar\LNumber::class => Node\Scalar\Int_::class,
Node\Stmt\DeclareDeclare::class => Node\DeclareItem::class,
Node\Stmt\PropertyProperty::class => Node\PropertyItem::class,
Node\Stmt\StaticVar::class => Node\StaticVar::class,
Node\Stmt\UseUse::class => Node\UseItem::class,
];

public static function getPHPParserClassName(string $className): string
{
if (isset(self::CLASS_MAP[$className]) && class_exists(self::CLASS_MAP[$className])) {
return self::CLASS_MAP[$className];
}

return $className;
}

public static function usePHPParserV4(): bool
{
return class_exists('\PhpParser\Node\Stmt\Throw');
Expand All @@ -26,4 +50,27 @@ public static function isThrow(Node $stmt): bool
return $stmt instanceof PhpParser\Node\Stmt\Expression
&& $stmt->expr instanceof PhpParser\Node\Expr\Throw_;
}

public static function isThrowStatement(Node $node): bool
{
if (self::usePHPParserV4()) {
return $node instanceof PhpParser\Node\Stmt\Throw_;
}

return false;
}

public static function createEmulative(int $major_version, int $minor_version): PhpParser\Lexer\Emulative
{
if (class_exists(PhpVersion::class)) {
return new Emulative(PhpVersion::fromComponents($major_version, $minor_version));
}

return new Emulative([
'usedAttributes' => [
'comments', 'startLine', 'startFilePos', 'endFilePos',
],
'phpVersion' => $major_version . '.' . $minor_version,
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ public function start(PhpParser\Node\Stmt\ClassLike $node): ?bool

$fq_classlike_name =
($this->aliases->namespace ? $this->aliases->namespace . '\\' : '') . $node->name->name;
assert($fq_classlike_name !== "");

$fq_classlike_name_lc = strtolower($fq_classlike_name);

Expand Down
3 changes: 3 additions & 0 deletions src/Psalm/Internal/PhpVisitor/SimpleNameResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ public function enterNode(Node $node): ?int
return null;
}

/**
* @param Stmt\Use_::TYPE_* $type
*/
private function addAlias(Stmt\UseUse $use, int $type, ?Name $prefix = null): void
{
// Add prefix for group uses
Expand Down
21 changes: 16 additions & 5 deletions src/Psalm/Internal/Provider/ClassLikeStorageProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use InvalidArgumentException;
use LogicException;
use Psalm\Internal\BCHelper;
use Psalm\Storage\ClassLikeStorage;

use function array_merge;
Expand Down Expand Up @@ -39,7 +40,7 @@ public function __construct(?ClassLikeStorageCacheProvider $cache = null)
*/
public function get(string $fq_classlike_name): ClassLikeStorage
{
$fq_classlike_name_lc = strtolower($fq_classlike_name);
$fq_classlike_name_lc = $this->formatClassName($fq_classlike_name);
/** @psalm-suppress ImpureStaticProperty Used only for caching */
if (!isset(self::$storage[$fq_classlike_name_lc])) {
throw new InvalidArgumentException('Could not get class storage for ' . $fq_classlike_name_lc);
Expand All @@ -49,20 +50,30 @@ public function get(string $fq_classlike_name): ClassLikeStorage
return self::$storage[$fq_classlike_name_lc];
}

/**
* @psalm-mutation-free
*
* @return lowercase-string
*/
private function formatClassName(string $class): string
{
return strtolower(BCHelper::getPHPParserClassName($class));
}

/**
* @psalm-mutation-free
*/
public function has(string $fq_classlike_name): bool
{
$fq_classlike_name_lc = strtolower($fq_classlike_name);
$fq_classlike_name_lc = $this->formatClassName($fq_classlike_name);

/** @psalm-suppress ImpureStaticProperty Used only for caching */
return isset(self::$storage[$fq_classlike_name_lc]);
}

public function exhume(string $fq_classlike_name, string $file_path, string $file_contents): ClassLikeStorage
{
$fq_classlike_name_lc = strtolower($fq_classlike_name);
$fq_classlike_name_lc = $this->formatClassName($fq_classlike_name);

if (isset(self::$storage[$fq_classlike_name_lc])) {
return self::$storage[$fq_classlike_name_lc];
Expand Down Expand Up @@ -112,7 +123,7 @@ public function makeNew(string $fq_classlike_name_lc): void

public function create(string $fq_classlike_name): ClassLikeStorage
{
$fq_classlike_name_lc = strtolower($fq_classlike_name);
$fq_classlike_name_lc = $this->formatClassName($fq_classlike_name);

$storage = new ClassLikeStorage($fq_classlike_name);
self::$storage[$fq_classlike_name_lc] = $storage;
Expand All @@ -123,7 +134,7 @@ public function create(string $fq_classlike_name): ClassLikeStorage

public function remove(string $fq_classlike_name): void
{
$fq_classlike_name_lc = strtolower($fq_classlike_name);
$fq_classlike_name_lc = $this->formatClassName($fq_classlike_name);

unset(self::$storage[$fq_classlike_name_lc]);
}
Expand Down
5 changes: 3 additions & 2 deletions src/Psalm/Internal/Provider/StatementsProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
use PhpParser\Lexer\Emulative;
use PhpParser\Node\Stmt;
use PhpParser\Parser;
use PhpParser\PhpVersion;
use Psalm\CodeLocation\ParseErrorLocation;
use Psalm\Codebase;
use Psalm\Config;
use Psalm\Internal\BCHelper;
use Psalm\Internal\Diff\FileDiffer;
use Psalm\Internal\Diff\FileStatementsDiffer;
use Psalm\Internal\PhpTraverser\CustomTraverser;
Expand Down Expand Up @@ -394,7 +394,8 @@ public static function parseStatements(
if (!self::$lexer) {
$major_version = Codebase::transformPhpVersionId($analysis_php_version_id, 10_000);
$minor_version = Codebase::transformPhpVersionId($analysis_php_version_id % 10_000, 100);
self::$lexer = new Emulative(PhpVersion::fromComponents($major_version, $minor_version));

self::$lexer = BCHelper::createEmulative($major_version, $minor_version);
}

if (!self::$parser) {
Expand Down

0 comments on commit ea8ae0b

Please sign in to comment.