From 872f1c232cb3a6ff2c7d2c5db02316307ea1892e Mon Sep 17 00:00:00 2001 From: orklah Date: Fri, 18 Jun 2021 00:15:45 +0200 Subject: [PATCH] allow Psalter to fix RedundantCast (#5948) * allow Psalter to fix RedundantCast * fix test --- .../Internal/Analyzer/ProjectAnalyzer.php | 4 + .../Statements/Expression/CastAnalyzer.php | 132 ++++++++---------- .../RedundantCastManipulationTest.php | 46 ++++++ 3 files changed, 107 insertions(+), 75 deletions(-) create mode 100644 tests/FileManipulation/RedundantCastManipulationTest.php diff --git a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php index 75eaa7b65be..837d945dc5a 100644 --- a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php @@ -32,6 +32,8 @@ use Psalm\Issue\PossiblyUndefinedVariable; use Psalm\Issue\PossiblyUnusedMethod; use Psalm\Issue\PossiblyUnusedProperty; +use Psalm\Issue\RedundantCast; +use Psalm\Issue\RedundantCastGivenDocblockType; use Psalm\Issue\UnnecessaryVarAnnotation; use Psalm\Issue\UnusedMethod; use Psalm\Issue\UnusedProperty; @@ -229,6 +231,8 @@ class ProjectAnalyzer PossiblyUndefinedVariable::class, PossiblyUnusedMethod::class, PossiblyUnusedProperty::class, + RedundantCast::class, + RedundantCastGivenDocblockType::class, UnusedMethod::class, UnusedProperty::class, UnusedVariable::class, diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php index 4930f654d5b..c4f3dc13ade 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php @@ -7,6 +7,7 @@ use Psalm\Internal\Analyzer\Statements\Expression\Call\Method\MethodCallReturnTypeFetcher; use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer; use Psalm\Internal\Analyzer\StatementsAnalyzer; +use Psalm\Internal\FileManipulation\FileManipulationBuffer; use Psalm\Internal\Type\TypeCombiner; use Psalm\Issue\InvalidCast; use Psalm\Issue\PossiblyInvalidCast; @@ -52,21 +53,7 @@ public static function analyze( if ($maybe_type->isInt()) { $valid_int_type = $maybe_type; if (!$maybe_type->from_calculation) { - if ($maybe_type->from_docblock) { - $issue = new RedundantCastGivenDocblockType( - 'Redundant cast to ' . $maybe_type->getKey() . ' given docblock-provided type', - new CodeLocation($statements_analyzer->getSource(), $stmt) - ); - } else { - $issue = new RedundantCast( - 'Redundant cast to ' . $maybe_type->getKey(), - new CodeLocation($statements_analyzer->getSource(), $stmt) - ); - } - - if (IssueBuffer::accepts($issue, $statements_analyzer->getSuppressedIssues())) { - // fall through - } + self::handleRedundantCast($maybe_type, $statements_analyzer, $stmt); } } @@ -113,21 +100,7 @@ public static function analyze( if ($maybe_type) { if ($maybe_type->isFloat()) { - if ($maybe_type->from_docblock) { - $issue = new RedundantCastGivenDocblockType( - 'Redundant cast to ' . $maybe_type->getKey() . ' given docblock-provided type', - new CodeLocation($statements_analyzer->getSource(), $stmt) - ); - } else { - $issue = new RedundantCast( - 'Redundant cast to ' . $maybe_type->getKey(), - new CodeLocation($statements_analyzer->getSource(), $stmt) - ); - } - - if (IssueBuffer::accepts($issue, $statements_analyzer->getSuppressedIssues())) { - // fall through - } + self::handleRedundantCast($maybe_type, $statements_analyzer, $stmt); } } @@ -153,21 +126,7 @@ public static function analyze( if ($maybe_type) { if ($maybe_type->isBool()) { - if ($maybe_type->from_docblock) { - $issue = new RedundantCastGivenDocblockType( - 'Redundant cast to ' . $maybe_type->getKey() . ' given docblock-provided type', - new CodeLocation($statements_analyzer->getSource(), $stmt) - ); - } else { - $issue = new RedundantCast( - 'Redundant cast to ' . $maybe_type->getKey(), - new CodeLocation($statements_analyzer->getSource(), $stmt) - ); - } - - if (IssueBuffer::accepts($issue, $statements_analyzer->getSuppressedIssues())) { - // fall through - } + self::handleRedundantCast($maybe_type, $statements_analyzer, $stmt); } } @@ -193,21 +152,7 @@ public static function analyze( if ($stmt_expr_type) { if ($stmt_expr_type->isString()) { - if ($stmt_expr_type->from_docblock) { - $issue = new RedundantCastGivenDocblockType( - 'Redundant cast to ' . $stmt_expr_type->getKey() . ' given docblock-provided type', - new CodeLocation($statements_analyzer->getSource(), $stmt) - ); - } else { - $issue = new RedundantCast( - 'Redundant cast to ' . $stmt_expr_type->getKey(), - new CodeLocation($statements_analyzer->getSource(), $stmt) - ); - } - - if (IssueBuffer::accepts($issue, $statements_analyzer->getSuppressedIssues())) { - // fall through - } + self::handleRedundantCast($stmt_expr_type, $statements_analyzer, $stmt); } $stmt_type = self::castStringAttempt( @@ -262,21 +207,7 @@ public static function analyze( if ($stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr)) { if ($stmt_expr_type->isArray()) { - if ($stmt_expr_type->from_docblock) { - $issue = new RedundantCastGivenDocblockType( - 'Redundant cast to ' . $stmt_expr_type->getKey() . ' given docblock-provided type', - new CodeLocation($statements_analyzer->getSource(), $stmt) - ); - } else { - $issue = new RedundantCast( - 'Redundant cast to ' . $stmt_expr_type->getKey(), - new CodeLocation($statements_analyzer->getSource(), $stmt) - ); - } - - if (IssueBuffer::accepts($issue, $statements_analyzer->getSuppressedIssues())) { - // fall through - } + self::handleRedundantCast($stmt_expr_type, $statements_analyzer, $stmt); } $all_permissible = true; @@ -518,4 +449,55 @@ public static function castStringAttempt( return $str_type; } + + private static function handleRedundantCast( + Type\Union $maybe_type, + StatementsAnalyzer $statements_analyzer, + PhpParser\Node\Expr\Cast $stmt + ): void { + $codebase = $statements_analyzer->getCodebase(); + $project_analyzer = $statements_analyzer->getProjectAnalyzer(); + + $file_manipulation = null; + if ($maybe_type->from_docblock) { + $issue = new RedundantCastGivenDocblockType( + 'Redundant cast to ' . $maybe_type->getKey() . ' given docblock-provided type', + new CodeLocation($statements_analyzer->getSource(), $stmt) + ); + + if ($codebase->alter_code + && isset($project_analyzer->getIssuesToFix()['RedundantCastGivenDocblockType']) + ) { + $file_manipulation = new \Psalm\FileManipulation( + (int) $stmt->getAttribute('startFilePos'), + (int) $stmt->expr->getAttribute('startFilePos'), + '' + ); + } + } else { + $issue = new RedundantCast( + 'Redundant cast to ' . $maybe_type->getKey(), + new CodeLocation($statements_analyzer->getSource(), $stmt) + ); + + if ($codebase->alter_code + && isset($project_analyzer->getIssuesToFix()['RedundantCast']) + ) { + $file_manipulation = new \Psalm\FileManipulation( + (int) $stmt->getAttribute('startFilePos'), + (int) $stmt->expr->getAttribute('startFilePos'), + '' + ); + } + } + + if ($file_manipulation) { + FileManipulationBuffer::add($statements_analyzer->getFilePath(), [$file_manipulation]); + } + + + if (IssueBuffer::accepts($issue, $statements_analyzer->getSuppressedIssues())) { + // fall through + } + } } diff --git a/tests/FileManipulation/RedundantCastManipulationTest.php b/tests/FileManipulation/RedundantCastManipulationTest.php new file mode 100644 index 00000000000..721deb15c6e --- /dev/null +++ b/tests/FileManipulation/RedundantCastManipulationTest.php @@ -0,0 +1,46 @@ + + */ + public function providerValidCodeParse(): array + { + return [ + 'RemoveRedundantCast' => [ + ' [ + '