Skip to content

support deprecated magic __toString() in echo statement #37

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

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 1 commit
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
94 changes: 94 additions & 0 deletions src/Rules/Deprecations/EchoDeprecatedToStringRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Deprecations;

use PhpParser\Node;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Identifier;
use PHPStan\Analyser\Scope;
use PHPStan\Analyser\VariableTypeHolder;
use PHPStan\Broker\Broker;
use PHPStan\Type\ObjectType;
use PHPStan\Type\TypeUtils;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;

/**
* @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 Node\Stmt\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) {
continue;
}

$type = $this->ruleLevelHelper->findTypeToCheck(
$scope,
$expr,
'',
static function (Type $type): bool {
return !$type->toString() instanceof ErrorType;
}
)->getType();

if (!$type instanceof ObjectType) {
continue;
}

$classReflection = $type->getClassReflection();
$methodReflection = $classReflection->getNativeMethod('__toString', $scope);

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

$description = $methodReflection->getDeprecatedDescription();
if ($description === null) {
$messages[] = sprintf(
'Call to deprecated method %s() of class %s.',
$methodReflection->getName(),
$methodReflection->getDeclaringClass()->getName()
);
} else {
$messages[] = sprintf(
"Call to deprecated method %s() of class %s:\n%s",
$methodReflection->getName(),
$methodReflection->getDeclaringClass()->getName(),
$description
);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

most of this code is inspired by CallToDeprecatedMethodRule

}

return $messages;
}

}
34 changes: 34 additions & 0 deletions tests/Rules/Deprecations/EchoDeprecatedToStringRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?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.',
6,
]
]
);
}

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

namespace CheckDeprecatedStaticMethodCall;

$bar = new MagicBar();
echo $bar;

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