Skip to content

Commit

Permalink
[StrictTypes] Add MethodCall/StaticCall to ExclusiveNativeCallLikeRet…
Browse files Browse the repository at this point in the history
…urnMatcher (#2646)
  • Loading branch information
TomasVotruba committed Jul 9, 2022
1 parent f9916a1 commit fba410b
Show file tree
Hide file tree
Showing 13 changed files with 138 additions and 81 deletions.
6 changes: 3 additions & 3 deletions build/target-repository/docs/rector_rules_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -9620,11 +9620,11 @@ Add strict return type based on returned strict expr type

<br>

### ReturnTypeFromStrictNativeFuncCallRector
### ReturnTypeFromStrictNativeCallRector

Add strict return type based native function return
Add strict return type based native function or class method return

- class: [`Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeFuncCallRector`](../rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNativeFuncCallRector.php)
- class: [`Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector`](../rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNativeCallRector.php)

```diff
final class SomeClass
Expand Down
4 changes: 2 additions & 2 deletions config/set/type-declaration-strict.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Rector\TypeDeclaration\Rector\ClassMethod\ParamTypeByParentCallTypeRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromReturnNewRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictBoolReturnExprRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeFuncCallRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNewArrayRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictTypedCallRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictTypedPropertyRector;
Expand All @@ -33,7 +33,7 @@
AddMethodCallBasedStrictParamTypeRector::class,
ArrayShapeFromConstantArrayReturnRector::class,
ReturnTypeFromStrictBoolReturnExprRector::class,
ReturnTypeFromStrictNativeFuncCallRector::class,
ReturnTypeFromStrictNativeCallRector::class,
ReturnTypeFromStrictNewArrayRector::class,
ReturnTypeFromStrictScalarReturnExprRector::class,
TypedPropertyFromStrictSetUpRector::class,
Expand Down
1 change: 1 addition & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ parameters:
- src/*/*Processor.php
- rules/Composer/Application/FileProcessor/ComposerFileProcessor.php
- src/Contract/Processor/FileProcessorInterface.php
- packages/Parallel/Application/ParallelFileProcessor.php

# skipped on purpose, as ctor overrie
- '#Rector\\StaticTypeMapper\\ValueObject\\Type\\SimpleStaticType\:\:__construct\(\) does not call parent constructor from PHPStan\\Type\\StaticType#'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector\Fixture;

function custom_function(): string
{
return 'yes';
}

final class SkipCustomFunction
{
public function run()
{
return custom_function();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeFuncCallRector\Fixture;
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector\Fixture;

final class SomeClass
{
Expand All @@ -14,7 +14,7 @@ final class SomeClass
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeFuncCallRector\Fixture;
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector\Fixture;

final class SomeClass
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector\Fixture;

final class SomeNativeMethodCall
{
public function run(\SplFileInfo $splFileInfo)
{
return $splFileInfo->isDir();
}
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector\Fixture;

final class SomeNativeMethodCall
{
public function run(\SplFileInfo $splFileInfo): bool
{
return $splFileInfo->isDir();
}
}

?>
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

declare(strict_types=1);

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeFuncCallRector;
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector;

use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;

final class ReturnTypeFromStrictNativeFuncCallRectorTest extends AbstractRectorTestCase
final class ReturnTypeFromStrictNativeCallRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

use Rector\Config\RectorConfig;

use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeFuncCallRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(ReturnTypeFromStrictNativeFuncCallRector::class);
$rectorConfig->rule(ReturnTypeFromStrictNativeCallRector::class);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

namespace Rector\TypeDeclaration\NodeAnalyzer\ReturnFilter;

use PhpParser\Node\Expr;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\Return_;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Reflection\MethodReflection;
use Rector\Core\Reflection\ReflectionResolver;

final class ExclusiveNativeCallLikeReturnMatcher
{
public function __construct(
private readonly ReflectionResolver $reflectionResolver,
) {
}

/**
* @param Return_[] $returns
* @return array<StaticCall|FuncCall|MethodCall>|null
*/
public function match(array $returns): array|null
{
$callLikes = [];

foreach ($returns as $return) {
// we need exact expr return
$returnExpr = $return->expr;
if (! $returnExpr instanceof StaticCall && ! $returnExpr instanceof MethodCall && ! $returnExpr instanceof FuncCall) {
return null;
}

$functionLikeReflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($returnExpr);

if (! $functionLikeReflection instanceof FunctionReflection && ! $functionLikeReflection instanceof MethodReflection) {
return null;
}

// is native func call?
if (! $this->isNativeCallLike($functionLikeReflection)) {
return null;
}

$callLikes[] = $returnExpr;
}

return $callLikes;
}

private function isNativeCallLike(MethodReflection|FunctionReflection $functionLikeReflection): bool
{
if ($functionLikeReflection instanceof FunctionReflection) {
return $functionLikeReflection->isBuiltin();
}

// is native method call?
$classReflection = $functionLikeReflection->getDeclaringClass();
return $classReflection->isBuiltin();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@
namespace Rector\TypeDeclaration\NodeAnalyzer\ReturnTypeAnalyzer;

use PhpParser\Node\Expr;
use PhpParser\Node\Expr\CallLike;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\Yield_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\Return_;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\TypeDeclaration\NodeAnalyzer\ReturnFilter\ExclusiveNativeFuncCallReturnMatcher;
use Rector\TypeDeclaration\NodeAnalyzer\ReturnFilter\ExclusiveNativeCallLikeReturnMatcher;

final class StrictNativeFunctionReturnTypeAnalyzer
{
public function __construct(
private readonly BetterNodeFinder $betterNodeFinder,
private readonly ExclusiveNativeFuncCallReturnMatcher $exclusiveNativeFuncCallReturnMatcher
private readonly ExclusiveNativeCallLikeReturnMatcher $exclusiveNativeCallLikeReturnMatcher
) {
}

/**
* @return FuncCall[]|null
* @return CallLike[]|null
*/
public function matchAlwaysReturnNativeFuncCalls(ClassMethod|Closure|Function_ $functionLike): ?array
public function matchAlwaysReturnNativeCallLikes(ClassMethod|Closure|Function_ $functionLike): ?array
{
if ($functionLike->stmts === null) {
return null;
Expand All @@ -51,12 +51,12 @@ public function matchAlwaysReturnNativeFuncCalls(ClassMethod|Closure|Function_ $
return null;
}

$nativeFuncCalls = $this->exclusiveNativeFuncCallReturnMatcher->match($returns);
if ($nativeFuncCalls === null) {
$nativeCalls = $this->exclusiveNativeCallLikeReturnMatcher->match($returns);
if ($nativeCalls === null) {
return null;
}

return $nativeFuncCalls;
return $nativeCalls;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @see \Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeFuncCallRector\ReturnTypeFromStrictNativeFuncCallRectorTest
* @see \Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector\ReturnTypeFromStrictNativeCallRectorTest
*/
final class ReturnTypeFromStrictNativeFuncCallRector extends AbstractRector implements MinPhpVersionInterface
final class ReturnTypeFromStrictNativeCallRector extends AbstractRector implements MinPhpVersionInterface
{
public function __construct(
private readonly StrictNativeFunctionReturnTypeAnalyzer $strictNativeFunctionReturnTypeAnalyzer,
Expand All @@ -31,7 +31,7 @@ public function __construct(

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Add strict return type based native function return', [
return new RuleDefinition('Add strict return type based native function or class method return', [
new CodeSample(
<<<'CODE_SAMPLE'
final class SomeClass
Expand Down Expand Up @@ -74,17 +74,17 @@ public function refactor(Node $node): ?Node
return null;
}

$nativeFuncCalls = $this->strictNativeFunctionReturnTypeAnalyzer->matchAlwaysReturnNativeFuncCalls($node);
if ($nativeFuncCalls === null) {
$nativeCallLikes = $this->strictNativeFunctionReturnTypeAnalyzer->matchAlwaysReturnNativeCallLikes($node);
if ($nativeCallLikes === null) {
return null;
}

$funcCallTypes = [];
foreach ($nativeFuncCalls as $nativeFuncCall) {
$funcCallTypes[] = $this->getType($nativeFuncCall);
$callLikeTypes = [];
foreach ($nativeCallLikes as $nativeCallLike) {
$callLikeTypes[] = $this->getType($nativeCallLike);
}

$returnType = $this->typeFactory->createMixedPassedOrUnionType($funcCallTypes);
$returnType = $this->typeFactory->createMixedPassedOrUnionType($callLikeTypes);
if ($returnType instanceof MixedType) {
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Reflection/ReflectionResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public function resolveMethodReflectionFromMethodCall(MethodCall $methodCall): ?
}

public function resolveFunctionLikeReflectionFromCall(
MethodCall | StaticCall | FuncCall $call
MethodCall|FuncCall|StaticCall $call
): MethodReflection | FunctionReflection | null {
if ($call instanceof MethodCall) {
return $this->resolveMethodReflectionFromMethodCall($call);
Expand Down

0 comments on commit fba410b

Please sign in to comment.