diff --git a/README.md b/README.md index 9da179f..fb96e30 100644 --- a/README.md +++ b/README.md @@ -366,6 +366,15 @@ enum TaskStatus: int And if you're using the same meta property in multiple enums, you can create a dedicated trait that includes this `@method` annotation. +## PHPStan + +To assist PHPStan when using invokable cases, you can include the PHPStan extensions into your own `phpstan.neon` file: + +```yaml +includes: + - ./vendor/archtechx/enums/extension.neon +``` + ## Development Run all checks locally: diff --git a/extension.neon b/extension.neon new file mode 100644 index 0000000..d236892 --- /dev/null +++ b/extension.neon @@ -0,0 +1,2 @@ +includes: + - ./src/PHPStan/InvokableCases/extension.neon \ No newline at end of file diff --git a/src/PHPStan/InvokableCases/ReflectionExtension.php b/src/PHPStan/InvokableCases/ReflectionExtension.php new file mode 100644 index 0000000..6ef612a --- /dev/null +++ b/src/PHPStan/InvokableCases/ReflectionExtension.php @@ -0,0 +1,31 @@ +getNativeReflection() instanceof ReflectionEnum + && $classReflection->hasTraitUse(InvokableCases::class) + ) { + return $classReflection->getNativeReflection()->hasCase($methodName); + } + + return false; + } + + public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection + { + return new StaticInvokableCaseMethodReflection($classReflection, $methodName); + } +} diff --git a/src/PHPStan/InvokableCases/StaticInvokableCaseMethodReflection.php b/src/PHPStan/InvokableCases/StaticInvokableCaseMethodReflection.php new file mode 100644 index 0000000..0abae71 --- /dev/null +++ b/src/PHPStan/InvokableCases/StaticInvokableCaseMethodReflection.php @@ -0,0 +1,109 @@ +callStaticMethod = $this->classReflection->getMethod('__callStatic', new OutOfClassScope()); + } + + public function getDeclaringClass(): ClassReflection + { + return $this->classReflection; + } + + public function isStatic(): bool + { + return true; + } + + public function isPrivate(): bool + { + return false; + } + + public function isPublic(): bool + { + return true; + } + + public function getDocComment(): ?string + { + return $this->callStaticMethod->getDocComment(); + } + + public function getName(): string + { + return $this->name; + } + + public function getPrototype(): ClassMemberReflection + { + return $this; + } + + /** + * @return ParametersAcceptor[] + */ + public function getVariants(): array + { + return [ + new FunctionVariant( + TemplateTypeMap::createEmpty(), + TemplateTypeMap::createEmpty(), + [], + false, + $this->classReflection->getBackedEnumType() ?? new StringType() + ), + ]; + } + + public function isDeprecated(): TrinaryLogic + { + return $this->callStaticMethod->isDeprecated(); + } + + public function getDeprecatedDescription(): ?string + { + return $this->callStaticMethod->getDeprecatedDescription(); + } + + public function isFinal(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isInternal(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function getThrowType(): ?Type + { + return $this->callStaticMethod->getThrowType(); + } + + public function hasSideEffects(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } +} diff --git a/src/PHPStan/InvokableCases/extension.neon b/src/PHPStan/InvokableCases/extension.neon new file mode 100644 index 0000000..6c9eb58 --- /dev/null +++ b/src/PHPStan/InvokableCases/extension.neon @@ -0,0 +1,5 @@ +services: + - + class: ArchTech\Enums\PHPStan\InvokableCases\ReflectionExtension + tags: + - phpstan.broker.methodsClassReflectionExtension \ No newline at end of file