diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a3cd8f..5ac6294 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Yii Framework 2 apidoc extension Change Log - Bug #313: Fix deprecation error `Method deprecated, use ::getParameters()` (mspirkov) - Bug #317: Fix `trim` deprecation errors `Passing null to parameter #1 ($string) of type string is deprecated` (mspirkov) - Bug #318: Fix deprecation errors `mb_convert_encoding(): Handling HTML entities via mbstring is deprecated` (mspirkov) +- Enh #319: Determining types by type hints for properties, methods and params (mspirkov) 3.0.7 February 13, 2025 diff --git a/models/BaseDoc.php b/models/BaseDoc.php index 91c838e..216b9fb 100644 --- a/models/BaseDoc.php +++ b/models/BaseDoc.php @@ -25,6 +25,8 @@ */ class BaseDoc extends BaseObject { + private const INHERITDOC_TAG_NAME = 'inheritdoc'; + /** * @var \phpDocumentor\Reflection\Types\Context */ @@ -210,11 +212,16 @@ public function __construct($reflector = null, $context = null, $config = []) if (in_array($this->shortDescription, ['{@inheritdoc}', '{@inheritDoc}', '@inheritdoc', '@inheritDoc'], true)) { // Mock up parsing of '{@inheritdoc}' (in brackets) tag, which is not yet supported at "phpdocumentor/reflection-docblock" 2.x // todo consider removal in case of "phpdocumentor/reflection-docblock" upgrade - $this->tags[] = new Generic('inheritdoc'); + $this->tags[] = new Generic(self::INHERITDOC_TAG_NAME); $this->shortDescription = ''; } } + protected function isInheritdocTag(Tag $tag): bool + { + return $tag instanceof Generic && $tag->getName() === self::INHERITDOC_TAG_NAME; + } + /** * Converts inline links to unified format. * @see ApiMarkdownTrait::parseApiLinks() diff --git a/models/FunctionDoc.php b/models/FunctionDoc.php index 70765f5..4cba57d 100644 --- a/models/FunctionDoc.php +++ b/models/FunctionDoc.php @@ -7,6 +7,7 @@ namespace yii\apidoc\models; +use phpDocumentor\Reflection\DocBlock\Tags\Generic; use phpDocumentor\Reflection\DocBlock\Tags\Param; use phpDocumentor\Reflection\DocBlock\Tags\Return_; use phpDocumentor\Reflection\DocBlock\Tags\Throws; @@ -27,7 +28,13 @@ class FunctionDoc extends BaseDoc public $params = []; public $exceptions = []; public $return; + /** + * @var string|null + */ public $returnType; + /** + * @var string[]|null + */ public $returnTypes; public $isReturnByReference; @@ -52,6 +59,8 @@ public function __construct($reflector = null, $context = null, $config = []) $this->params[$arg->name] = $arg; } + $hasInheritdoc = false; + foreach ($this->tags as $i => $tag) { if ($tag instanceof Throws) { $this->exceptions[implode($this->splitTypes($tag->getType()))] = $tag->getDescription(); @@ -75,7 +84,14 @@ public function __construct($reflector = null, $context = null, $config = []) $this->returnTypes = $this->splitTypes($tag->getType()); $this->return = StringHelper::mb_ucfirst($tag->getDescription()); unset($this->tags[$i]); + } elseif ($this->isInheritdocTag($tag)) { + $hasInheritdoc = true; } } + + if (!$hasInheritdoc && $this->returnType === null) { + $this->returnType = (string) $reflector->getReturnType(); + $this->returnTypes = [$this->returnType]; + } } } diff --git a/models/ParamDoc.php b/models/ParamDoc.php index 7316d13..a101029 100644 --- a/models/ParamDoc.php +++ b/models/ParamDoc.php @@ -25,7 +25,13 @@ class ParamDoc extends BaseObject public $isPassedByReference; // will be set by creating class public $description; + /** + * @var string|null + */ public $type; + /** + * @var string[]|null + */ public $types; public $sourceFile; @@ -42,6 +48,8 @@ public function __construct($reflector = null, $context = null, $config = []) if ($reflector !== null) { $this->name = $reflector->getName(); $this->typeHint = (string) $reflector->getType(); + $this->type = $this->typeHint; + $this->types = [$this->type]; $this->defaultValue = $reflector->getDefault(); $this->isOptional = $this->defaultValue !== null; $this->isPassedByReference = $reflector->isByReference(); diff --git a/models/PropertyDoc.php b/models/PropertyDoc.php index ccf629b..c082875 100644 --- a/models/PropertyDoc.php +++ b/models/PropertyDoc.php @@ -70,17 +70,17 @@ public function __construct($reflector = null, $context = null, $config = []) $hasInheritdoc = false; foreach ($this->tags as $tag) { - if ($tag->getName() === 'inheritdoc') { - $hasInheritdoc = true; - } if ($tag instanceof Var_) { $this->type = (string) $tag->getType(); $this->types = $this->splitTypes($tag->getType()); $this->description = StringHelper::mb_ucfirst($tag->getDescription()); $this->shortDescription = BaseDoc::extractFirstSentence($this->description); + } elseif ($this->isInheritdocTag($tag)) { + $hasInheritdoc = true; } } + if (empty($this->shortDescription) && $context !== null && !$hasInheritdoc) { $context->warnings[] = [ 'line' => $this->startLine, @@ -88,5 +88,10 @@ public function __construct($reflector = null, $context = null, $config = []) 'message' => "No short description for element '{$this->name}'", ]; } + + if (!$hasInheritdoc && $this->type === null) { + $this->type = (string) $reflector->getType(); + $this->types = [$this->type]; + } } } diff --git a/templates/html/ApiRenderer.php b/templates/html/ApiRenderer.php index abe93fd..00513fb 100644 --- a/templates/html/ApiRenderer.php +++ b/templates/html/ApiRenderer.php @@ -292,7 +292,7 @@ public function renderMethodSignature($method, $context = null) return '' . implode(' ', $definition) . ' ' . '' . ($method->isReturnByReference ? '&' : '') - . ($method->returnType === null ? 'void' : $this->createTypeLink($method->returnTypes, $context)) . ' ' + . $this->createTypeLink($method->returnTypes, $context) . ' ' . '' . $this->createSubjectLink($method, $method->name) . '' . str_replace(' ', ' ', ' ( ' . implode(', ', $params) . ' )'); } diff --git a/tests/commands/__snapshots__/ApiControllerTest__testGenerateBootstrap__1.html b/tests/commands/__snapshots__/ApiControllerTest__testGenerateBootstrap__1.html index 6e963d9..febfd20 100644 --- a/tests/commands/__snapshots__/ApiControllerTest__testGenerateBootstrap__1.html +++ b/tests/commands/__snapshots__/ApiControllerTest__testGenerateBootstrap__1.html @@ -120,6 +120,18 @@

