Skip to content

Commit

Permalink
spec fixing
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Nov 6, 2021
1 parent 1432b7b commit ae5b81e
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 104 deletions.
2 changes: 1 addition & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ parameters:
- '#Cognitive complexity for "Rector\\Php80\\NodeResolver\\SwitchExprsResolver\:\:resolve\(\)" is (.*?), keep it under 9#'

-
message: "#^Cognitive complexity for \"Rector\\\\PhpSpecToPHPUnit\\\\Rector\\\\MethodCall\\\\PhpSpecPromisesToPHPUnitAssertRector\\:\\:refactor\\(\\)\" is 13, keep it under 9$#"
message: "#^Cognitive complexity for \"Rector\\\\PhpSpecToPHPUnit\\\\Rector\\\\MethodCall\\\\PhpSpecPromisesToPHPUnitAssertRector\\:\\:refactor\\(\\)\" is \d+, keep it under 9$#"
path: rules/PhpSpecToPHPUnit/Rector/MethodCall/PhpSpecPromisesToPHPUnitAssertRector.php

-
Expand Down

This file was deleted.

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

namespace Rector\Tests\Php74\Rector\Property\TypedPropertyRector\Fixture;

trait SkipTrait
{
private $body;

public function setJsonBody(array $body): self
{
$this->body = $body;
return $this;
}

public function getJsonBody(): ?array
{
return $this->body;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ trait MaterializedPathEntity
public function setParent(self $parent = null) : static
{
$this->parent = $parent;

return $this;
}

Expand Down
40 changes: 14 additions & 26 deletions rules/Php74/Rector/Property/TypedPropertyRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
use PhpParser\Node\Name;
use PhpParser\Node\NullableType;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\Trait_;
use PhpParser\Node\UnionType as PhpParserUnionType;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\Generic\TemplateType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NullType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\UnionType;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\NodeAnalyzer\PropertyAnalyzer;
Expand All @@ -23,6 +24,7 @@
use Rector\DeadCode\PhpDoc\TagRemover\VarTagRemover;
use Rector\FamilyTree\Reflection\FamilyRelationsAnalyzer;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Php74\TypeAnalyzer\PropertyUnionTypeResolver;
use Rector\PHPStanStaticTypeMapper\DoctrineTypeAnalyzer;
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
use Rector\StaticTypeMapper\ValueObject\Type\AliasedObjectType;
Expand Down Expand Up @@ -73,7 +75,8 @@ public function __construct(
private ReflectionProvider $reflectionProvider,
private PropertyFetchAnalyzer $propertyFetchAnalyzer,
private FamilyRelationsAnalyzer $familyRelationsAnalyzer,
private PropertyAnalyzer $propertyAnalyzer
private PropertyAnalyzer $propertyAnalyzer,
private PropertyUnionTypeResolver $propertyUnionTypeResolver
) {
}

Expand Down Expand Up @@ -199,7 +202,8 @@ private function isNullOrNonClassLikeTypeOrMixedOrVendorLockedIn(
return true;
}

$type = $this->resolveTypePossibleUnionNullableType($node, $type);
$type = $this->propertyUnionTypeResolver->resolve($node, $type);

// is not class-type and should be skipped
if ($this->shouldSkipNonClassLikeType($node, $type)) {
return true;
Expand All @@ -217,28 +221,6 @@ private function isNullOrNonClassLikeTypeOrMixedOrVendorLockedIn(
return true;
}

private function resolveTypePossibleUnionNullableType(
Name|NullableType|\PhpParser\Node\UnionType $node,
Type $possibleUnionType
): Type {
if (! $node instanceof NullableType) {
return $possibleUnionType;
}

if (! $possibleUnionType instanceof UnionType) {
return $possibleUnionType;
}

$types = $possibleUnionType->getTypes();
foreach ($types as $type) {
if (! $type instanceof NullType) {
return $type;
}
}

return $possibleUnionType;
}

private function shouldSkipNonClassLikeType(Name|NullableType|PhpParserUnionType $node, Type $type): bool
{
// unwrap nullable type
Expand Down Expand Up @@ -278,7 +260,7 @@ private function addDefaultValueNullForNullableType(Property $property, Type $pr
return;
}

if (! $propertyType->isSuperTypeOf(new NullType())->yes()) {
if (! TypeCombinator::containsNull($propertyType)) {
return;
}

Expand Down Expand Up @@ -308,6 +290,12 @@ private function shouldSkipProperty(Property $property): bool
return true;
}

$trait = $this->betterNodeFinder->findParentType($property, Trait_::class);
// skip trait properties, as they ar unpredictable based on class context they appear in
if ($trait instanceof Trait_) {
return true;
}

if (! $this->privatePropertyOnly) {
return $this->propertyAnalyzer->hasForbiddenType($property);
}
Expand Down
34 changes: 34 additions & 0 deletions rules/Php74/TypeAnalyzer/PropertyUnionTypeResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Rector\Php74\TypeAnalyzer;

use PhpParser\Node\Name;
use PhpParser\Node\NullableType;
use PHPStan\Type\NullType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;

final class PropertyUnionTypeResolver
{
public function resolve(Name|NullableType|\PhpParser\Node\UnionType $phpUnionType, Type $possibleUnionType): Type
{
if (! $phpUnionType instanceof NullableType) {
return $possibleUnionType;
}

if (! $possibleUnionType instanceof UnionType) {
return $possibleUnionType;
}

$types = $possibleUnionType->getTypes();
foreach ($types as $type) {
if (! $type instanceof NullType) {
return $type;
}
}

return $possibleUnionType;
}
}
1 change: 0 additions & 1 deletion rules/PhpSpecToPHPUnit/Naming/PhpSpecRenaming.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ public function resolveTestedClass(Node $node): string
$className = $node->getAttribute(AttributeKey::CLASS_NAME);

$newClassName = StaticRectorStrings::removePrefixes($className, ['spec\\']);

return StaticRectorStrings::removeSuffixes($newClassName, [self::SPEC]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,17 @@ protected function setUp()
]);
}

public function isInPhpSpecBehavior(Node $node): bool
protected function isInPhpSpecBehavior(Node $node): bool
{
if ($node instanceof ClassLike) {
return $this->isObjectType($node, new ObjectType('PhpSpec\ObjectBehavior'));
}

$classLike = $this->betterNodeFinder->findParentType($node, ClassLike::class);
if (! $classLike instanceof ClassLike) {
return false;
}

return $this->isObjectType($classLike, new ObjectType('PhpSpec\ObjectBehavior'));
return $this->isInPhpSpecBehavior($classLike);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ public function refactor(Node $node): ?Node
}

$this->processMethodParamsToMocks($node);

return $node;
}

Expand Down Expand Up @@ -93,35 +92,35 @@ private function processMethodParamsToMocks(ClassMethod $classMethod): void

private function processMethodCall(MethodCall $methodCall): ?MethodCall
{
if ($this->isName($methodCall->name, 'shouldBeCalled')) {
if (! $methodCall->var instanceof MethodCall) {
throw new ShouldNotHappenException();
}
if (! $this->isName($methodCall->name, 'shouldBeCalled')) {
return null;
}

$mockMethodName = $this->getName($methodCall->var->name);
if ($mockMethodName === null) {
throw new ShouldNotHappenException();
}
if (! $methodCall->var instanceof MethodCall) {
throw new ShouldNotHappenException();
}

$arg = $methodCall->var->args[0] ?? null;
$mockMethodName = $this->getName($methodCall->var->name);
if ($mockMethodName === null) {
throw new ShouldNotHappenException();
}

$expectedArg = $arg instanceof Arg ? $arg->value : null;
$arg = $methodCall->var->args[0] ?? null;

$methodCall->var->name = new Identifier('expects');
$thisOnceMethodCall = $this->nodeFactory->createLocalMethodCall('atLeastOnce');
$methodCall->var->args = [new Arg($thisOnceMethodCall)];
$expectedArg = $arg instanceof Arg ? $arg->value : null;

$methodCall->name = new Identifier('method');
$methodCall->args = [new Arg(new String_($mockMethodName))];
$methodCall->var->name = new Identifier('expects');
$thisOnceMethodCall = $this->nodeFactory->createLocalMethodCall('atLeastOnce');
$methodCall->var->args = [new Arg($thisOnceMethodCall)];

if ($expectedArg !== null) {
return $this->appendWithMethodCall($methodCall, $expectedArg);
}
$methodCall->name = new Identifier('method');
$methodCall->args = [new Arg(new String_($mockMethodName))];

return $methodCall;
if ($expectedArg !== null) {
return $this->appendWithMethodCall($methodCall, $expectedArg);
}

return null;
return $methodCall;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,11 @@ public function refactor(Node $node): ?Node
return null;
}

// direct PHPUnit method calls, no need to call on property
if (in_array($methodName, ['atLeastOnce', 'equalTo', 'isInstanceOf', 'isType'], true)) {
return $node;
}

$node->var = $this->getTestedObjectPropertyFetch();

return $node;
Expand All @@ -201,12 +206,19 @@ private function prepareMethodCall(MethodCall $methodCall): void
return;
}

/** @var Class_ $classLike */
$classLike = $this->betterNodeFinder->findParentType($methodCall, Class_::class);
$class = $this->betterNodeFinder->findParentType($methodCall, Class_::class);
if (! $class instanceof Class_) {
return;
}

$this->matchersKeys = $this->matchersManipulator->resolveMatcherNamesFromClass($classLike);
$this->testedClass = $this->phpSpecRenaming->resolveTestedClass($methodCall);
$this->testedObjectPropertyFetch = $this->createTestedObjectPropertyFetch($classLike);
$className = $this->getName($class);
if (! is_string($className)) {
return;
}

$this->matchersKeys = $this->matchersManipulator->resolveMatcherNamesFromClass($class);
$this->testedClass = $this->phpSpecRenaming->resolveTestedClass($class);
$this->testedObjectPropertyFetch = $this->createTestedObjectPropertyFetch($class);

$this->isPrepared = true;
}
Expand Down Expand Up @@ -283,7 +295,6 @@ private function shouldSkip(MethodCall $methodCall): bool
private function createTestedObjectPropertyFetch(Class_ $class): PropertyFetch
{
$propertyName = $this->phpSpecRenaming->resolveObjectPropertyName($class);

return new PropertyFetch(new Variable(self::THIS), $propertyName);
}
}
6 changes: 3 additions & 3 deletions rules/TypeDeclaration/TypeInferer/SilentVoidResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\Yield_;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\Interface_;
use PhpParser\Node\Stmt\Return_;
use PhpParser\Node\Stmt\Switch_;
use PhpParser\Node\Stmt\Throw_;
Expand All @@ -27,8 +27,8 @@ public function __construct(

public function hasExclusiveVoid(ClassMethod | Closure | Function_ $functionLike): bool
{
$class = $this->betterNodeFinder->findParentType($functionLike, Class_::class);
if (! $class instanceof Class_) {
$interface = $this->betterNodeFinder->findParentType($functionLike, Interface_::class);
if ($interface instanceof Interface_) {
return false;
}

Expand Down

0 comments on commit ae5b81e

Please sign in to comment.