Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support deprecated magic __toString() in echo statement #37

Open
wants to merge 41 commits into
base: 1.1.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ae33971
support deprecated magic __toString() in echo statement
staabm May 1, 2021
86ad5d0
cleanup
staabm May 1, 2021
0e7f1d1
check against null
staabm May 1, 2021
d5e3248
remove unnecessary $scope arg
staabm May 1, 2021
d555a07
wrap test into function() to prevent echoing the actual string
staabm May 1, 2021
8f530ff
Update EchoDeprecatedToStringRuleTest.php
staabm May 1, 2021
8f3cb87
fix cs
staabm May 1, 2021
514e904
fix cs
staabm May 1, 2021
2c04cf2
support echo with string concat
staabm May 1, 2021
024edd4
fix type error
staabm May 1, 2021
fed9f4f
Update tests/Rules/Deprecations/data/echo-deprecated-magic-method-tos…
staabm May 1, 2021
b410c0d
Update EchoDeprecatedToStringRuleTest.php
staabm May 1, 2021
4417914
more testcoverage
staabm May 1, 2021
f133d6b
cover __toString() without deprecation
staabm May 1, 2021
47c4a55
added more testcoverage
staabm May 1, 2021
f23f190
support nested expressions
staabm May 1, 2021
d720be6
fix cs
staabm May 1, 2021
2b38c72
fix cs
staabm May 1, 2021
2ab82ca
cover explicit (string) cast
staabm May 1, 2021
1b43bf1
impl string casts
staabm May 1, 2021
ea2038c
cover assignment in expression
staabm May 1, 2021
a111c5f
cover Node\Expr\AssignOp
staabm May 1, 2021
689ff9c
cover Expr\AssignOp\Coalesce
staabm May 1, 2021
ca8c02b
cover Expr\BinaryOp\Equal
staabm May 1, 2021
b6016a7
cover Expr\BinaryOp\Identical
staabm May 1, 2021
470ccd2
cover Expr\BinaryOp\NotEqual
staabm May 1, 2021
239be6a
cover Expr\BinaryOp\NotIdentical
staabm May 1, 2021
eed7f60
cover Expr\BinaryOp\Spaceship
staabm May 1, 2021
879df38
simplify
staabm May 1, 2021
266bf34
cover Node\Scalar\Encapsed
staabm May 1, 2021
4ae64bb
cover coalesce operator
staabm May 1, 2021
61c9b8f
fix cs
staabm May 1, 2021
c114463
extracted EchoDeprecatedBinaryOpToStringRule
staabm May 9, 2021
3adc283
register PHPStan\Rules\Deprecations\EchoDeprecatedBinaryOpToStringRul…
staabm May 9, 2021
a4138a7
take core-logic from CallToDeprecatedMethodRule
staabm May 9, 2021
c09043b
Update EchoDeprecatedBinaryOpToStringRule.php
staabm May 9, 2021
2ca2d51
fix cs
staabm May 9, 2021
830f6d5
removed copy/paste leftovers
staabm May 9, 2021
fef4fe7
fix test generic
staabm May 9, 2021
583279a
removed no longer needed RuleLevelHeper from tests
staabm May 9, 2021
867e2a5
fix analysis errors and cs
staabm May 9, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions src/Rules/Deprecations/EchoDeprecatedToStringRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Deprecations;

use PhpParser\Node;
use PhpParser\Node\Stmt\Echo_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;

/**
* @implements \PHPStan\Rules\Rule<Echo_>
*/
class EchoDeprecatedToStringRule implements \PHPStan\Rules\Rule
{

/** @var RuleLevelHelper */
private $ruleLevelHelper;

public function __construct(RuleLevelHelper $ruleLevelHelper)
{
$this->ruleLevelHelper = $ruleLevelHelper;
}

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

public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}

$messages = [];

foreach ($node->exprs as $key => $expr) {
if ($expr instanceof Node\Expr\Variable) {
$message = $this->checkExpr($expr, $scope);

if ($message) {
$messages[] = $message;
}
} elseif ($expr instanceof Node\Expr\BinaryOp\Concat) {
$message = $this->checkExpr($expr->left, $scope);
if ($message) {
$messages[] = $message;
}

$message = $this->checkExpr($expr->right, $scope);
if ($message) {
$messages[] = $message;
}
}
}

return $messages;
}

private function checkExpr(Node\Expr $expr, Scope $scope): ?string
{
$type = $this->ruleLevelHelper->findTypeToCheck(
$scope,
$expr,
'',
static function (Type $type): bool {
return !$type->toString() instanceof ErrorType;
}
)->getType();

if (!$type instanceof ObjectType) {
return null;
}

$classReflection = $type->getClassReflection();

if ($classReflection === null) {
return null;
}

$methodReflection = $classReflection->getNativeMethod('__toString');

if (!$methodReflection->isDeprecated()->yes()) {
return null;
}

$description = $methodReflection->getDeprecatedDescription();
if ($description === null) {
return sprintf(
'Call to deprecated method %s() of class %s.',
$methodReflection->getName(),
$methodReflection->getDeclaringClass()->getName()
);
}

return sprintf(
"Call to deprecated method %s() of class %s:\n%s",
$methodReflection->getName(),
$methodReflection->getDeclaringClass()->getName(),
$description
);
}

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

namespace PHPStan\Rules\Deprecations;

use PHPStan\Rules\RuleLevelHelper;

/**
* @extends \PHPStan\Testing\RuleTestCase<EchoDeprecatedToStringRule>
*/
class EchoDeprecatedToStringRuleTest extends \PHPStan\Testing\RuleTestCase
{

protected function getRule(): \PHPStan\Rules\Rule
{
$ruleLevelHelper = new RuleLevelHelper($this->createBroker(), true, false, true);

return new EchoDeprecatedToStringRule($ruleLevelHelper);
}

public function testDeprecatedMagicMethodToStringCall(): void
{
require_once __DIR__ . '/data/echo-deprecated-magic-method-tostring.php';
$this->analyse(
[__DIR__ . '/data/echo-deprecated-magic-method-tostring.php'],
[
[
'Call to deprecated method __toString() of class CheckDeprecatedStaticMethodCall\MagicBar.',
8,
],
[
'Call to deprecated method __toString() of class CheckDeprecatedStaticMethodCall\MagicBar.',
9,
],
]
);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace CheckDeprecatedStaticMethodCall;

function ()
{
$bar = new MagicBar();
echo $bar;
echo $bar . "hallo";
};

class MagicBar
{
/**
* @deprecated
*/
public function __toString()
{
return 'a string';
}
}