Public Properties

string Animal name. yiiunit\apidoc\data\api\animal\Animal + + + $propertyWithoutDoc + string + + yiiunit\apidoc\data\api\animal\Animal + + + $propertyWithoutDocAndTypeHint + + + yiiunit\apidoc\data\api\animal\Animal @@ -162,6 +174,11 @@

Public Methods

render() Renders animal description. yiiunit\apidoc\data\api\animal\Animal + + + setBirthDate() + + yiiunit\apidoc\data\api\animal\Animal @@ -244,6 +261,50 @@

Property Details

+ +
+
+ + + + $propertyWithoutDoc + + public property + +
+ + +
+ +
+ +
+public string $propertyWithoutDoc '' +
+ + +
+
+
+ + + + $propertyWithoutDocAndTypeHint + + public property + +
+ + +
+ +
+ +
+public $propertyWithoutDocAndTypeHint '' +
+ +
@@ -452,6 +513,60 @@

Method Details

+ +
+
+ + + + setBirthDate() + + + public method + +
+ + +
+ +

+
+ + + + + + + + + + + +
+public self setBirthDate ( integer $birthDate )
$birthDateinteger +
+ + + + +

+ +

+
+
+
+                public function setBirthDate(int $birthDate): self
+{
+    $this->birthDate = $birthDate;
+    return $this;
+}
+
+            
+
+
+
diff --git a/tests/commands/__snapshots__/ApiControllerTest__testGenerateBootstrap__2.html b/tests/commands/__snapshots__/ApiControllerTest__testGenerateBootstrap__2.html index 47dcfbb..abd75e2 100644 --- a/tests/commands/__snapshots__/ApiControllerTest__testGenerateBootstrap__2.html +++ b/tests/commands/__snapshots__/ApiControllerTest__testGenerateBootstrap__2.html @@ -115,6 +115,18 @@

Public Properties

