diff --git a/composer.json b/composer.json index e3fabfc06..1f279817a 100644 --- a/composer.json +++ b/composer.json @@ -67,7 +67,7 @@ "@lint" ], "analyse": [ - "phpstan analyze --level=2 src | grep -v 'does not accept default value of type string'", + "phpstan analyze --level=3 src | grep -v 'does not accept default value of type string'", "psalm" ], "docs": "./docs/node_modules/.bin/vuepress dev docs/", diff --git a/src/Analyser.php b/src/Analyser.php index 8241069c5..7ab99a5b5 100644 --- a/src/Analyser.php +++ b/src/Analyser.php @@ -11,7 +11,7 @@ if (class_exists(AnnotationRegistry::class, true)) { AnnotationRegistry::registerLoader( - function ($class) { + function (string $class): bool { if (Analyser::$whitelist === false) { $whitelist = ['OpenApi\Annotations\\']; } else { @@ -66,7 +66,7 @@ class Analyser */ public $docParser; - public function __construct($docParser = null) + public function __construct(?DocParser $docParser = null) { if ($docParser === null) { $docParser = new DocParser(); @@ -84,7 +84,7 @@ public function __construct($docParser = null) * * @return array Annotations */ - public function fromComment($comment, $context = null) + public function fromComment(string $comment, ?Context $context = null): array { $context = $context ?: new Context(); $context->comment = $comment; diff --git a/src/Analysis.php b/src/Analysis.php index 3c7e9ce3a..4ea22fb92 100644 --- a/src/Analysis.php +++ b/src/Analysis.php @@ -6,8 +6,6 @@ namespace OpenApi; -use Closure; -use Exception; use OpenApi\Annotations\AbstractAnnotation; use OpenApi\Annotations\OpenApi; use OpenApi\Annotations\Schema; @@ -25,17 +23,17 @@ use OpenApi\Processors\MergeJsonContent; use OpenApi\Processors\MergeXmlContent; use OpenApi\Processors\OperationId; -use SplObjectStorage; -use stdClass; /** - * Result of the analyser which pretends to be an array of annotations, but also contains detected classes and helper - * functions for the processors. + * Result of the analyser. + * + * Pretends to be an array of annotations, but also contains detected classes + * and helper functions for the processors. */ class Analysis { /** - * @var SplObjectStorage + * @var \SplObjectStorage */ public $annotations; @@ -75,12 +73,11 @@ class Analysis private static $processors; /** - * @param array $annotations - * @param null $context + * @param null $context */ - public function __construct($annotations = [], $context = null) + public function __construct(array $annotations = [], ?Context $context = null) { - $this->annotations = new SplObjectStorage(); + $this->annotations = new \SplObjectStorage(); if (count($annotations) !== 0) { if ($context === null) { $context = Context::detect(1); @@ -89,7 +86,7 @@ public function __construct($annotations = [], $context = null) } } - public function addAnnotation($annotation, ?Context $context) + public function addAnnotation($annotation, ?Context $context): void { if ($this->annotations->contains($annotation)) { return; @@ -129,48 +126,32 @@ public function addAnnotation($annotation, ?Context $context) } } - /** - * @param array $annotations - * @param Context $context - */ - public function addAnnotations($annotations, $context) + public function addAnnotations(array $annotations, Context $context): void { foreach ($annotations as $annotation) { $this->addAnnotation($annotation, $context); } } - /** - * @param array $definition - */ - public function addClassDefinition($definition) + public function addClassDefinition(array $definition): void { $class = $definition['context']->fullyQualifiedName($definition['class']); $this->classes[$class] = $definition; } - /** - * @param array $definition - */ - public function addInterfaceDefinition($definition) + public function addInterfaceDefinition(array $definition): void { $interface = $definition['context']->fullyQualifiedName($definition['interface']); $this->interfaces[$interface] = $definition; } - /** - * @param array $definition - */ - public function addTraitDefinition($definition) + public function addTraitDefinition(array $definition): void { $trait = $definition['context']->fullyQualifiedName($definition['trait']); $this->traits[$trait] = $definition; } - /** - * @param Analysis $analysis - */ - public function addAnalysis($analysis) + public function addAnalysis(Analysis $analysis): void { foreach ($analysis->annotations as $annotation) { $this->addAnnotation($annotation, $analysis->annotations[$annotation]); @@ -190,7 +171,7 @@ public function addAnalysis($analysis) * * @return array map of class => definition pairs of sub-classes */ - public function getSubClasses($parent) + public function getSubClasses(string $parent): array { $definitions = []; foreach ($this->classes as $class => $classDefinition) { @@ -210,7 +191,7 @@ public function getSubClasses($parent) * * @return array map of class => definition pairs of parent classes */ - public function getSuperClasses($class) + public function getSuperClasses(string $class): array { $classDefinition = isset($this->classes[$class]) ? $this->classes[$class] : null; if (!$classDefinition || empty($classDefinition['extends'])) { @@ -235,7 +216,7 @@ public function getSuperClasses($class) * * @return array map of class => definition pairs of interfaces */ - public function getInterfacesOfClass($class, $direct = false) + public function getInterfacesOfClass(string $class, bool $direct = false): array { $classes = $direct ? [] : array_keys($this->getSuperClasses($class)); // add self @@ -281,7 +262,7 @@ public function getInterfacesOfClass($class, $direct = false) * * @return array map of class => definition pairs of traits */ - public function getTraitsOfClass($source, $direct = false) + public function getTraitsOfClass(string $source, bool $direct = false): array { $sources = $direct ? [] : array_keys($this->getSuperClasses($source)); // add self @@ -320,12 +301,9 @@ public function getTraitsOfClass($source, $direct = false) } /** - * @param string $class - * @param bool $strict innon-strict mode childclasses are also detected - * - * @return array + * @param bool $strict innon-strict mode childclasses are also detected */ - public function getAnnotationsOfType($class, $strict = false) + public function getAnnotationsOfType(string $class, bool $strict = false): array { $annotations = []; if ($strict) { @@ -347,10 +325,8 @@ public function getAnnotationsOfType($class, $strict = false) /** * @param string $fqdn the source class/interface/trait - * - * @return null|Schema */ - public function getSchemaForSource($fqdn) + public function getSchemaForSource(string $fqdn): ?Schema { $sourceDefinitions = [ $this->classes, @@ -379,31 +355,29 @@ public function getSchemaForSource($fqdn) * * @return \OpenApi\Context */ - public function getContext($annotation) + public function getContext($annotation): Context { if ($annotation instanceof AbstractAnnotation) { return $annotation->_context; } if ($this->annotations->contains($annotation) === false) { - throw new Exception('Annotation not found'); + throw new \Exception('Annotation not found'); } $context = $this->annotations[$annotation]; if ($context instanceof Context) { return $context; } // Weird, did you use the addAnnotation/addAnnotations methods? - throw new Exception('Annotation has no context'); + throw new \Exception('Annotation has no context'); } /** * Build an analysis with only the annotations that are merged into the OpenAPI annotation. - * - * @return Analysis */ - public function merged() + public function merged(): Analysis { if ($this->openapi === null) { - throw new Exception('No openapi target set. Run the MergeIntoOpenApi processor'); + throw new \Exception('No openapi target set. Run the MergeIntoOpenApi processor'); } $unmerged = $this->openapi->_unmerged; $this->openapi->_unmerged = []; @@ -415,10 +389,8 @@ public function merged() /** * Analysis with only the annotations that not merged. - * - * @return Analysis */ - public function unmerged() + public function unmerged(): Analysis { return $this->split()->unmerged; } @@ -431,7 +403,7 @@ public function unmerged() */ public function split() { - $result = new stdClass(); + $result = new \stdClass(); $result->merged = $this->merged(); $result->unmerged = new Analysis(); foreach ($this->annotations as $annotation) { @@ -446,9 +418,9 @@ public function split() /** * Apply the processor(s). * - * @param Closure|Closure[] $processors One or more processors + * @param \Closure|\Closure[] $processors One or more processors */ - public function process($processors = null) + public function process($processors = null): void { if ($processors === null) { // Use the default and registered processors. @@ -495,9 +467,9 @@ public static function &processors() /** * Register a processor. * - * @param Closure $processor + * @param \Closure $processor */ - public static function registerProcessor($processor) + public static function registerProcessor($processor): void { array_push(self::processors(), $processor); } @@ -505,19 +477,19 @@ public static function registerProcessor($processor) /** * Unregister a processor. * - * @param Closure $processor + * @param \Closure $processor */ - public static function unregisterProcessor($processor) + public static function unregisterProcessor($processor): void { $processors = &self::processors(); $key = array_search($processor, $processors, true); if ($key === false) { - throw new Exception('Given processor was not registered'); + throw new \Exception('Given processor was not registered'); } unset($processors[$key]); } - public function validate() + public function validate(): bool { if ($this->openapi !== null) { return $this->openapi->validate(); diff --git a/src/Annotations/AbstractAnnotation.php b/src/Annotations/AbstractAnnotation.php index 36c833cc6..db780e059 100644 --- a/src/Annotations/AbstractAnnotation.php +++ b/src/Annotations/AbstractAnnotation.php @@ -6,18 +6,15 @@ namespace OpenApi\Annotations; -use Exception; -use JsonSerializable; use OpenApi\Analyser; use OpenApi\Context; use OpenApi\Logger; -use stdClass; use Symfony\Component\Yaml\Yaml; /** * The openapi annotation base class. */ -abstract class AbstractAnnotation implements JsonSerializable +abstract class AbstractAnnotation implements \JsonSerializable { /** * While the OpenAPI Specification tries to accommodate most use cases, additional data can be added to extend the specification at certain points. @@ -85,10 +82,7 @@ abstract class AbstractAnnotation implements JsonSerializable */ public static $_blacklist = ['_context', '_unmerged']; - /** - * @param array $properties - */ - public function __construct($properties) + public function __construct(array $properties) { if (isset($properties['_context'])) { $this->_context = $properties['_context']; @@ -159,7 +153,7 @@ public function __set($property, $value) * * @return AbstractAnnotation[] The unmerged annotations */ - public function merge($annotations, $ignore = false) + public function merge(array $annotations, bool $ignore = false): array { $unmerged = []; $nestedContext = new Context(['nested' => $this], $this->_context); @@ -200,7 +194,7 @@ public function merge($annotations, $ignore = false) * * @param object $object */ - public function mergeProperties($object) + public function mergeProperties($object): void { $defaultValues = get_class_vars(get_class($this)); $currentValues = get_object_vars($this); @@ -233,10 +227,8 @@ public function mergeProperties($object) /** * Generate the documentation in YAML format. - * - * @return string */ - public function toYaml($flags = null) + public function toYaml($flags = null): string { if ($flags === null) { $flags = Yaml::DUMP_OBJECT_AS_MAP ^ Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE; @@ -247,10 +239,8 @@ public function toYaml($flags = null) /** * Generate the documentation in YAML format. - * - * @return string */ - public function toJson($flags = null) + public function toJson($flags = null): string { if ($flags === null) { $flags = JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE; @@ -276,7 +266,7 @@ public function __debugInfo() */ public function jsonSerialize() { - $data = new stdClass(); + $data = new \stdClass(); // Strip undefined values. foreach (get_object_vars($this) as $property => $value) { @@ -293,7 +283,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)) { - $data->$property = new stdClass; + $data->$property = new \stdClass(); } } @@ -316,14 +306,14 @@ public function jsonSerialize() continue; } $keyField = $nested[1]; - $object = new stdClass(); + $object = new \stdClass(); foreach ($this->$property as $key => $item) { if (is_numeric($key) === false && is_array($item)) { $object->$key = $item; } else { $key = $item->$keyField; if ($key !== UNDEFINED && empty($object->$key)) { - if ($item instanceof JsonSerializable) { + if ($item instanceof \JsonSerializable) { $object->$key = $item->jsonSerialize(); } else { $object->$key = $item; @@ -349,12 +339,8 @@ public function jsonSerialize() * * @param array $parents the path of annotations above this annotation in the tree * @param array $skip (prevent stack overflow, when traversing an infinite dependency graph) - * - * @throws Exception - * - * @return bool */ - public function validate($parents = [], $skip = [], $ref = '') + public function validate(array $parents = [], array $skip = [], string $ref = ''): bool { if (in_array($this, $skip, true)) { return true; @@ -415,8 +401,8 @@ public function validate($parents = [], $skip = [], $ref = '') // Internal reference try { $parents[0]->ref($this->ref); - } catch (Exception $exception) { - Logger::notice($exception->getMessage().' for '.$this->identity().' in '.$this->_context); + } catch (\Exception $e) { + Logger::notice($e->getMessage().' for '.$this->identity().' in '.$this->_context); } } } else { @@ -458,7 +444,7 @@ public function validate($parents = [], $skip = [], $ref = '') Logger::notice($this->identity().'->'.$property.' "'.$value.'" is invalid, expecting "'.implode('", "', $type).'" in '.$this->_context); } } else { - throw new Exception('Invalid '.get_class($this).'::$_types['.$property.']'); + throw new \Exception('Invalid '.get_class($this).'::$_types['.$property.']'); } } $parents[] = $this; @@ -472,10 +458,8 @@ public function validate($parents = [], $skip = [], $ref = '') * @param array|object $fields * @param array $parents the path of annotations above this annotation in the tree * @param array $skip List of objects already validated - * - * @return bool */ - private static function _validate($fields, $parents, $skip, $baseRef) + private static function _validate($fields, array $parents, array $skip, string $baseRef): bool { $valid = true; $blacklist = []; @@ -511,10 +495,8 @@ private static function _validate($fields, $parents, $skip, $baseRef) /** * Return a identity for easy debugging. * Example: "@OA\Get(path="/pets")". - * - * @return string */ - public function identity() + public function identity(): string { $class = get_class($this); $properties = []; @@ -537,7 +519,7 @@ public function identity() * * @return null|object key/value object or `null` */ - public static function matchNested($class) + public static function matchNested(string $class) { if (array_key_exists($class, static::$_nested)) { return (object) ['key' => $class, 'value' => static::$_nested[$class]]; @@ -556,12 +538,8 @@ public static function matchNested($class) /** * Helper for generating the identity(). - * - * @param array $properties - * - * @return string */ - protected function _identity($properties) + protected function _identity(array $properties): string { $fields = []; foreach ($properties as $property) { @@ -579,10 +557,8 @@ protected function _identity($properties) * * @param string $type The annotations property type * @param mixed $value The property value - * - * @throws \Exception */ - private function validateType($type, $value): bool + private function validateType(string $type, $value): bool { if (substr($type, 0, 1) === '[' && substr($type, -1) === ']') { // Array of a specified type? if ($this->validateType('array', $value) === false) { @@ -610,10 +586,8 @@ private function validateType($type, $value): bool * * @param string $type The property type * @param mixed $value The value to validate - * - * @throws \Exception */ - private function validateDefaultTypes($type, $value): bool + private function validateDefaultTypes(string $type, $value): bool { switch ($type) { case 'string': @@ -631,7 +605,7 @@ private function validateDefaultTypes($type, $value): bool case 'scheme': return in_array($value, ['http', 'https', 'ws', 'wss'], true); default: - throw new Exception('Invalid type "'.$type.'"'); + throw new \Exception('Invalid type "'.$type.'"'); } } @@ -659,11 +633,10 @@ private function validateArrayType($value): bool * Wrap the context with a reference to the annotation it is nested in. * * @param AbstractAnnotation $annotation - * @param Context $nestedContext * * @return AbstractAnnotation */ - private function nested($annotation, $nestedContext) + private function nested($annotation, Context $nestedContext) { if (property_exists($annotation, '_context') && $annotation->_context === $this->_context) { $annotation->_context = $nestedContext; diff --git a/src/Annotations/Flow.php b/src/Annotations/Flow.php index 17a70ec8d..9e12ef907 100644 --- a/src/Annotations/Flow.php +++ b/src/Annotations/Flow.php @@ -47,8 +47,6 @@ class Flow extends AbstractAnnotation /** * The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. - * - * @var array */ public $scopes = UNDEFINED; diff --git a/src/Annotations/Items.php b/src/Annotations/Items.php index ad98c6145..942acba19 100644 --- a/src/Annotations/Items.php +++ b/src/Annotations/Items.php @@ -41,7 +41,7 @@ class Items extends Schema /** * {@inheritdoc} */ - public function validate($parents = [], $skip = [], $ref = '') + public function validate(array $parents = [], array $skip = [], string $ref = ''): bool { if (in_array($this, $skip, true)) { return true; diff --git a/src/Annotations/OpenApi.php b/src/Annotations/OpenApi.php index b68cdea53..d598fa741 100644 --- a/src/Annotations/OpenApi.php +++ b/src/Annotations/OpenApi.php @@ -6,7 +6,6 @@ namespace OpenApi\Annotations; -use Exception; use OpenApi\Analysis; use OpenApi\Logger; use OpenApi\Util; @@ -126,9 +125,9 @@ class OpenApi extends AbstractAnnotation /** * {@inheritdoc} */ - public function validate($parents = null, $skip = null, $ref = null) + public function validate(array $parents = null, array $skip = null, string $ref = ''): bool { - if ($parents !== null || $skip !== null || $ref !== null) { + if ($parents !== null || $skip !== null || $ref !== '') { Logger::notice('Nested validation for '.$this->identity().' not allowed'); return false; @@ -139,12 +138,8 @@ public function validate($parents = null, $skip = null, $ref = null) /** * Save the OpenAPI documentation to a file. - * - * @param string $filename - * - * @throws Exception */ - public function saveAs($filename, $format = 'auto') + public function saveAs(string $filename, string $format = 'auto'): void { if ($format === 'auto') { $format = strtolower(substr($filename, -5)) === '.json' ? 'json' : 'yaml'; @@ -155,7 +150,7 @@ public function saveAs($filename, $format = 'auto') $content = $this->toYaml(); } if (file_put_contents($filename, $content) === false) { - throw new Exception('Failed to saveAs("'.$filename.'", "'.$format.'")'); + throw new \Exception('Failed to saveAs("'.$filename.'", "'.$format.'")'); } } @@ -163,14 +158,12 @@ public function saveAs($filename, $format = 'auto') * Look up an annotation with a $ref url. * * @param string $ref The $ref value, for example: "#/components/schemas/Product" - * - * @throws Exception */ - public function ref($ref) + public function ref(string $ref) { if (substr($ref, 0, 2) !== '#/') { // @todo Add support for external (http) refs? - throw new Exception('Unsupported $ref "'.$ref.'", it should start with "#/"'); + throw new \Exception('Unsupported $ref "'.$ref.'", it should start with "#/"'); } return $this->resolveRef($ref, '#/', $this, []); @@ -179,7 +172,7 @@ public function ref($ref) /** * Recursive helper for ref(). */ - private static function resolveRef($ref, $resolved, $container, $mapping) + private static function resolveRef(string $ref, string $resolved, $container, array $mapping) { if ($ref === $resolved) { return $container; @@ -193,7 +186,7 @@ private static function resolveRef($ref, $resolved, $container, $mapping) if (is_object($container)) { if (property_exists($container, $property) === false) { - throw new Exception('$ref "'.$ref.'" not found'); + throw new \Exception('$ref "'.$ref.'" not found'); } if ($slash === false) { return $container->$property; @@ -220,6 +213,6 @@ private static function resolveRef($ref, $resolved, $container, $mapping) } } } - throw new Exception('$ref "'.$unresolved.'" not found'); + throw new \Exception('$ref "'.$unresolved.'" not found'); } } diff --git a/src/Annotations/Operation.php b/src/Annotations/Operation.php index 06051b808..90c38793d 100644 --- a/src/Annotations/Operation.php +++ b/src/Annotations/Operation.php @@ -184,7 +184,7 @@ public function jsonSerialize() return $data; } - public function validate($parents = [], $skip = [], $ref = '') + public function validate(array $parents = [], array $skip = [], string $ref = ''): bool { if (in_array($this, $skip, true)) { return true; diff --git a/src/Annotations/Parameter.php b/src/Annotations/Parameter.php index b655db00a..79cf19305 100644 --- a/src/Annotations/Parameter.php +++ b/src/Annotations/Parameter.php @@ -234,7 +234,7 @@ class Parameter extends AbstractAnnotation /** * {@inheritdoc} */ - public function validate($parents = [], $skip = [], $ref = '') + public function validate(array $parents = [], array $skip = [], string $ref = ''): bool { if (in_array($this, $skip, true)) { return true; @@ -246,21 +246,6 @@ public function validate($parents = [], $skip = [], $ref = '') Logger::notice('Field "schema" is required when '.$this->identity().' is in "'.$this->in.'" in '.$this->_context); $valid = false; } - } else { - // $validTypes = ['string', 'number', 'integer', 'boolean', 'array', 'file']; - // if ($this->type === null) { - // Logger::notice($this->identity() . '->type is required when ' . $this->_identity([]) . '->in == "' . $this->in . '" in ' . $this->_context); - // $valid = false; - // } elseif ($this->type === 'array' && $this->items === null) { - // Logger::notice($this->identity() . '->items required when ' . $this->_identity([]) . '->type == "array" in ' . $this->_context); - // $valid = false; - // } elseif (in_array($this->type, $validTypes) === false) { - // $valid = false; - // Logger::notice($this->identity() . '->type must be "' . implode('", "', $validTypes) . '" when ' . $this->_identity([]) . '->in != "body" in ' . $this->_context); - // } elseif ($this->type === 'file' && $this->in !== 'formData') { - // Logger::notice($this->identity() . '->in must be "formData" when ' . $this->_identity([]) . '->type == "file" in ' . $this->_context); - // $valid = false; - // } } } @@ -270,7 +255,7 @@ public function validate($parents = [], $skip = [], $ref = '') /** * {@inheritdoc} */ - public function identity() + public function identity(): string { return parent::_identity(['name', 'in']); } diff --git a/src/Annotations/Schema.php b/src/Annotations/Schema.php index e7441d1c7..ecfdb851e 100644 --- a/src/Annotations/Schema.php +++ b/src/Annotations/Schema.php @@ -369,7 +369,7 @@ class Schema extends AbstractAnnotation Header::class, ]; - public function validate($parents = [], $skip = [], $ref = '') + public function validate(array $parents = [], array $skip = [], string $ref = ''): bool { if ($this->type === 'array' && $this->items === UNDEFINED) { Logger::notice('@OA\Items() is required when '.$this->identity().' has type "array" in '.$this->_context); diff --git a/src/Annotations/SecurityScheme.php b/src/Annotations/SecurityScheme.php index 66b482205..de822f025 100644 --- a/src/Annotations/SecurityScheme.php +++ b/src/Annotations/SecurityScheme.php @@ -119,7 +119,7 @@ class SecurityScheme extends AbstractAnnotation /** * {@inheritdoc} */ - public function merge($annotations, $ignore = false) + public function merge(array $annotations, bool $ignore = false): array { $unmerged = parent::merge($annotations, $ignore); diff --git a/src/Context.php b/src/Context.php index 4b579a904..8697108ad 100644 --- a/src/Context.php +++ b/src/Context.php @@ -52,7 +52,7 @@ class Context * @param array $properties new properties for this context * @param Context $parent The parent context */ - public function __construct($properties = [], $parent = null) + public function __construct(array $properties = [], ?Context $parent = null) { foreach ($properties as $property => $value) { $this->$property = $value; @@ -64,10 +64,8 @@ public function __construct($properties = [], $parent = null) * Check if a property is set directly on this context and not its parent context. * * @param string $type Example: $c->is('method') or $c->is('class') - * - * @return bool */ - public function is($type) + public function is(string $type): bool { return property_exists($this, $type); } @@ -76,22 +74,16 @@ public function is($type) * Check if a property is NOT set directly on this context and but its parent context. * * @param string $type Example: $c->not('method') or $c->not('class') - * - * @return bool */ - public function not($type) + public function not(string $type): bool { return property_exists($this, $type) === false; } /** * Return the context containing the specified property. - * - * @param string $property - * - * @return bool|Context */ - public function with($property) + public function with(string $property): ?Context { if (property_exists($this, $property)) { return $this; @@ -100,13 +92,10 @@ public function with($property) return $this->_parent->with($property); } - return false; + return null; } - /** - * @return Context - */ - public function getRootContext() + public function getRootContext(): Context { if ($this->_parent !== null) { return $this->_parent->getRootContext(); @@ -120,7 +109,7 @@ public function getRootContext() * * @return string Example: "file1.php on line 12" */ - public function getDebugLocation() + public function getDebugLocation(): string { $location = ''; if ($this->class && ($this->method || $this->property)) { @@ -256,12 +245,8 @@ public function phpdocContent() /** * Create a Context based on the debug_backtrace. - * - * @param int $index - * - * @return Context */ - public static function detect($index = 0) + public static function detect(int $index = 0): Context { $context = new Context(); $backtrace = debug_backtrace(); diff --git a/src/Logger.php b/src/Logger.php index 6000e178f..536f59e97 100644 --- a/src/Logger.php +++ b/src/Logger.php @@ -39,10 +39,7 @@ protected function __construct() }; } - /** - * @return Logger - */ - public static function getInstance() + public static function getInstance(): Logger { if (self::$instance === null) { self::$instance = new Logger(); @@ -56,7 +53,7 @@ public static function getInstance() * * @param Exception|string $entry */ - public static function warning($entry) + public static function warning($entry): void { call_user_func(self::getInstance()->log, $entry, E_USER_WARNING); } @@ -66,7 +63,7 @@ public static function warning($entry) * * @param Exception|string $entry */ - public static function notice($entry) + public static function notice($entry): void { call_user_func(self::getInstance()->log, $entry, E_USER_NOTICE); } diff --git a/src/Processors/DocBlockDescriptions.php b/src/Processors/DocBlockDescriptions.php index fa941baea..7f7dff804 100644 --- a/src/Processors/DocBlockDescriptions.php +++ b/src/Processors/DocBlockDescriptions.php @@ -47,7 +47,7 @@ public function __invoke(Analysis $analysis) } } - private function description($annotation) + private function description($annotation): void { if ($annotation->description !== UNDEFINED) { if ($annotation->description === null) { @@ -59,7 +59,7 @@ private function description($annotation) $annotation->description = $annotation->_context->phpdocContent(); } - private function summaryAndDescription($annotation) + private function summaryAndDescription($annotation): void { $ignoreSummary = $annotation->summary !== UNDEFINED; $ignoreDescription = $annotation->description !== UNDEFINED; diff --git a/src/Processors/InheritProperties.php b/src/Processors/InheritProperties.php index 2a5b94082..a84b8708c 100644 --- a/src/Processors/InheritProperties.php +++ b/src/Processors/InheritProperties.php @@ -74,7 +74,7 @@ public function __invoke(Analysis $analysis) /** * Add schema to child schema allOf property. */ - private function inherit(Schema $to, Schema $from) + private function inherit(Schema $to, Schema $from): void { if ($to->allOf === UNDEFINED) { // Move all properties into an `allOf` entry except the `schema` property. diff --git a/src/Serializer.php b/src/Serializer.php index 2a9e7212b..a436c56fe 100644 --- a/src/Serializer.php +++ b/src/Serializer.php @@ -73,8 +73,6 @@ public function serialize(OA\AbstractAnnotation $annotation) /** * Deserialize a string. * - * @throws \Exception - * * @return OA\AbstractAnnotation */ public function deserialize(string $jsonString, string $className) @@ -89,8 +87,6 @@ public function deserialize(string $jsonString, string $className) /** * Deserialize a file. * - * @throws \Exception - * * @return OA\AbstractAnnotation */ public function deserializeFile(string $filename, string $className = 'OpenApi\Annotations\OpenApi') @@ -105,14 +101,12 @@ public function deserializeFile(string $filename, string $className = 'OpenApi\A /** * Do deserialization. * - * @param string $class the class name of annotation - * * @return OA\AbstractAnnotation */ - protected function doDeserialize(\stdClass $c, $class) + protected function doDeserialize(\stdClass $c, string $class) { $annotation = new $class([]); - foreach ($c as $property => $value) { + foreach ((array) $c as $property => $value) { if ($property === '$ref') { $property = 'ref'; } @@ -133,10 +127,8 @@ protected function doDeserialize(\stdClass $c, $class) /** * Deserialize the annotation's property. - * - * @param string $property */ - protected function doDeserializeProperty(OA\AbstractAnnotation $annotation, $property, $value) + protected function doDeserializeProperty(OA\AbstractAnnotation $annotation, string $property, $value) { // property is primitive type if (array_key_exists($property, $annotation::$_types)) { @@ -185,8 +177,8 @@ protected function doDeserializeProperty(OA\AbstractAnnotation $annotation, $pro /** * Deserialize base annotation property. * - * @param string $type The property type - * @param mixed $value The value to deserialization + * @param array|string $type The property type + * @param mixed $value The value to deserialization * * @return array|OA\AbstractAnnotation */ diff --git a/src/StaticAnalyser.php b/src/StaticAnalyser.php index 9a257c2f9..6d11bc650 100644 --- a/src/StaticAnalyser.php +++ b/src/StaticAnalyser.php @@ -11,24 +11,12 @@ */ class StaticAnalyser { - /** - * @param string $filename - */ - public function __construct($filename = null) - { - if ($filename !== null) { - $this->fromFile($filename); - } - } - /** * Extract and process all doc-comments from a file. * * @param string $filename path to a php file - * - * @return Analysis */ - public function fromFile($filename) + public function fromFile(string $filename): Analysis { if (function_exists('opcache_get_status') && function_exists('opcache_get_configuration')) { if (empty($GLOBALS['openapi_opcache_warning'])) { @@ -50,10 +38,8 @@ public function fromFile($filename) * * @param string $code PHP code. (including addAnnotations($analyser->fromComment($comment, $context), $context); } @@ -416,12 +394,10 @@ private function analyseComment($analysis, $analyser, $comment, $context) /** * The next non-whitespace, non-comment token. * - * @param array $tokens - * @param Context $context * * @return array|string The next token (or false) */ - private function nextToken(&$tokens, $context) + private function nextToken(array &$tokens, Context $context) { while (true) { $token = next($tokens); @@ -447,7 +423,7 @@ private function nextToken(&$tokens, $context) /** * Parse namespaced string. */ - private function parseNamespace(&$tokens, &$token, $parseContext) + private function parseNamespace(array &$tokens, &$token, Context $parseContext): string { $namespace = ''; while ($token !== false) { @@ -464,7 +440,7 @@ private function parseNamespace(&$tokens, &$token, $parseContext) /** * Parse comma separated list of namespaced strings. */ - private function parseNamespaceList(&$tokens, &$token, $parseContext) + private function parseNamespaceList(array &$tokens, &$token, Context $parseContext): array { $namespaces = []; while ($namespace = $this->parseNamespace($tokens, $token, $parseContext)) { @@ -480,7 +456,7 @@ private function parseNamespaceList(&$tokens, &$token, $parseContext) /** * Parse a use statement. */ - private function parseUseStatement(&$tokens, &$token, $parseContext) + private function parseUseStatement(array &$tokens, &$token, Context $parseContext): array { $normalizeAlias = function ($alias) { $alias = ltrim($alias, '\\'); diff --git a/src/Util.php b/src/Util.php index 88e4569b6..843e725e1 100644 --- a/src/Util.php +++ b/src/Util.php @@ -25,12 +25,9 @@ class Util * and conform specifically to what is expected by functions like `exclude()` and `notPath()`. * In particular, leading and trailing slashes are removed. * - * @param string $fullPath * @param array|string $basePaths - * - * @return string */ - public static function getRelativePath($fullPath, $basePaths) + public static function getRelativePath(string $fullPath, $basePaths): string { $relativePath = null; if (is_string($basePaths)) { // just a single path, not an array of possible paths @@ -49,13 +46,8 @@ public static function getRelativePath($fullPath, $basePaths) /** * Removes a prefix from the start of a string if it exists, or null otherwise. - * - * @param string $str - * @param string $prefix - * - * @return null|string */ - private static function removePrefix($str, $prefix) + private static function removePrefix(string $str, string $prefix): ?string { if (substr($str, 0, strlen($prefix)) == $prefix) { return substr($str, strlen($prefix)); @@ -73,7 +65,7 @@ private static function removePrefix($str, $prefix) * * @throws InvalidArgumentException */ - public static function finder($directory, $exclude = null, $pattern = null) + public static function finder($directory, $exclude = null, $pattern = null): Finder { if ($directory instanceof Finder) { return $directory; @@ -124,7 +116,7 @@ public static function finder($directory, $exclude = null, $pattern = null) * https://swagger.io/docs/specification/using-ref/ * https://tools.ietf.org/html/rfc6901#page-3 */ - public static function refEncode($raw) + public static function refEncode(string $raw): string { return str_replace('/', '~1', str_replace('~', '~0', $raw)); } @@ -135,7 +127,7 @@ public static function refEncode($raw) * https://swagger.io/docs/specification/using-ref/ * https://tools.ietf.org/html/rfc6901#page-3 */ - public static function refDecode($encoded) + public static function refDecode(string $encoded): string { return str_replace('~1', '/', str_replace('~0', '~', $encoded)); } diff --git a/tests/ContextTest.php b/tests/ContextTest.php index 1f7085546..50bc99f59 100644 --- a/tests/ContextTest.php +++ b/tests/ContextTest.php @@ -20,7 +20,6 @@ public function testDetect() $this->assertSame(__FILE__, $context->filename); $this->assertSame($line, $context->line); $this->assertSame('OpenApi\Tests', $context->namespace); - // $this->assertCount(1, $context->uses); // Context::detect() doesn't pick up USE statements (yet) } public function testFullyQualifiedName()