From a773786d1657901afd7a09beddf8d2128e4938b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Unger?= Date: Mon, 19 Feb 2018 18:54:55 +0100 Subject: [PATCH 1/2] Update for latest PHPStan master --- .../PHPUnit/AssertSameBooleanExpectedRule.php | 23 +++++------ .../AssertSameDifferentTypesRuleTest.php | 40 ++++++++++++++++--- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/Rules/PHPUnit/AssertSameBooleanExpectedRule.php b/src/Rules/PHPUnit/AssertSameBooleanExpectedRule.php index 715ec965..aef53f10 100644 --- a/src/Rules/PHPUnit/AssertSameBooleanExpectedRule.php +++ b/src/Rules/PHPUnit/AssertSameBooleanExpectedRule.php @@ -4,8 +4,7 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; -use PHPStan\Type\FalseBooleanType; -use PHPStan\Type\TrueBooleanType; +use PHPStan\Type\Constant\ConstantBooleanType; class AssertSameBooleanExpectedRule implements \PHPStan\Rules\Rule { @@ -35,16 +34,16 @@ public function processNode(Node $node, Scope $scope): array $leftType = $scope->getType($node->args[0]->value); - if ($leftType instanceof TrueBooleanType) { - return [ - 'You should use assertTrue() instead of assertSame() when expecting "true"', - ]; - } - - if ($leftType instanceof FalseBooleanType) { - return [ - 'You should use assertFalse() instead of assertSame() when expecting "false"', - ]; + if ($leftType instanceof ConstantBooleanType) { + if ($leftType->getValue()) { + return [ + 'You should use assertTrue() instead of assertSame() when expecting "true"', + ]; + } else { + return [ + 'You should use assertFalse() instead of assertSame() when expecting "false"', + ]; + } } return []; diff --git a/tests/Rules/PHPUnit/AssertSameDifferentTypesRuleTest.php b/tests/Rules/PHPUnit/AssertSameDifferentTypesRuleTest.php index 4e81480e..fe6204f4 100644 --- a/tests/Rules/PHPUnit/AssertSameDifferentTypesRuleTest.php +++ b/tests/Rules/PHPUnit/AssertSameDifferentTypesRuleTest.php @@ -16,7 +16,7 @@ public function testRule(): void { $this->analyse([__DIR__ . '/data/assert-same.php'], [ [ - 'Call to assertSame() with different types string and int will always result in test failure.', + 'Call to assertSame() with different types string and int(1) will always result in test failure.', 10, ], [ @@ -24,7 +24,7 @@ public function testRule(): void 11, ], [ - 'Call to assertSame() with different types int and string will always result in test failure.', + 'Call to assertSame() with different types int(1) and string will always result in test failure.', 12, ], [ @@ -32,25 +32,53 @@ public function testRule(): void 13, ], [ - 'Call to assertSame() with different types array and array will always result in test failure.', + 'Call to assertSame() with different types array and array will always result in test failure.', 14, ], [ - 'Call to assertSame() with different types string and int will always result in test failure.', + 'Call to assertSame() with different types string and int(2) will always result in test failure.', 16, ], [ - 'Call to assertSame() with different types string and int will always result in test failure.', + 'Call to assertSame() with different types string and int(2) will always result in test failure.', 17, ], [ - 'Call to assertSame() with different types string and int will always result in test failure.', + 'Call to assertSame() with different types string and int(2) will always result in test failure.', 18, ], [ 'Call to assertSame() with different types array and array will always result in test failure.', 39, ], + [ + 'Call to assertSame() with different types array and array will always result in test failure.', + 45, + ], + [ + 'Call to assertSame() with different types string and string will always result in test failure.', + 47, + ], + [ + 'Call to assertSame() with different types array and array will always result in test failure.', + 51, + ], + [ + 'Call to assertSame() with different types array and array will always result in test failure.', + 52, + ], + [ + 'Call to assertSame() with different types int(1) and int(2) will always result in test failure.', + 53, + ], + [ + 'Call to assertSame() with different types int(1) and int(2) will always result in test failure.', + 54, + ], + [ + 'Call to assertSame() with different types int(1) and int(2) will always result in test failure.', + 55, + ], ]); } From 5c525781ed4161ca9214bd1a926adfb3c89f8a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Unger?= Date: Mon, 19 Feb 2018 20:18:13 +0100 Subject: [PATCH 2/2] Support string arguments --- .../CreateMockDynamicReturnTypeExtension.php | 16 +-- ...eateMockDynamicReturnTypeExtensionTest.php | 125 ++++++++++++++++++ tests/Type/PHPUnit/ExtensionTestCase.php | 79 +++++++++++ tests/Type/PHPUnit/data/MockedClass.php | 7 + tests/Type/PHPUnit/data/TestClass.php | 39 ++++++ 5 files changed, 254 insertions(+), 12 deletions(-) create mode 100644 tests/Type/PHPUnit/CreateMockDynamicReturnTypeExtensionTest.php create mode 100644 tests/Type/PHPUnit/ExtensionTestCase.php create mode 100644 tests/Type/PHPUnit/data/MockedClass.php create mode 100644 tests/Type/PHPUnit/data/TestClass.php diff --git a/src/Type/PHPUnit/CreateMockDynamicReturnTypeExtension.php b/src/Type/PHPUnit/CreateMockDynamicReturnTypeExtension.php index 6d74e3f9..631fcc9c 100644 --- a/src/Type/PHPUnit/CreateMockDynamicReturnTypeExtension.php +++ b/src/Type/PHPUnit/CreateMockDynamicReturnTypeExtension.php @@ -5,6 +5,7 @@ use PhpParser\Node\Expr\MethodCall; use PHPStan\Analyser\Scope; use PHPStan\Reflection\MethodReflection; +use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -38,26 +39,17 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method if (!isset($methodCall->args[$argumentIndex])) { return $methodReflection->getReturnType(); } - $arg = $methodCall->args[$argumentIndex]->value; - if (!($arg instanceof \PhpParser\Node\Expr\ClassConstFetch)) { + $argType = $scope->getType($methodCall->args[$argumentIndex]->value); + if (!$argType instanceof ConstantStringType) { return $methodReflection->getReturnType(); } - $class = $arg->class; - if (!($class instanceof \PhpParser\Node\Name)) { - return $methodReflection->getReturnType(); - } - - $class = (string) $class; + $class = $argType->getValue(); if ($class === 'static') { return $methodReflection->getReturnType(); } - if ($class === 'self') { - $class = $scope->getClassReflection()->getName(); - } - return TypeCombinator::intersect( new ObjectType($class), $methodReflection->getReturnType() diff --git a/tests/Type/PHPUnit/CreateMockDynamicReturnTypeExtensionTest.php b/tests/Type/PHPUnit/CreateMockDynamicReturnTypeExtensionTest.php new file mode 100644 index 00000000..530b4f88 --- /dev/null +++ b/tests/Type/PHPUnit/CreateMockDynamicReturnTypeExtensionTest.php @@ -0,0 +1,125 @@ +assertTypes( + __DIR__ . '/data/TestClass.php', + $description, + $expression, + [new CreateMockDynamicReturnTypeExtension()] + ); + } + +} diff --git a/tests/Type/PHPUnit/ExtensionTestCase.php b/tests/Type/PHPUnit/ExtensionTestCase.php new file mode 100644 index 00000000..d4cb588d --- /dev/null +++ b/tests/Type/PHPUnit/ExtensionTestCase.php @@ -0,0 +1,79 @@ +processFile($file, function (\PhpParser\Node $node, Scope $scope) use ($description, $expression, $evaluatedPointExpression): void { + $printer = new \PhpParser\PrettyPrinter\Standard(); + $printedNode = $printer->prettyPrint([$node]); + if ($printedNode === $evaluatedPointExpression) { + /** @var \PhpParser\Node\Expr $expressionNode */ + $expressionNode = $this->getParser()->parseString(sprintf('getType($expressionNode); + $this->assertTypeDescribe( + $description, + $type->describe(), + sprintf('%s at %s', $expression, $evaluatedPointExpression) + ); + } + }, $dynamicMethodReturnTypeExtensions, $dynamicStaticMethodReturnTypeExtensions); + } + + protected function processFile(string $file, \Closure $callback, array $dynamicMethodReturnTypeExtensions = [], array $dynamicStaticMethodReturnTypeExtensions = []): void + { + /** @var \PHPStan\PhpDoc\PhpDocStringResolver $phpDocStringResolver */ + $phpDocStringResolver = $this->getContainer()->getByType(PhpDocStringResolver::class); + + $printer = new \PhpParser\PrettyPrinter\Standard(); + $resolver = new NodeScopeResolver( + $this->createBroker(), + $this->getParser(), + $printer, + new FileTypeMapper($this->getParser(), $phpDocStringResolver, $this->createMock(Cache::class)), + new FileHelper('/'), + true, + true, + [] + ); + $resolver->processNodes( + $this->getParser()->parseFile($file), + new Scope( + $this->createBroker($dynamicMethodReturnTypeExtensions, $dynamicStaticMethodReturnTypeExtensions), + $printer, + new TypeSpecifier($printer), + $file + ), + $callback + ); + } + + protected function assertTypeDescribe(string $expectedDescription, string $actualDescription, string $label = ''): void + { + self::assertSame( + $expectedDescription, + $actualDescription, + $label + ); + } + +} diff --git a/tests/Type/PHPUnit/data/MockedClass.php b/tests/Type/PHPUnit/data/MockedClass.php new file mode 100644 index 00000000..8c28f9ff --- /dev/null +++ b/tests/Type/PHPUnit/data/MockedClass.php @@ -0,0 +1,7 @@ +createMock(MockedClass::class); + $b = $this->createConfiguredMock(MockedClass::class, []); + $c = $this->createPartialMock(MockedClass::class, []); + $d = $this->createTestProxy(MockedClass::class); + $e = $this->getMockForAbstractClass(MockedClass::class); + $f = $this->getMockFromWsdl('', MockedClass::class); + + $g = $this->createMock('CreateMockTest\MockedClass'); + $h = $this->createConfiguredMock('CreateMockTest\MockedClass', []); + $i = $this->createPartialMock('CreateMockTest\MockedClass', []); + $j = $this->createTestProxy('CreateMockTest\MockedClass'); + $k = $this->getMockForAbstractClass('CreateMockTest\MockedClass'); + $l = $this->getMockFromWsdl('', 'CreateMockTest\MockedClass'); + + $m = $this->createMock(self::class); + $n = $this->createConfiguredMock(self::class); + $o = $this->createPartialMock(self::class); + $p = $this->createTestProxy(self::class); + $q = $this->getMockForAbstractClass(self::class); + $r = $this->getMockFromWsdl('', self::class); + + $s = $this->createMock(static::class); + $t = $this->createConfiguredMock(static::class); + $u = $this->createPartialMock(static::class); + $v = $this->createTestProxy(static::class); + $w = $this->getMockForAbstractClass(static::class); + $x = $this->getMockFromWsdl('', static::class); + + die; + } +}