Fix #20508: Fix PHPDoc, add PHPStan/Psalm annotations for yii\web\CookieCollection::getIterator. Add missing @property annotation in yii\base\Model

This commit is contained in:
Maksim Spirkov
2025-09-02 10:10:56 +05:00
committed by GitHub
parent 9b417e5f6d
commit 06858c1089
7 changed files with 42 additions and 14 deletions

View File

@ -12,6 +12,7 @@ use yii\console\Controller;
use yii\helpers\Console; use yii\helpers\Console;
use yii\helpers\FileHelper; use yii\helpers\FileHelper;
use yii\helpers\Json; use yii\helpers\Json;
use yii\web\Controller as WebController;
/** /**
* PhpDocController is there to help to maintain PHPDoc annotation in class files. * PhpDocController is there to help to maintain PHPDoc annotation in class files.
@ -22,6 +23,19 @@ use yii\helpers\Json;
*/ */
class PhpDocController extends Controller class PhpDocController extends Controller
{ {
/**
* Manually added PHPDoc properties that do not need to be removed.
*
* @phpstan-var array<class-string, string[]>
*/
private const MANUALLY_ADDED_PROPERTIES = [
WebController::class => [
'request',
'response',
'view',
],
];
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -535,7 +549,7 @@ class PhpDocController extends Controller
} }
$oldDoc = $ref->getDocComment(); $oldDoc = $ref->getDocComment();
$newDoc = $this->cleanDocComment($this->updateDocComment($oldDoc, $propertyDoc)); $newDoc = $this->cleanDocComment($this->updateDocComment($oldDoc, $propertyDoc, $className));
$seenSince = false; $seenSince = false;
$seenAuthor = false; $seenAuthor = false;
@ -614,8 +628,9 @@ class PhpDocController extends Controller
* @param $properties * @param $properties
* @return string * @return string
*/ */
protected function updateDocComment($doc, $properties) protected function updateDocComment($doc, $properties, $className)
{ {
$manuallyAddedProperties = self::MANUALLY_ADDED_PROPERTIES[$className] ?? [];
$lines = explode("\n", $doc); $lines = explode("\n", $doc);
$propertyPart = false; $propertyPart = false;
$propertyPosition = false; $propertyPosition = false;
@ -632,9 +647,12 @@ class PhpDocController extends Controller
$propertyPart = false; $propertyPart = false;
} }
if ($propertyPart) { if ($propertyPart) {
preg_match('/@property\s+\w+\s+\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)/', $line, $matches);
if (!isset($matches[1]) || !in_array($matches[1], $manuallyAddedProperties)) {
unset($lines[$i]); unset($lines[$i]);
} }
} }
}
// if no properties or other tags were present add properties at the end // if no properties or other tags were present add properties at the end
if ($propertyPosition === false) { if ($propertyPosition === false) {
@ -700,16 +718,16 @@ class PhpDocController extends Controller
$gets = $this->match( $gets = $this->match(
'#\* @return (?<type>[\w\\|\\\\\\[\\]]+)(?: (?<comment>(?:(?!\*/|\* @).)+?)(?:(?!\*/).)+|[\s\n]*)\*/' . '#\* @return (?<type>[\w\\|\\\\\\[\\]]+)(?: (?<comment>(?:(?!\*/|\* @).)+?)(?:(?!\*/).)+|[\s\n]*)\*/' .
'[\s\n]{2,}public function (?<kind>get)(?<name>\w+)\((?:,? ?\$\w+ ?= ?[^,]+)*\)#', '[\s\n]{2,}(\#\[\\\\*.+\])*[\s\n]{2,}public function (?<kind>get)(?<name>\w+)\((?:,? ?\$\w+ ?= ?[^,]+)*\)#',
$class['content'], true); $class['content'], true);
$sets = $this->match( $sets = $this->match(
'#\* @param (?<type>[\w\\|\\\\\\[\\]]+) \$\w+(?: (?<comment>(?:(?!\*/|\* @).)+?)(?:(?!\*/).)+|[\s\n]*)\*/' . '#\* @param (?<type>[\w\\|\\\\\\[\\]]+) \$\w+(?: (?<comment>(?:(?!\*/|\* @).)+?)(?:(?!\*/).)+|[\s\n]*)\*/' .
'[\s\n]{2,}public function (?<kind>set)(?<name>\w+)\(\$\w+(?:, ?\$\w+ ?= ?[^,]+)*\)#', '[\s\n]{2,}(\#\[\\\\*.+\])*[\s\n]{2,}public function (?<kind>set)(?<name>\w+)\(\$\w+(?:, ?\$\w+ ?= ?[^,]+)*\)#',
$class['content'], true); $class['content'], true);
// check for @property annotations in getter and setter // check for @property annotations in getter and setter
$properties = $this->match( $properties = $this->match(
'#\* @(?<kind>property) (?<type>[\w\\|\\\\\\[\\]]+)(?: (?<comment>(?:(?!\*/|\* @).)+?)(?:(?!\*/).)+|[\s\n]*)\*/' . '#\* @(?<kind>property) (?<type>[\w\\|\\\\\\[\\]]+)(?: (?<comment>(?:(?!\*/|\* @).)+?)(?:(?!\*/).)+|[\s\n]*)\*/' .
'[\s\n]{2,}public function [g|s]et(?<name>\w+)\(((?:,? ?\$\w+ ?= ?[^,]+)*|\$\w+(?:, ?\$\w+ ?= ?[^,]+)*)\)#', '[\s\n]{2,}(\#\[\\\\*.+\])*[\s\n]{2,}public function [g|s]et(?<name>\w+)\(((?:,? ?\$\w+ ?= ?[^,]+)*|\$\w+(?:, ?\$\w+ ?= ?[^,]+)*)\)#',
$class['content']); $class['content']);
$acrs = array_merge($properties, $gets, $sets); $acrs = array_merge($properties, $gets, $sets);
@ -791,6 +809,9 @@ class PhpDocController extends Controller
protected function fixSentence($str) protected function fixSentence($str)
{ {
$str = rtrim($str, '*');
$str = rtrim($str);
// TODO fix word wrap // TODO fix word wrap
if ($str == '') { if ($str == '') {
return ''; return '';

View File

@ -23,6 +23,7 @@ Yii Framework 2 Change Log
- Bug #20494: Fix `PHPdoc`, add `PHPStan/Psalm` annotations for `authMethods` property in `CompositeAuth` class (terabytesoftw) - Bug #20494: Fix `PHPdoc`, add `PHPStan/Psalm` annotations for `authMethods` property in `CompositeAuth` class (terabytesoftw)
- Bug #20485: Fix error `Cannot unset string offsets` in `yii\di\Instance:ensure(['__class' => ...], 'some\class\name')` (max-s-lab) - Bug #20485: Fix error `Cannot unset string offsets` in `yii\di\Instance:ensure(['__class' => ...], 'some\class\name')` (max-s-lab)
- Enh #20505: `ArrayDataProvider` key handling with flexible path support (fetus-hina) - Enh #20505: `ArrayDataProvider` key handling with flexible path support (fetus-hina)
- Bug #20508: Fix PHPDoc, add PHPStan/Psalm annotations for `yii\web\CookieCollection::getIterator`. Add missing `@property` annotation in `yii\base\Model` (max-s-lab)
2.0.53 June 27, 2025 2.0.53 June 27, 2025
-------------------- --------------------

View File

@ -30,13 +30,15 @@ use Yii;
* *
* For more details and usage information on Action, see the [guide article on actions](guide:structure-controllers). * For more details and usage information on Action, see the [guide article on actions](guide:structure-controllers).
* *
* @template T of Controller
* @property-read string $uniqueId The unique ID of this action among the whole application. * @property-read string $uniqueId The unique ID of this action among the whole application.
* @phpstan-property T $controller
* @psalm-property T $controller
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*
* @template T of Controller
*
* @phpstan-property T $controller
* @psalm-property T $controller
*/ */
class Action extends Component class Action extends Component
{ {

View File

@ -46,6 +46,7 @@ use yii\validators\Validator;
* 'Username must contain only word characters.', ], 'email' => [ 'Email address is invalid.', ] ] ```. * 'Username must contain only word characters.', ], 'email' => [ 'Email address is invalid.', ] ] ```.
* @property-read array $firstErrors The first errors. The array keys are the attribute names, and the array * @property-read array $firstErrors The first errors. The array keys are the attribute names, and the array
* values are the corresponding error messages. An empty array will be returned if there is no error. * values are the corresponding error messages. An empty array will be returned if there is no error.
* @property-read ArrayIterator $iterator An iterator for traversing the items in the list.
* @property string $scenario The scenario that this model is in. Defaults to [[SCENARIO_DEFAULT]]. * @property string $scenario The scenario that this model is in. Defaults to [[SCENARIO_DEFAULT]].
* @property-read ArrayObject|\yii\validators\Validator[] $validators All the validators declared in the * @property-read ArrayObject|\yii\validators\Validator[] $validators All the validators declared in the
* model. * model.

View File

@ -520,7 +520,7 @@ class Controller extends \yii\base\Controller
* You may override this method to return customized summary. * You may override this method to return customized summary.
* The default implementation returns first line from the PHPDoc comment. * The default implementation returns first line from the PHPDoc comment.
* *
* @return string * @return string the one-line short summary describing this controller.
*/ */
public function getHelpSummary() public function getHelpSummary()
{ {
@ -532,7 +532,7 @@ class Controller extends \yii\base\Controller
* *
* You may override this method to return customized help. * You may override this method to return customized help.
* The default implementation returns help information retrieved from the PHPDoc comment. * The default implementation returns help information retrieved from the PHPDoc comment.
* @return string * @return string the help information for this controller.
*/ */
public function getHelp() public function getHelp()
{ {

View File

@ -52,7 +52,10 @@ class CookieCollection extends BaseObject implements \IteratorAggregate, \ArrayA
* Returns an iterator for traversing the cookies in the collection. * Returns an iterator for traversing the cookies in the collection.
* This method is required by the SPL interface [[\IteratorAggregate]]. * This method is required by the SPL interface [[\IteratorAggregate]].
* It will be implicitly called when you use `foreach` to traverse the collection. * It will be implicitly called when you use `foreach` to traverse the collection.
* @return ArrayIterator<string, Cookie> an iterator for traversing the cookies in the collection. * @return ArrayIterator an iterator for traversing the cookies in the collection.
*
* @phpstan-return ArrayIterator<string, Cookie>
* @psalm-return ArrayIterator<string, Cookie>
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function getIterator() public function getIterator()