diff --git a/composer.json b/composer.json index bc9b4d70..0a4912b2 100644 --- a/composer.json +++ b/composer.json @@ -62,7 +62,8 @@ "friendsofphp/php-cs-fixer": "^3.48", "phpstan/phpstan": "^1.6", "phpunit/phpunit": "^9.0", - "vimeo/psalm": "^4.23" + "rector/rector": "^1.0", + "vimeo/psalm": "^4.30" }, "suggest": { "doctrine/annotations": "^2.0" @@ -79,6 +80,7 @@ }, "scripts-descriptions": { "cs": "Fix all codestyle issues", + "rector": "Automatic refactoring", "lint": "Test codestyle", "test": "Run all non-legacy and codestyle tests", "testlegacy": "Run tests using the legacy TokenAnalyser", @@ -93,7 +95,11 @@ }, "scripts": { "cs": "export XDEBUG_MODE=off && php-cs-fixer fix --allow-risky=yes", - "lint": "@cs --dry-run", + "rector": "rector process src", + "lint": [ + "@cs --dry-run", + "@rector --dry-run" + ], "test": [ "export XDEBUG_MODE=off && phpunit", "@lint" diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 0fa9f3fc..3c36cd70 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -50,11 +50,6 @@ parameters: count: 1 path: src/Annotations/Schema.php - - - message: "#^If condition is always true\\.$#" - count: 1 - path: src/Generator.php - - message: "#^Call to function is_array\\(\\) with bool\\|OpenApi\\\\Annotations\\\\AdditionalProperties will always evaluate to false\\.$#" count: 1 diff --git a/rector.php b/rector.php new file mode 100644 index 00000000..e0a7c581 --- /dev/null +++ b/rector.php @@ -0,0 +1,34 @@ +withRules([ + TypedPropertyFromStrictConstructorRector::class + ]) + ->withSkip([ + CombineIfRector::class, + ExplicitBoolCompareRector::class, + ExplicitReturnNullRector::class => [ + __DIR__ . '/src/Analysers/TokenAnalyser.php', + ], + ForRepeatedCountToOwnVariableRector::class, + RemoveAlwaysTrueIfConditionRector::class => [ + __DIR__ . '/src/Processors/ExpandEnums.php', + ] , + RemoveDeadInstanceOfRector::class => [ + __DIR__ . '/src/Processors/ExpandEnums.php', + ], + ShortenElseIfRector::class, + ]) + ->withPreparedSets(true, true) + ->withPhpVersion(PhpVersion::PHP_74); diff --git a/src/Analysers/AttributeAnnotationFactory.php b/src/Analysers/AttributeAnnotationFactory.php index c93609a2..7a4e0ba5 100644 --- a/src/Analysers/AttributeAnnotationFactory.php +++ b/src/Analysers/AttributeAnnotationFactory.php @@ -12,19 +12,13 @@ class AttributeAnnotationFactory implements AnnotationFactoryInterface { - /** @var Generator|null */ - protected $generator; + use GeneratorAwareTrait; public function isSupported(): bool { return \PHP_VERSION_ID >= 80100; } - public function setGenerator(Generator $generator): void - { - $this->generator = $generator; - } - public function build(\Reflector $reflector, Context $context): array { if (!$this->isSupported() || !method_exists($reflector, 'getAttributes')) { @@ -116,9 +110,7 @@ public function build(\Reflector $reflector, Context $context): array Generator::$context = null; } - $annotations = array_values(array_filter($annotations, function ($a) { - return $a instanceof OA\AbstractAnnotation; - })); + $annotations = array_values(array_filter($annotations, fn ($a) => $a instanceof OA\AbstractAnnotation)); // merge backwards into parents... $isParent = function (OA\AbstractAnnotation $annotation, OA\AbstractAnnotation $possibleParent): bool { @@ -140,7 +132,7 @@ public function build(\Reflector $reflector, Context $context): array } // Property can be nested... - return $annotation->getRoot() != $possibleParent->getRoot() + return $annotation->getRoot() !== $possibleParent->getRoot() && ($explicitParent || ($isAttachable && $isParentAllowed)); }; diff --git a/src/Analysers/DocBlockAnnotationFactory.php b/src/Analysers/DocBlockAnnotationFactory.php index 435c4776..469a1070 100644 --- a/src/Analysers/DocBlockAnnotationFactory.php +++ b/src/Analysers/DocBlockAnnotationFactory.php @@ -12,11 +12,9 @@ class DocBlockAnnotationFactory implements AnnotationFactoryInterface { - /** @var DocBlockParser|null */ - protected $docBlockParser = null; + use GeneratorAwareTrait; - /** @var Generator|null */ - protected $generator = null; + protected ?DocBlockParser $docBlockParser = null; public function __construct(?DocBlockParser $docBlockParser = null) { diff --git a/src/Analysers/DocBlockParser.php b/src/Analysers/DocBlockParser.php index 5e68cc39..a4045fce 100644 --- a/src/Analysers/DocBlockParser.php +++ b/src/Analysers/DocBlockParser.php @@ -16,10 +16,7 @@ */ class DocBlockParser { - /** - * @var DocParser - */ - protected $docParser; + protected DocParser $docParser; /** * @param array $aliases diff --git a/src/Analysers/GeneratorAwareTrait.php b/src/Analysers/GeneratorAwareTrait.php new file mode 100644 index 00000000..afb9f314 --- /dev/null +++ b/src/Analysers/GeneratorAwareTrait.php @@ -0,0 +1,19 @@ +generator = $generator; + } +} diff --git a/src/Analysers/ReflectionAnalyser.php b/src/Analysers/ReflectionAnalyser.php index fb67aa13..8c561c10 100644 --- a/src/Analysers/ReflectionAnalyser.php +++ b/src/Analysers/ReflectionAnalyser.php @@ -22,18 +22,16 @@ */ class ReflectionAnalyser implements AnalyserInterface { - /** @var AnnotationFactoryInterface[] */ - protected $annotationFactories; + use GeneratorAwareTrait; - /** @var Generator|null */ - protected $generator; + /** @var AnnotationFactoryInterface[] */ + protected array $annotationFactories = []; /** * @param array $annotationFactories */ public function __construct(array $annotationFactories = []) { - $this->annotationFactories = []; foreach ($annotationFactories as $annotationFactory) { if ($annotationFactory->isSupported()) { $this->annotationFactories[] = $annotationFactory; @@ -113,13 +111,11 @@ protected function analyzeFqdn(string $fqdn, Analysis $analysis, array $details) 'methods' => [], 'context' => $context, ]; - $normaliseClass = function (string $name): string { - return '\\' . ltrim($name, '\\'); - }; + $normaliseClass = fn (string $name): string => '\\' . ltrim($name, '\\'); if ($parentClass = $rc->getParentClass()) { $definition['extends'] = $normaliseClass($parentClass->getName()); } - $definition[$contextType == 'class' ? 'implements' : 'extends'] = array_map($normaliseClass, $details['interfaces']); + $definition[$contextType === 'class' ? 'implements' : 'extends'] = array_map($normaliseClass, $details['interfaces']); $definition['traits'] = array_map($normaliseClass, $details['traits']); foreach ($this->annotationFactories as $annotationFactory) { diff --git a/src/Analysers/TokenAnalyser.php b/src/Analysers/TokenAnalyser.php index d7e8fa4e..ad2dc021 100644 --- a/src/Analysers/TokenAnalyser.php +++ b/src/Analysers/TokenAnalyser.php @@ -15,13 +15,7 @@ */ class TokenAnalyser implements AnalyserInterface { - /** @var Generator|null */ - protected $generator; - - public function setGenerator(Generator $generator): void - { - $this->generator = $generator; - } + use GeneratorAwareTrait; /** * Extract and process all doc-comments from a file. @@ -166,7 +160,9 @@ protected function fromTokens(array $tokens, Context $parseContext): Analysis if ($token[0] === T_IMPLEMENTS) { $schemaContext->implements = $this->parseNamespaceList($tokens, $token, $parseContext); - $classDefinition['implements'] = array_map([$schemaContext, 'fullyQualifiedName'], $schemaContext->implements); + $classDefinition['implements'] = array_map(function (?string $source) use ($schemaContext): string { + return $schemaContext->fullyQualifiedName($source); + }, $schemaContext->implements); } if ($comment) { @@ -207,7 +203,9 @@ protected function fromTokens(array $tokens, Context $parseContext): Analysis if ($token[0] === T_EXTENDS) { $schemaContext->extends = $this->parseNamespaceList($tokens, $token, $parseContext); - $interfaceDefinition['extends'] = array_map([$schemaContext, 'fullyQualifiedName'], $schemaContext->extends); + $interfaceDefinition['extends'] = array_map(function (?string $source) use ($schemaContext): string { + return $schemaContext->fullyQualifiedName($source); + }, $schemaContext->extends); } if ($comment) { diff --git a/src/Analysers/TokenScanner.php b/src/Analysers/TokenScanner.php index 872753db..8ba9ce9e 100644 --- a/src/Analysers/TokenScanner.php +++ b/src/Analysers/TokenScanner.php @@ -66,7 +66,7 @@ protected function scanTokens(array $tokens): array break; case '}': array_pop($stack); - if (count($stack) == $unitLevel) { + if (count($stack) === $unitLevel) { $currentName = null; } break; @@ -76,7 +76,7 @@ protected function scanTokens(array $tokens): array switch ($token[0]) { case T_ABSTRACT: - if (count($stack)) { + if ($stack !== []) { $isAbstractFunction = true; } break; @@ -115,7 +115,7 @@ protected function scanTokens(array $tokens): array // unless ... if (is_string($token) && ($token === '(' || $token === '{')) { // new class[()] { ... } - if ('{' == $token) { + if ('{' === $token) { prev($tokens); } break; @@ -212,7 +212,7 @@ protected function scanTokens(array $tokens): array /** * Get the next token that is not whitespace or comment. * - * @return string|array|false + * @return string|array|false Next token */ protected function nextToken(array &$tokens) { @@ -254,7 +254,7 @@ protected function resolveFQN(array $names, string $namespace, array $uses): arr protected function skipTo(array &$tokens, string $char, bool $prev = false): void { while (false !== ($token = next($tokens))) { - if (is_string($token) && $token == $char) { + if (is_string($token) && $token === $char) { if ($prev) { prev($tokens); } diff --git a/src/Analysis.php b/src/Analysis.php index e749f8a6..50bd00e9 100644 --- a/src/Analysis.php +++ b/src/Analysis.php @@ -17,50 +17,34 @@ */ class Analysis { - /** - * @var \SplObjectStorage - */ - public $annotations; + public \SplObjectStorage $annotations; /** * Class definitions. - * - * @var array */ - public $classes = []; + public array $classes = []; /** * Interface definitions. - * - * @var array */ - public $interfaces = []; + public array $interfaces = []; /** * Trait definitions. - * - * @var array */ - public $traits = []; + public array $traits = []; /** * Enum definitions. - * - * @var array */ - public $enums = []; + public array $enums = []; /** * The target OpenApi annotation. - * - * @var OA\OpenApi|null */ - public $openapi = null; + public ?OA\OpenApi $openapi = null; - /** - * @var Context|null - */ - public $context = null; + public ?Context $context = null; public function __construct(array $annotations = [], ?Context $context = null) { @@ -150,7 +134,7 @@ public function addAnalysis(Analysis $analysis): void $this->interfaces = array_merge($this->interfaces, $analysis->interfaces); $this->traits = array_merge($this->traits, $analysis->traits); $this->enums = array_merge($this->enums, $analysis->enums); - if ($this->openapi === null && $analysis->openapi !== null) { + if (!$this->openapi instanceof OA\OpenApi && $analysis->openapi instanceof OA\OpenApi) { $this->openapi = $analysis->openapi; } } @@ -347,7 +331,7 @@ public function getAnnotationForSource(string $fqdn, string $class): ?OA\Abstrac if (is_iterable($definition['context']->annotations)) { /** @var OA\AbstractAnnotation $annotation */ foreach (array_reverse($definition['context']->annotations) as $annotation) { - if (is_a($annotation, $class) && $annotation->isRoot($class) && !$annotation->_context->is('generated')) { + if ($annotation instanceof $class && $annotation->isRoot($class) && !$annotation->_context->is('generated')) { return $annotation; } } @@ -379,7 +363,7 @@ public function getContext(object $annotation): ?Context */ public function merged(): Analysis { - if ($this->openapi === null) { + if (!$this->openapi instanceof OA\OpenApi) { throw new OpenApiException('No openapi target set. Run the MergeIntoOpenApi processor'); } $unmerged = $this->openapi->_unmerged; @@ -436,7 +420,7 @@ public function process($processors = null): void public function validate(): bool { - if ($this->openapi !== null) { + if ($this->openapi instanceof OA\OpenApi) { return $this->openapi->validate(); } diff --git a/src/Annotations/AbstractAnnotation.php b/src/Annotations/AbstractAnnotation.php index e8468549..227bc21e 100644 --- a/src/Annotations/AbstractAnnotation.php +++ b/src/Annotations/AbstractAnnotation.php @@ -38,7 +38,7 @@ abstract class AbstractAnnotation implements \JsonSerializable /** * @var Context|null */ - public $_context = null; + public $_context; /** * Annotations that couldn't be merged by mapping or postprocessing. @@ -241,7 +241,7 @@ public function mergeProperties($object): void $identity = method_exists($object, 'identity') ? $object->identity() : get_class($object); $context1 = $this->_context; $context2 = property_exists($object, '_context') ? $object->_context : 'unknown'; - if (is_object($this->{$property}) && $this->{$property} instanceof AbstractAnnotation) { + if ($this->{$property} instanceof AbstractAnnotation) { $context1 = $this->{$property}->_context; } $this->_context->logger->error('Multiple definitions for ' . $identity . '->' . $property . "\n Using: " . $context1 . "\n Skipping: " . $context2); @@ -307,7 +307,7 @@ public function jsonSerialize() // Correct empty array to empty objects. foreach (static::$_types as $property => $type) { - if ($type === 'object' && is_array($data->{$property}) && empty($data->{$property})) { + if ($type === 'object' && is_array($data->{$property}) && $data->{$property} === []) { $data->{$property} = new \stdClass(); } } @@ -338,11 +338,7 @@ public function jsonSerialize() } else { $key = $item->{$keyField}; if (!Generator::isDefault($key) && empty($object->{$key})) { - if ($item instanceof \JsonSerializable) { - $object->{$key} = $item->jsonSerialize(); - } else { - $object->{$key} = $item; - } + $object->{$key} = $item instanceof \JsonSerializable ? $item->jsonSerialize() : $item; unset($object->{$key}->{$keyField}); } } @@ -374,7 +370,7 @@ public function jsonSerialize() // preserve other properties foreach (get_object_vars($this) as $property => $value) { - if ('_' == $property[0] || in_array($property, ['ref', 'nullable'])) { + if ('_' === $property[0] || in_array($property, ['ref', 'nullable'])) { continue; } if (!Generator::isDefault($value)) { @@ -503,7 +499,7 @@ public function validate(array $stack = [], array $skip = [], string $ref = '', } if (property_exists($this, 'ref') && !Generator::isDefault($this->ref) && is_string($this->ref)) { - if (substr($this->ref, 0, 2) === '#/' && count($stack) > 0 && $stack[0] instanceof OpenApi) { + if (substr($this->ref, 0, 2) === '#/' && $stack !== [] && $stack[0] instanceof OpenApi) { // Internal reference try { $stack[0]->ref($this->ref); @@ -562,7 +558,7 @@ public function validate(array $stack = [], array $skip = [], string $ref = '', } } - return self::_validate($this, $stack, $skip, $ref, $context) ? $valid : false; + return self::_validate($this, $stack, $skip, $ref, $context) && $valid; } /** @@ -668,7 +664,7 @@ public function getRoot(): string */ public function isRoot(string $rootClass): bool { - return get_class($this) == $rootClass || $this->getRoot() == $rootClass; + return get_class($this) === $rootClass || $this->getRoot() === $rootClass; } /** @@ -700,7 +696,7 @@ private function validateType(string $type, $value): bool return false; } $itemType = substr($type, 1, -1); - foreach ($value as $i => $item) { + foreach ($value as $item) { if ($this->validateType($itemType, $item) === false) { return false; } @@ -764,7 +760,7 @@ private function validateArrayType($value): bool return false; } $count = 0; - foreach ($value as $i => $item) { + foreach (array_keys($value) as $i) { // not a array, but a hash/map if ($count !== $i) { return false; @@ -801,8 +797,6 @@ protected function combine(...$args): array } } - return array_filter($combined, function ($value) { - return !Generator::isDefault($value) && $value !== null; - }); + return array_filter($combined, fn ($value) => !Generator::isDefault($value) && $value !== null); } } diff --git a/src/Annotations/Flow.php b/src/Annotations/Flow.php index 54092062..c94f9446 100644 --- a/src/Annotations/Flow.php +++ b/src/Annotations/Flow.php @@ -97,7 +97,7 @@ class Flow extends AbstractAnnotation #[\ReturnTypeWillChange] public function jsonSerialize() { - if (is_array($this->scopes) && empty($this->scopes)) { + if ($this->scopes === []) { $this->scopes = new \stdClass(); } diff --git a/src/Annotations/OpenApi.php b/src/Annotations/OpenApi.php index 5351a6e8..42e1af12 100644 --- a/src/Annotations/OpenApi.php +++ b/src/Annotations/OpenApi.php @@ -179,11 +179,7 @@ public function saveAs(string $filename, string $format = 'auto'): void $format = strtolower(substr($filename, -5)) === '.json' ? 'json' : 'yaml'; } - if (strtolower($format) === 'json') { - $content = $this->toJson(); - } else { - $content = $this->toYaml(); - } + $content = strtolower($format) === 'json' ? $this->toJson() : $this->toYaml(); if (file_put_contents($filename, $content) === false) { throw new OpenApiException('Failed to saveAs("' . $filename . '", "' . $format . '")'); @@ -230,11 +226,9 @@ private static function resolveRef(string $ref, string $resolved, $container, ar return $container->{$property}; } $mapping = []; - if ($container instanceof AbstractAnnotation) { - foreach ($container::$_nested as $nestedClass => $nested) { - if (is_string($nested) === false && count($nested) === 2 && $nested[0] === $property) { - $mapping[$nestedClass] = $nested[1]; - } + foreach ($container::$_nested as $nestedClass => $nested) { + if (is_string($nested) === false && count($nested) === 2 && $nested[0] === $property) { + $mapping[$nestedClass] = $nested[1]; } } diff --git a/src/Annotations/Operation.php b/src/Annotations/Operation.php index bc089dc1..17407269 100644 --- a/src/Annotations/Operation.php +++ b/src/Annotations/Operation.php @@ -224,7 +224,7 @@ public function validate(array $stack = [], array $skip = [], string $ref = '', if (!Generator::isDefault($this->responses)) { foreach ($this->responses as $response) { - if (!Generator::isDefault($response->response) && $response->response !== 'default' && preg_match('/^([12345]{1}[0-9]{2})|([12345]{1}XX)$/', (string) $response->response) === 0) { + if (!Generator::isDefault($response->response) && $response->response !== 'default' && preg_match('/^([12345]{1}\d{2})|([12345]{1}XX)$/', (string) $response->response) === 0) { $this->_context->logger->warning('Invalid value "' . $response->response . '" for ' . $response->_identity([]) . '->response, expecting "default", a HTTP Status Code or HTTP Status Code range definition in ' . $response->_context); $valid = false; } diff --git a/src/Context.php b/src/Context.php index 907617c1..68e85782 100644 --- a/src/Context.php +++ b/src/Context.php @@ -47,10 +47,8 @@ class Context { /** * Prototypical inheritance for properties. - * - * @var Context|null */ - private $parent; + private ?Context $parent; /** * @deprecated @@ -117,7 +115,7 @@ public function with(string $property): ?Context if ($this->is($property)) { return $this; } - if ($this->parent !== null) { + if ($this->parent instanceof Context) { return $this->parent->with($property); } @@ -129,7 +127,7 @@ public function with(string $property): ?Context */ public function root(): Context { - if ($this->parent !== null) { + if ($this->parent instanceof Context) { return $this->parent->root(); } @@ -196,7 +194,7 @@ public function getDebugLocation(): string */ public function __get(string $property) { - if ($this->parent !== null) { + if ($this->parent instanceof Context) { return $this->parent->{$property}; } @@ -239,7 +237,7 @@ public static function detect(int $index = 0): Context if (isset($caller['class'])) { $fqn = explode('\\', $caller['class']); $context->class = array_pop($fqn); - if (count($fqn)) { + if ($fqn !== []) { $context->namespace = implode('\\', $fqn); } } @@ -257,12 +255,7 @@ public function fullyQualifiedName(?string $source): string return ''; } - if ($this->namespace) { - $namespace = str_replace('\\\\', '\\', '\\' . $this->namespace . '\\'); - } else { - // global namespace - $namespace = '\\'; - } + $namespace = $this->namespace ? str_replace('\\\\', '\\', '\\' . $this->namespace . '\\') : '\\'; $thisSource = $this->class ?? $this->interface ?? $this->trait; if ($thisSource && strcasecmp($source, $thisSource) === 0) { diff --git a/src/Generator.php b/src/Generator.php index b9b2aa2a..6992618a 100644 --- a/src/Generator.php +++ b/src/Generator.php @@ -6,7 +6,6 @@ namespace OpenApi; -use Doctrine\Common\Annotations\AnnotationRegistry; use OpenApi\Analysers\AnalyserInterface; use OpenApi\Analysers\AttributeAnnotationFactory; use OpenApi\Analysers\DocBlockAnnotationFactory; @@ -28,10 +27,8 @@ class Generator { /** * Allows Annotation classes to know the context of the annotation that is being processed. - * - * @var Context|null */ - public static $context; + public static ?Context $context; /** @var string Magic value to differentiate between null and undefined. */ public const UNDEFINED = '@OA\Generator::UNDEFINED🙈'; @@ -42,22 +39,19 @@ class Generator public const DEFAULT_NAMESPACES = ['OpenApi\\Annotations\\']; /** @var array Map of namespace aliases to be supported by doctrine. */ - protected $aliases; + protected array $aliases; /** @var array|null List of annotation namespaces to be autoloaded by doctrine. */ - protected $namespaces; + protected ?array $namespaces; - /** @var AnalyserInterface|null The configured analyzer. */ - protected $analyser = null; + protected ?AnalyserInterface $analyser = null; /** @var array */ - protected $config = []; + protected array $config = []; - /** @var Pipeline|null */ - protected $processorPipeline = null; + protected ?Pipeline $processorPipeline = null; - /** @var LoggerInterface|null PSR logger. */ - protected $logger = null; + protected ?LoggerInterface $logger = null; /** * OpenApi version override. @@ -66,12 +60,8 @@ class Generator * * Due to the order of processing any conditional code using this (via `Context::$version`) * must come only after the analysis is finished. - * - * @var string|null */ - protected $version = null; - - private $configStack; + protected ?string $version = null; public function __construct(?LoggerInterface $logger = null) { @@ -79,49 +69,6 @@ public function __construct(?LoggerInterface $logger = null) $this->setAliases(self::DEFAULT_ALIASES); $this->setNamespaces(self::DEFAULT_NAMESPACES); - - // kinda config stack to stay BC... - // @deprecated Can be removed once doctrine/annotations 2.0 becomes mandatory - $this->configStack = new class() { - protected $generator; - - public function push(Generator $generator): void - { - $this->generator = $generator; - /* @phpstan-ignore-next-line */ - if (class_exists(AnnotationRegistry::class, true) && method_exists(AnnotationRegistry::class, 'registerLoader')) { - // keeping track of &this->generator allows to 'disable' the loader after we are done; - // no unload, unfortunately :/ - $gref = &$this->generator; - AnnotationRegistry::registerLoader( - function (string $class) use (&$gref): bool { - if ($gref) { - foreach ($gref->getNamespaces() as $namespace) { - if (strtolower(substr($class, 0, strlen($namespace))) === strtolower($namespace)) { - $loaded = class_exists($class); - if (!$loaded && $namespace === 'OpenApi\\Annotations\\') { - if (in_array(strtolower(substr($class, 20)), ['definition', 'path'])) { - // Detected an 2.x annotation? - throw new OpenApiException('The annotation @SWG\\' . substr($class, 20) . '() is deprecated. Found in ' . Generator::$context . "\nFor more information read the migration guide: https://github.com/zircote/swagger-php/blob/master/docs/Migrating-to-v3.md"); - } - } - - return $loaded; - } - } - } - - return false; - } - ); - } - } - - public function pop(): void - { - $this->generator = null; - } - }; } public static function isDefault($value): bool @@ -219,7 +166,7 @@ protected function normaliseConfig(array $config): array $value = 'true' == $value; } - if ($isList = ('[]' == substr($key, -2))) { + if ($isList = ('[]' === substr($key, -2))) { $key = substr($key, 0, -2); } $token = explode('.', $key); @@ -257,7 +204,7 @@ public function setConfig(array $config): Generator public function getProcessorPipeline(): Pipeline { - if (null === $this->processorPipeline) { + if (!$this->processorPipeline instanceof Pipeline) { $this->processorPipeline = new Pipeline([ new Processors\DocBlockDescriptions(), new Processors\MergeIntoOpenApi(), @@ -402,9 +349,7 @@ public function updateProcessor($processor, ?callable $matcher = null): Generato return $processor instanceof $otherClass; }; - $processors = array_map(function ($other) use ($processor, $matcher) { - return $matcher($other) ? $processor : $other; - }, $this->getProcessors()); + $processors = array_map(fn ($other) => $matcher($other) ? $processor : $other, $this->getProcessors()); $this->setProcessors($processors); return $this; @@ -472,12 +417,7 @@ public function withContext(callable $callable) ]); $analysis = new Analysis([], $rootContext); - $this->configStack->push($this); - try { - return $callable($this, $analysis, $rootContext); - } finally { - $this->configStack->pop(); - } + return $callable($this, $analysis, $rootContext); } /** @@ -501,26 +441,21 @@ public function generate(iterable $sources, ?Analysis $analysis = null, bool $va $analysis = $analysis ?: new Analysis([], $rootContext); $analysis->context = $analysis->context ?: $rootContext; - $this->configStack->push($this); - try { - $this->scanSources($sources, $analysis, $rootContext); + $this->scanSources($sources, $analysis, $rootContext); - // post-processing - $this->getProcessorPipeline()->process($analysis); + // post-processing + $this->getProcessorPipeline()->process($analysis); - if ($analysis->openapi) { - // overwrite default/annotated version - $analysis->openapi->openapi = $this->getVersion() ?: $analysis->openapi->openapi; - // update context to provide the same to validation/serialisation code - $rootContext->version = $analysis->openapi->openapi; - } + if ($analysis->openapi) { + // overwrite default/annotated version + $analysis->openapi->openapi = $this->getVersion() ?: $analysis->openapi->openapi; + // update context to provide the same to validation/serialisation code + $rootContext->version = $analysis->openapi->openapi; + } - // validation - if ($validate) { - $analysis->validate(); - } - } finally { - $this->configStack->pop(); + // validation + if ($validate) { + $analysis->validate(); } return $analysis->openapi; diff --git a/src/Loggers/ConsoleLogger.php b/src/Loggers/ConsoleLogger.php index 3bcd5c6e..a85232a7 100644 --- a/src/Loggers/ConsoleLogger.php +++ b/src/Loggers/ConsoleLogger.php @@ -25,8 +25,7 @@ class ConsoleLogger extends AbstractLogger implements LoggerInterface /** @var bool */ protected $loggedMessageAboveNotice = false; - /** @var bool */ - protected $debug; + protected bool $debug; public function __construct(bool $debug = false) { @@ -64,7 +63,7 @@ public function log($level, $message, array $context = []): void $color = static::COLOR_ERROR; break; } - $stop = !empty($color) ? static::COLOR_STOP : ''; + $stop = empty($color) ? '' : static::COLOR_STOP; if (!in_array($level, self::LOG_LEVELS_UP_TO_NOTICE, true)) { $this->loggedMessageAboveNotice = true; @@ -83,7 +82,7 @@ public function log($level, $message, array $context = []): void if ($this->debug) { if ($exception) { error_log($exception->getTraceAsString()); - } elseif (!empty($logLine)) { + } elseif ($logLine !== '' && $logLine !== '0') { $stack = explode(PHP_EOL, (new \Exception())->getTraceAsString()); // self array_shift($stack); diff --git a/src/Loggers/DefaultLogger.php b/src/Loggers/DefaultLogger.php index d4118f0d..75be1833 100644 --- a/src/Loggers/DefaultLogger.php +++ b/src/Loggers/DefaultLogger.php @@ -18,15 +18,7 @@ public function log($level, $message, array $context = []): void return; } - if ($message instanceof \Exception) { - $message = $message->getMessage(); - } - - if (in_array($level, [LogLevel::NOTICE, LogLevel::INFO])) { - $error_level = E_USER_NOTICE; - } else { - $error_level = E_USER_WARNING; - } + $error_level = in_array($level, [LogLevel::NOTICE, LogLevel::INFO]) ? E_USER_NOTICE : E_USER_WARNING; trigger_error($message, $error_level); } diff --git a/src/Processors/AugmentParameters.php b/src/Processors/AugmentParameters.php index 2c882ba6..fbe0f579 100644 --- a/src/Processors/AugmentParameters.php +++ b/src/Processors/AugmentParameters.php @@ -18,7 +18,7 @@ class AugmentParameters implements ProcessorInterface { use DocblockTrait; - protected $augmentOperationParameters = true; + protected bool $augmentOperationParameters; public function __construct(bool $augmentOperationParameters = true) { diff --git a/src/Processors/AugmentSchemas.php b/src/Processors/AugmentSchemas.php index a07b2aa3..ebc4d0b7 100644 --- a/src/Processors/AugmentSchemas.php +++ b/src/Processors/AugmentSchemas.php @@ -93,13 +93,13 @@ protected function augmentType(Analysis $analysis, array $schemas): void { foreach ($schemas as $schema) { if (Generator::isDefault($schema->type)) { - if (is_array($schema->properties) && count($schema->properties) > 0) { + if (is_array($schema->properties) && $schema->properties !== []) { $schema->type = 'object'; - } elseif (is_array($schema->additionalProperties) && count($schema->additionalProperties) > 0) { + } elseif (is_array($schema->additionalProperties) && $schema->additionalProperties !== []) { $schema->type = 'object'; - } elseif (is_array($schema->patternProperties) && count($schema->patternProperties) > 0) { + } elseif (is_array($schema->patternProperties) && $schema->patternProperties !== []) { $schema->type = 'object'; - } elseif (is_array($schema->propertyNames) && count($schema->propertyNames) > 0) { + } elseif (is_array($schema->propertyNames) && $schema->propertyNames !== []) { $schema->type = 'object'; } } else { diff --git a/src/Processors/CleanUnmerged.php b/src/Processors/CleanUnmerged.php index dacdaa10..6b3e2147 100644 --- a/src/Processors/CleanUnmerged.php +++ b/src/Processors/CleanUnmerged.php @@ -20,9 +20,9 @@ public function __invoke(Analysis $analysis) /** @var OA\AbstractAnnotation $annotation */ foreach ($analysis->annotations as $annotation) { if (property_exists($annotation, '_unmerged')) { - foreach ($annotation->_unmerged as $i => $item) { + foreach ($annotation->_unmerged as $ii => $item) { if ($merged->contains($item)) { - unset($annotation->_unmerged[$i]); // Property was merged + unset($annotation->_unmerged[$ii]); // Property was merged } } } diff --git a/src/Processors/CleanUnusedComponents.php b/src/Processors/CleanUnusedComponents.php index 1871c81f..ecd4b0c6 100644 --- a/src/Processors/CleanUnusedComponents.php +++ b/src/Processors/CleanUnusedComponents.php @@ -17,7 +17,7 @@ class CleanUnusedComponents implements ProcessorInterface { use Concerns\AnnotationTrait; - protected $enabled = false; + protected bool $enabled; public function __construct(bool $enabled = false) { diff --git a/src/Processors/Concerns/DocblockTrait.php b/src/Processors/Concerns/DocblockTrait.php index 7c00c886..dd0b32cb 100644 --- a/src/Processors/Concerns/DocblockTrait.php +++ b/src/Processors/Concerns/DocblockTrait.php @@ -95,8 +95,8 @@ public function extractContent(?string $docblock, ?array &$tags = null): string $comment = preg_split('/(\n|\r\n)/', (string) $docblock); $comment[0] = preg_replace('/[ \t]*\\/\*\*/', '', $comment[0]); // strip '/**' - $i = count($comment) - 1; - $comment[$i] = preg_replace('/\*\/[ \t]*$/', '', $comment[$i]); // strip '*/' + $ii = count($comment) - 1; + $comment[$ii] = preg_replace('/\*\/[ \t]*$/', '', $comment[$ii]); // strip '*/' $lines = []; $append = false; $skip = false; @@ -110,8 +110,8 @@ public function extractContent(?string $docblock, ?array &$tags = null): string continue; } if ($append) { - $i = count($lines) - 1; - $lines[$i] = substr($lines[$i], 0, -1) . $line; + $ii = count($lines) - 1; + $lines[$ii] = substr($lines[$ii], 0, -1) . $line; } else { $lines[] = $line; } @@ -182,9 +182,7 @@ public function extractVarTypeAndDescription(?string $docblock): array return array_merge( ['type' => null, 'description' => null], - array_filter($matches, function ($key) { - return in_array($key, ['type', 'description']); - }, ARRAY_FILTER_USE_KEY) + array_filter($matches, fn ($key) => in_array($key, ['type', 'description']), ARRAY_FILTER_USE_KEY) ); } diff --git a/src/Processors/ExpandClasses.php b/src/Processors/ExpandClasses.php index 6ede741c..9ba65973 100644 --- a/src/Processors/ExpandClasses.php +++ b/src/Processors/ExpandClasses.php @@ -33,7 +33,7 @@ public function __invoke(Analysis $analysis) foreach ($ancestors as $ancestor) { $ancestorSchema = $analysis->getSchemaForSource($ancestor['context']->fullyQualifiedName($ancestor['class'])); if ($ancestorSchema) { - $refPath = !Generator::isDefault($ancestorSchema->schema) ? $ancestorSchema->schema : $ancestor['class']; + $refPath = Generator::isDefault($ancestorSchema->schema) ? $ancestor['class'] : $ancestorSchema->schema; $this->inheritFrom($analysis, $schema, $ancestorSchema, $refPath, $ancestor['context']); // one ancestor is enough diff --git a/src/Processors/ExpandEnums.php b/src/Processors/ExpandEnums.php index c9199b92..c3ce831e 100644 --- a/src/Processors/ExpandEnums.php +++ b/src/Processors/ExpandEnums.php @@ -38,7 +38,7 @@ protected function expandContextEnum(Analysis $analysis): void foreach ($schemas as $schema) { if ($schema->_context->is('enum')) { $re = new \ReflectionEnum($schema->_context->fullyQualifiedName($schema->_context->enum)); - $schema->schema = !Generator::isDefault($schema->schema) ? $schema->schema : $re->getShortName(); + $schema->schema = Generator::isDefault($schema->schema) ? $re->getShortName() : $schema->schema; $schemaType = $schema->type; $enumType = null; @@ -100,11 +100,7 @@ protected function expandSchemaEnum(Analysis $analysis): void $enums = []; foreach ($cases as $enum) { - if (is_a($enum, \UnitEnum::class)) { - $enums[] = $enum->value ?? $enum->name; - } else { - $enums[] = $enum; - } + $enums[] = is_a($enum, \UnitEnum::class) ? $enum->value ?? $enum->name : $enum; } $schema->enum = $enums; diff --git a/src/Processors/ExpandInterfaces.php b/src/Processors/ExpandInterfaces.php index 8bcc3c25..2d89ce1b 100644 --- a/src/Processors/ExpandInterfaces.php +++ b/src/Processors/ExpandInterfaces.php @@ -43,7 +43,7 @@ public function __invoke(Analysis $analysis) $interfaceName = $interface['context']->fullyQualifiedName($interface['interface']); $interfaceSchema = $analysis->getSchemaForSource($interfaceName); if ($interfaceSchema) { - $refPath = !Generator::isDefault($interfaceSchema->schema) ? $interfaceSchema->schema : $interface['interface']; + $refPath = Generator::isDefault($interfaceSchema->schema) ? $interface['interface'] : $interfaceSchema->schema; $this->inheritFrom($analysis, $schema, $interfaceSchema, $refPath, $interface['context']); } else { $this->mergeMethods($schema, $interface, $existing); diff --git a/src/Processors/ExpandTraits.php b/src/Processors/ExpandTraits.php index cd1b4aca..5cd7e2a4 100644 --- a/src/Processors/ExpandTraits.php +++ b/src/Processors/ExpandTraits.php @@ -32,7 +32,7 @@ public function __invoke(Analysis $analysis) foreach ($traits as $trait) { $traitSchema = $analysis->getSchemaForSource($trait['context']->fullyQualifiedName($trait['trait'])); if ($traitSchema) { - $refPath = !Generator::isDefault($traitSchema->schema) ? $traitSchema->schema : $trait['trait']; + $refPath = Generator::isDefault($traitSchema->schema) ? $trait['trait'] : $traitSchema->schema; $this->inheritFrom($analysis, $schema, $traitSchema, $refPath, $trait['context']); } else { $this->mergeMethods($schema, $trait, $existing); @@ -50,7 +50,7 @@ public function __invoke(Analysis $analysis) foreach ($traits as $trait) { $traitSchema = $analysis->getSchemaForSource($trait['context']->fullyQualifiedName($trait['trait'])); if ($traitSchema) { - $refPath = !Generator::isDefault($traitSchema->schema) ? $traitSchema->schema : $trait['trait']; + $refPath = Generator::isDefault($traitSchema->schema) ? $trait['trait'] : $traitSchema->schema; $this->inheritFrom($analysis, $schema, $traitSchema, $refPath, $trait['context']); } else { $this->mergeMethods($schema, $trait, $existing); diff --git a/src/Processors/OperationId.php b/src/Processors/OperationId.php index b6aff2ca..84d7ac60 100644 --- a/src/Processors/OperationId.php +++ b/src/Processors/OperationId.php @@ -15,7 +15,7 @@ */ class OperationId implements ProcessorInterface { - protected $hash = true; + protected bool $hash; public function __construct(bool $hash = true) { @@ -57,11 +57,7 @@ public function __invoke(Analysis $analysis) $operationId = null; if ($source) { $method = $context->method ? ('::' . $context->method) : ''; - if ($context->namespace) { - $operationId = $context->namespace . '\\' . $source . $method; - } else { - $operationId = $source . $method; - } + $operationId = $context->namespace ? $context->namespace . '\\' . $source . $method : $source . $method; } elseif ($context->method) { $operationId = $context->method; } diff --git a/src/Processors/PathFilter.php b/src/Processors/PathFilter.php index b393d468..079a098d 100644 --- a/src/Processors/PathFilter.php +++ b/src/Processors/PathFilter.php @@ -20,9 +20,9 @@ class PathFilter implements ProcessorInterface { use AnnotationTrait; - protected $tags = []; + protected array $tags; - protected $paths = []; + protected array $paths; public function __construct(array $tags = [], array $paths = []) { diff --git a/src/Serializer.php b/src/Serializer.php index ca02e1c4..80799ac1 100644 --- a/src/Serializer.php +++ b/src/Serializer.php @@ -90,7 +90,7 @@ public function deserializeFile(string $filename, string $format = 'json', strin $contents = file_get_contents($filename); $ext = pathinfo($filename, PATHINFO_EXTENSION); - if ('yaml' == $format || in_array($ext, ['yml', 'yaml'])) { + if ('yaml' === $format || in_array($ext, ['yml', 'yaml'])) { $contents = json_encode(Yaml::parse($contents)); } diff --git a/src/Util.php b/src/Util.php index be329af7..edb32bf9 100644 --- a/src/Util.php +++ b/src/Util.php @@ -34,13 +34,13 @@ public static function getRelativePath(string $fullPath, $basePaths): string } else { // an array of paths foreach ($basePaths as $basePath) { $relativePath = self::removePrefix($fullPath, $basePath); - if (!empty($relativePath)) { + if ($relativePath !== null && $relativePath !== '' && $relativePath !== '0') { break; } } } - return !empty($relativePath) ? trim($relativePath, '/') : $fullPath; + return $relativePath === null || $relativePath === '' || $relativePath === '0' ? $fullPath : trim($relativePath, '/'); } /** @@ -48,7 +48,7 @@ public static function getRelativePath(string $fullPath, $basePaths): string */ private static function removePrefix(string $str, string $prefix): ?string { - if (substr($str, 0, strlen($prefix)) == $prefix) { + if (substr($str, 0, strlen($prefix)) === $prefix) { return substr($str, strlen($prefix)); }