diff --git a/README.md b/README.md index 99b48b2..c3e771d 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ * [PHPStan](https://github.com/phpstan/phpstan) * [Money](https://github.com/moneyphp/money) -# THIS IS NOT FINISHED!!! ## Usage diff --git a/composer.json b/composer.json index 9d4b403..8d6afa8 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,9 @@ { "name": "johnstoncode/phpstan-moneyphp", - "description": "moneyphp Money class reflection extension for PHPStan", + "description": "Moneyphp Money class reflection extension for PHPStan", + "license": ["MIT"], "minimum-stability": "dev", + "prefer-stable": true, "authors": [ { "name": "Chris Johnston", @@ -13,16 +15,18 @@ "phpstan/phpstan": "^0.10", "moneyphp/money": "^1.3" }, - "autoload": { - "psr-4": { - "JohnstonCode\\": "src/", - "JohnstonCode\\Tests\\": "tests/" - } - }, "require-dev": { "phpunit/phpunit": "^7.2", "phpstan/phpstan-php-parser": "^0.10.0", "phpstan/phpstan-strict-rules": "^0.10.1", "phpstan/phpstan-phpunit": "^0.10.0" + }, + "autoload": { + "psr-4": { + "JohnstonCode\\": "src/" + } + }, + "autoload-dev": { + "classmap": ["tests/"] } } diff --git a/src/Reflection/Money/MoneyMethodReflection.php b/src/Reflection/Money/MoneyMethodReflection.php index aa489e5..d62d6d3 100644 --- a/src/Reflection/Money/MoneyMethodReflection.php +++ b/src/Reflection/Money/MoneyMethodReflection.php @@ -56,22 +56,11 @@ public function getName(): string return $this->name; } - - public function getParameters(): array - { - return []; - } - public function isVariadic(): bool { return false; } - public function getReturnType() - { - return $this->return; - } - /** * @return \PHPStan\Reflection\ParametersAcceptor[] */ diff --git a/src/Reflection/Money/MoneyMethodsReflectionExtension.php b/src/Reflection/Money/MoneyMethodsReflectionExtension.php index 2f603d7..8dd43d1 100644 --- a/src/Reflection/Money/MoneyMethodsReflectionExtension.php +++ b/src/Reflection/Money/MoneyMethodsReflectionExtension.php @@ -2,11 +2,10 @@ namespace JohnstonCode\Reflection\Money; -use Money\{Money, Currency}; +use Money\Currency; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\MethodsClassReflectionExtension; -use PHPStan\Type\ObjectType; class MoneyMethodsReflectionExtension implements MethodsClassReflectionExtension { @@ -16,19 +15,9 @@ public function hasMethod(ClassReflection $classReflection, string $methodName): return false; } - try { - $method = $classReflection->getNativeReflection()->getMethod($methodName); - - if (!$method->isStatic()) { - return true; - } - } catch (\Exception $e) { - - } - $currencies = Currency::getCurrencies(); - return array_key_exists($methodName, $currencies); + return ($classReflection->getNativeReflection()->hasMethod($methodName) || array_key_exists($methodName, $currencies)); } public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection @@ -36,12 +25,12 @@ public function getMethod(ClassReflection $classReflection, string $methodName): $currencies = Currency::getCurrencies(); if (array_key_exists($methodName, $currencies)) { - $returnType = new ObjectType('Money\Money'); - return new MoneyMethodReflection($classReflection, $methodName, true, false, $returnType); + return new MoneyStaticMethodReflection($classReflection, $methodName); } $method = $classReflection->getNativeReflection()->getMethod($methodName); return new MoneyMethodReflection($classReflection, $methodName, $method->isStatic(), $method->isPrivate()); } + } diff --git a/src/Reflection/Money/MoneyStaticMethodReflection.php b/src/Reflection/Money/MoneyStaticMethodReflection.php new file mode 100644 index 0000000..03b90c9 --- /dev/null +++ b/src/Reflection/Money/MoneyStaticMethodReflection.php @@ -0,0 +1,72 @@ +classReflection = $classReflection; + $this->name = $name; + } + + public function getDeclaringClass(): ClassReflection + { + return $this->classReflection; + } + + public function getPrototype(): ClassMemberReflection + { + return $this; + } + + public function isStatic(): bool + { + return true; + } + + public function isPrivate(): bool + { + return false; + } + + public function isPublic(): bool + { + return true; + } + + public function getName(): string + { + return $this->name; + } + + public function isVariadic(): bool + { + return false; + } + + /** + * @return \PHPStan\Reflection\ParametersAcceptor[] + */ + public function getVariants(): array + { + return [ + new FunctionVariant( + [new MoneyStaticParameterReflection()], + false, + new ObjectType('Money\Money') + ), + ]; + } +} \ No newline at end of file diff --git a/src/Reflection/Money/MoneyStaticParameterReflection.php b/src/Reflection/Money/MoneyStaticParameterReflection.php new file mode 100644 index 0000000..e3f6f5a --- /dev/null +++ b/src/Reflection/Money/MoneyStaticParameterReflection.php @@ -0,0 +1,36 @@ +broker = $this->createBroker(); - $this->extension = new \JohnstonCode\Reflection\Money\MoneyClassReflectionExtension(); - } - - public function testHasMethod(): void - { - $classReflection = $this->broker->getClass('Money\Money'); - $this->assertTrue($this->extension->hasMethod($classReflection, 'getUnits')); - } - - public function testHasStaticMethod(): void - { - $classReflection = $this->broker->getClass('Money\Money'); - $this->assertTrue($this->extension->hasMethod($classReflection, 'GBP')); - } - - public function testInvalidMethod(): void - { - $classReflection = $this->broker->getClass('Money\Money'); - $this->assertFalse($this->extension->hasMethod($classReflection, 'ZZZ')); - } - - public function testHasPrivateMethod(): void - { - $classReflection = $this->broker->getClass('Money\Money'); - $this->assertTrue($this->extension->hasMethod($classReflection, 'assertSameCurrency')); - } -} diff --git a/tests/Reflection/Money/MoneyMethodsReflectionExtensionTest.php b/tests/Reflection/Money/MoneyMethodsReflectionExtensionTest.php new file mode 100644 index 0000000..4266b8c --- /dev/null +++ b/tests/Reflection/Money/MoneyMethodsReflectionExtensionTest.php @@ -0,0 +1,83 @@ +broker = $this->createBroker(); + $this->extension = new MoneyMethodsReflectionExtension(); + } + + public function testHasMethod(): void + { + $classReflection = $this->broker->getClass('Money\Money'); + $this->assertTrue($this->extension->hasMethod($classReflection, 'getUnits')); + } + + public function testHasStaticMethod(): void + { + $classReflection = $this->broker->getClass('Money\Money'); + $this->assertTrue($this->extension->hasMethod($classReflection, 'GBP')); + } + + public function testInvalidMethod(): void + { + $classReflection = $this->broker->getClass('Money\Money'); + $this->assertFalse($this->extension->hasMethod($classReflection, 'ZZZ')); + } + + public function testHasPrivateMethod(): void + { + $classReflection = $this->broker->getClass('Money\Money'); + $this->assertTrue($this->extension->hasMethod($classReflection, 'assertSameCurrency')); + } + + public function testGetPublicMethod(): void + { + $classReflection = $this->broker->getClass('Money\Money'); + $methodReflection = $this->extension->getMethod($classReflection, 'getUnits'); + + $this->assertEquals('getUnits', $methodReflection->getName()); + $this->assertEquals($classReflection, $methodReflection->getDeclaringClass()); + $this->assertFalse($methodReflection->isStatic()); + $this->assertFalse($methodReflection->isVariadic()); + $this->assertFalse($methodReflection->isPrivate()); + $this->assertTrue($methodReflection->isPublic()); + } + + public function testGetPrivateMethod(): void + { + $classReflection = $this->broker->getClass('Money\Money'); + $methodReflection = $this->extension->getMethod($classReflection, 'assertSameCurrency'); + + $this->assertEquals('assertSameCurrency', $methodReflection->getName()); + $this->assertEquals($classReflection, $methodReflection->getDeclaringClass()); + $this->assertFalse($methodReflection->isStatic()); + $this->assertFalse($methodReflection->isVariadic()); + $this->assertTrue($methodReflection->isPrivate()); + $this->assertFalse($methodReflection->isPublic()); + } + + public function testGetStaticMethod(): void + { + $classReflection = $this->broker->getClass('Money\Money'); + $methodReflection = $this->extension->getMethod($classReflection, 'GBP'); + $parametersAcceptor = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants()); + + $this->assertEquals('GBP', $methodReflection->getName()); + $this->assertEquals($classReflection, $methodReflection->getDeclaringClass()); + $this->assertTrue($methodReflection->isStatic()); + $this->assertFalse($methodReflection->isVariadic()); + $this->assertFalse($methodReflection->isPrivate()); + $this->assertTrue($methodReflection->isPublic()); + $this->assertEquals(\Money\Money::class, $parametersAcceptor->getReturnType()->describe(VerbosityLevel::value())); + } +}