string Animal name. yiiunit\apidoc\data\api\animal\Animal + + + $propertyWithoutDoc + string + + yiiunit\apidoc\data\api\animal\Animal + + + $propertyWithoutDocAndTypeHint + + + yiiunit\apidoc\data\api\animal\Animal @@ -152,11 +164,21 @@

Public Methods

isOlder() Checks whether the animal is older than the specified time. yiiunit\apidoc\data\api\animal\Animal + + + methodWithoutDocAndTypeHints() + + yiiunit\apidoc\data\api\animal\Cat render() Renders animal description. yiiunit\apidoc\data\api\animal\Cat + + + setBirthDate() + + yiiunit\apidoc\data\api\animal\Animal @@ -324,6 +346,51 @@

Method Details

{ return $this->getAge() > $date; } + + + + + + +
+
+ + + + methodWithoutDocAndTypeHints() + + + public method + +
+ + +
+ +

+
+ + + + +
+public mixed methodWithoutDocAndTypeHints ( )
+ + + + +

+ +

+
+
+
+                public function methodWithoutDocAndTypeHints()
+{
+    return '';
+}
 
             
@@ -379,6 +446,63 @@

Method Details

// this method has `inheritdoc` tag in brackets return 'This is a cat'; } + + +
+
+ + +
+
+ + + + setBirthDate() + + + public method + +
+ + +
+

+ Defined in: + yiiunit\apidoc\data\api\animal\Animal::setBirthDate()

+ +

+
+ + + + + + + + + + + +
+public self setBirthDate ( integer $birthDate )
$birthDateinteger +
+ + + + +

+ +

+
+
+
+                public function setBirthDate(int $birthDate): self
+{
+    $this->birthDate = $birthDate;
+    return $this;
+}
 
             
diff --git a/tests/commands/__snapshots__/ApiControllerTest__testGenerateBootstrap__3.html b/tests/commands/__snapshots__/ApiControllerTest__testGenerateBootstrap__3.html index 76141f0..d3fa87b 100644 --- a/tests/commands/__snapshots__/ApiControllerTest__testGenerateBootstrap__3.html +++ b/tests/commands/__snapshots__/ApiControllerTest__testGenerateBootstrap__3.html @@ -115,6 +115,18 @@

Public Properties

string Animal name. yiiunit\apidoc\data\api\animal\Animal + + + $propertyWithoutDoc + string + + yiiunit\apidoc\data\api\animal\Animal + + + $propertyWithoutDocAndTypeHint + + + yiiunit\apidoc\data\api\animal\Animal
@@ -157,6 +169,11 @@

Public Methods

render() Renders animal description. yiiunit\apidoc\data\api\animal\Dog + + + setBirthDate() + + yiiunit\apidoc\data\api\animal\Animal
@@ -379,6 +396,63 @@

Method Details

// this method has `inheritdoc` tag without brackets return 'This is a dog'; } + + + + + + +
+
+ + + + setBirthDate() + + + public method + +
+ + +
+

+ Defined in: + yiiunit\apidoc\data\api\animal\Animal::setBirthDate()

+ +

+
+ + + + + + + + + + + +
+public self setBirthDate ( integer $birthDate )
$birthDateinteger +
+ + + + +

+ +

+
+
+
+                public function setBirthDate(int $birthDate): self
+{
+    $this->birthDate = $birthDate;
+    return $this;
+}
 
             
diff --git a/tests/data/api/animal/Animal.php b/tests/data/api/animal/Animal.php index fef0d09..63e2238 100644 --- a/tests/data/api/animal/Animal.php +++ b/tests/data/api/animal/Animal.php @@ -30,6 +30,9 @@ abstract class Animal extends BaseObject */ public $birthDate; + public string $propertyWithoutDoc = ''; + + public $propertyWithoutDocAndTypeHint = ''; /** * Renders animal description. @@ -55,4 +58,10 @@ public function isOlder($date) { return $this->getAge() > $date; } + + public function setBirthDate(int $birthDate): self + { + $this->birthDate = $birthDate; + return $this; + } } diff --git a/tests/data/api/animal/Cat.php b/tests/data/api/animal/Cat.php index c566a6d..e31acb5 100644 --- a/tests/data/api/animal/Cat.php +++ b/tests/data/api/animal/Cat.php @@ -23,4 +23,9 @@ public function render() // this method has `inheritdoc` tag in brackets return 'This is a cat'; } + + public function methodWithoutDocAndTypeHints() + { + return ''; + } }