Browse Source

Fix errors reported by static analyzers.

ADmad 4 years ago
parent
commit
eb65d06474

+ 1 - 36
phpstan-baseline.neon

@@ -16,17 +16,12 @@ parameters:
 			path: src/Collection/Collection.php
 
 		-
-			message: "#^Parameter \\#1 \\$iterator of method AppendIterator\\:\\:append\\(\\) expects Iterator, Traversable given\\.$#"
-			count: 2
-			path: src/Collection/Collection.php
-
-		-
 			message: "#^Strict comparison using \\=\\=\\= between class\\-string\\<ArrayObject\\> and 'ArrayIterator' will always evaluate to false\\.$#"
 			count: 1
 			path: src/Collection/Collection.php
 
 		-
-			message: "#^Call to an undefined method Traversable\\:\\:getArrayCopy\\(\\)\\.$#"
+			message: "#^Call to an undefined method Iterator\\:\\:getArrayCopy\\(\\)\\.$#"
 			count: 1
 			path: src/Collection/Iterator/ExtractIterator.php
 
@@ -51,11 +46,6 @@ parameters:
 			path: src/Collection/Iterator/TreeIterator.php
 
 		-
-			message: "#^Parameter \\#1 \\$iterator of method AppendIterator\\:\\:append\\(\\) expects Iterator, Traversable given\\.$#"
-			count: 2
-			path: src/Collection/Iterator/TreeIterator.php
-
-		-
 			message: "#^Strict comparison using \\=\\=\\= between class\\-string\\<ArrayObject\\> and 'ArrayIterator' will always evaluate to false\\.$#"
 			count: 1
 			path: src/Collection/Iterator/TreeIterator.php
@@ -66,11 +56,6 @@ parameters:
 			path: src/Collection/Iterator/TreePrinter.php
 
 		-
-			message: "#^Parameter \\#1 \\$iterator of method AppendIterator\\:\\:append\\(\\) expects Iterator, Traversable given\\.$#"
-			count: 2
-			path: src/Collection/Iterator/TreePrinter.php
-
-		-
 			message: "#^Strict comparison using \\=\\=\\= between class\\-string\\<ArrayObject\\> and 'ArrayIterator' will always evaluate to false\\.$#"
 			count: 1
 			path: src/Collection/Iterator/TreePrinter.php
@@ -86,16 +71,6 @@ parameters:
 			path: src/Collection/Iterator/ZipIterator.php
 
 		-
-			message: "#^Parameter \\#1 \\$iterator of method AppendIterator\\:\\:append\\(\\) expects Iterator, Traversable given\\.$#"
-			count: 2
-			path: src/Collection/Iterator/ZipIterator.php
-
-		-
-			message: "#^Parameter \\#1 \\$iterator of method MultipleIterator\\:\\:attachIterator\\(\\) expects Iterator, Traversable given\\.$#"
-			count: 1
-			path: src/Collection/Iterator/ZipIterator.php
-
-		-
 			message: "#^Strict comparison using \\=\\=\\= between class\\-string\\<ArrayObject\\> and 'ArrayIterator' will always evaluate to false\\.$#"
 			count: 1
 			path: src/Collection/Iterator/ZipIterator.php
@@ -291,11 +266,6 @@ parameters:
 			path: src/Mailer/Renderer.php
 
 		-
-			message: "#^PHPDoc tag @param for parameter \\$conditions with type array\\|Cake\\\\Database\\\\ExpressionInterface\\|Closure\\|string\\|null is not subtype of native type array\\|Cake\\\\Database\\\\ExpressionInterface\\|Closure\\.$#"
-			count: 1
-			path: src/ORM/Association.php
-
-		-
 			message: "#^Unsafe usage of new static\\(\\)\\.$#"
 			count: 2
 			path: src/ORM/EagerLoader.php
@@ -326,11 +296,6 @@ parameters:
 			path: src/ORM/ResultSet.php
 
 		-
-			message: "#^Parameter \\#1 \\$iterator of method AppendIterator\\:\\:append\\(\\) expects Iterator, Traversable given\\.$#"
-			count: 2
-			path: src/ORM/ResultSet.php
-
-		-
 			message: "#^Strict comparison using \\=\\=\\= between class\\-string\\<ArrayObject\\> and 'ArrayIterator' will always evaluate to false\\.$#"
 			count: 1
 			path: src/ORM/ResultSet.php

+ 0 - 54
psalm-baseline.xml

@@ -43,11 +43,6 @@
       <code>ReturnTypeWillChange</code>
     </UndefinedAttributeClass>
   </file>
-  <file src="src/Controller/Controller.php">
-    <PropertyTypeCoercion occurrences="1">
-      <code>$result</code>
-    </PropertyTypeCoercion>
-  </file>
   <file src="src/Controller/ControllerFactory.php">
     <ArgumentTypeCoercion occurrences="3">
       <code>$request</code>
@@ -70,50 +65,6 @@
       <code>$request</code>
     </ArgumentTypeCoercion>
   </file>
-  <file src="src/Http/Cookie/Cookie.php">
-    <InvalidReturnStatement occurrences="1">
-      <code>$this-&gt;value</code>
-    </InvalidReturnStatement>
-    <InvalidReturnType occurrences="1">
-      <code>string</code>
-    </InvalidReturnType>
-    <UndefinedInterfaceMethod occurrences="2">
-      <code>setTimezone</code>
-      <code>setTimezone</code>
-    </UndefinedInterfaceMethod>
-  </file>
-  <file src="src/Http/ServerRequest.php">
-    <ArgumentTypeCoercion occurrences="1">
-      <code>$this-&gt;data</code>
-    </ArgumentTypeCoercion>
-  </file>
-  <file src="src/I18n/DateFormatTrait.php">
-    <MissingParamType occurrences="1">
-      <code>$format</code>
-    </MissingParamType>
-  </file>
-  <file src="src/I18n/functions.php">
-    <InternalMethod occurrences="8">
-      <code>translate</code>
-      <code>translate</code>
-      <code>translate</code>
-      <code>translate</code>
-      <code>translate</code>
-      <code>translate</code>
-      <code>translate</code>
-      <code>translate</code>
-    </InternalMethod>
-  </file>
-  <file src="src/ORM/Association.php">
-    <MismatchingDocblockParamType occurrences="1">
-      <code>\Cake\Database\ExpressionInterface|\Closure|array|string|null</code>
-    </MismatchingDocblockParamType>
-  </file>
-  <file src="src/ORM/Locator/TableLocator.php">
-    <NonInvariantDocblockPropertyType occurrences="1">
-      <code>$instances</code>
-    </NonInvariantDocblockPropertyType>
-  </file>
   <file src="src/Routing/Middleware/RoutingMiddleware.php">
     <ArgumentTypeCoercion occurrences="2">
       <code>$request</code>
@@ -188,9 +139,4 @@
       <code>$options</code>
     </ArgumentTypeCoercion>
   </file>
-  <file src="src/View/Widget/SelectBoxWidget.php">
-    <InvalidScalarArgument occurrences="1">
-      <code>$selected</code>
-    </InvalidScalarArgument>
-  </file>
 </files>

+ 2 - 3
src/Collection/CollectionInterface.php

@@ -18,7 +18,6 @@ namespace Cake\Collection;
 
 use Iterator;
 use JsonSerializable;
-use Traversable;
 use const SORT_NUMERIC;
 
 /**
@@ -1096,9 +1095,9 @@ interface CollectionInterface extends Iterator, JsonSerializable
      * losing any possible transformations. This is used mainly to remove empty
      * IteratorIterator wrappers that can only slowdown the iteration process.
      *
-     * @return \Traversable
+     * @return \Iterator
      */
-    public function unwrap(): Traversable;
+    public function unwrap(): Iterator;
 
     /**
      * Transpose rows and columns into columns and rows

+ 2 - 1
src/Collection/CollectionTrait.php

@@ -32,6 +32,7 @@ use Cake\Collection\Iterator\UnfoldIterator;
 use Cake\Collection\Iterator\ZipIterator;
 use Countable;
 use InvalidArgumentException;
+use Iterator;
 use LimitIterator;
 use LogicException;
 use OuterIterator;
@@ -894,7 +895,7 @@ trait CollectionTrait
     /**
      * @inheritDoc
      */
-    public function unwrap(): Traversable
+    public function unwrap(): Iterator
     {
         $iterator = $this;
         while (

+ 2 - 2
src/Collection/Iterator/ExtractIterator.php

@@ -19,7 +19,7 @@ namespace Cake\Collection\Iterator;
 use ArrayIterator;
 use Cake\Collection\Collection;
 use Cake\Collection\CollectionInterface;
-use Traversable;
+use Iterator;
 
 /**
  * Creates an iterator from another iterator that extract the requested column
@@ -78,7 +78,7 @@ class ExtractIterator extends Collection
     /**
      * @inheritDoc
      */
-    public function unwrap(): Traversable
+    public function unwrap(): Iterator
     {
         $iterator = $this->getInnerIterator();
 

+ 1 - 1
src/Collection/Iterator/FilterIterator.php

@@ -62,7 +62,7 @@ class FilterIterator extends Collection
     /**
      * @inheritDoc
      */
-    public function unwrap(): Traversable
+    public function unwrap(): Iterator
     {
         /** @var \IteratorIterator $filter */
         $filter = $this->getInnerIterator();

+ 2 - 1
src/Collection/Iterator/ReplaceIterator.php

@@ -19,6 +19,7 @@ namespace Cake\Collection\Iterator;
 use ArrayIterator;
 use Cake\Collection\Collection;
 use Cake\Collection\CollectionInterface;
+use Iterator;
 use Traversable;
 
 /**
@@ -75,7 +76,7 @@ class ReplaceIterator extends Collection
     /**
      * @inheritDoc
      */
-    public function unwrap(): Traversable
+    public function unwrap(): Iterator
     {
         $iterator = $this->_innerIterator;
 

+ 3 - 3
src/Collection/Iterator/SortIterator.php

@@ -18,7 +18,7 @@ namespace Cake\Collection\Iterator;
 
 use Cake\Collection\Collection;
 use DateTimeInterface;
-use Traversable;
+use Iterator;
 use const SORT_DESC;
 use const SORT_NUMERIC;
 
@@ -92,9 +92,9 @@ class SortIterator extends Collection
     /**
      * {@inheritDoc}
      *
-     * @return \Traversable
+     * @return \Iterator
      */
-    public function unwrap(): Traversable
+    public function unwrap(): Iterator
     {
         return $this->getInnerIterator();
     }

+ 2 - 1
src/Collection/Iterator/StoppableIterator.php

@@ -19,6 +19,7 @@ namespace Cake\Collection\Iterator;
 use ArrayIterator;
 use Cake\Collection\Collection;
 use Cake\Collection\CollectionInterface;
+use Iterator;
 use Traversable;
 
 /**
@@ -86,7 +87,7 @@ class StoppableIterator extends Collection
     /**
      * @inheritDoc
      */
-    public function unwrap(): Traversable
+    public function unwrap(): Iterator
     {
         $iterator = $this->_innerIterator;
 

+ 1 - 0
src/Controller/Controller.php

@@ -501,6 +501,7 @@ class Controller implements EventListenerInterface, EventDispatcherInterface
             $result = $this->render();
         }
         if ($result) {
+            /** @psalm-suppress PropertyTypeCoercion */
             $this->response = $result;
         }
     }

+ 6 - 3
src/Http/Cookie/Cookie.php

@@ -171,6 +171,7 @@ class Cookie implements CookieInterface
         }
 
         if ($expiresAt) {
+            /** @psalm-suppress UndefinedInterfaceMethod */
             $expiresAt = $expiresAt->setTimezone(new DateTimeZone('GMT'));
         } else {
             $expiresAt = static::$defaults['expires'];
@@ -424,13 +425,14 @@ class Cookie implements CookieInterface
             return $this->_flatten($this->value);
         }
 
+        /** @var string */
         return $this->value;
     }
 
     /**
      * @inheritDoc
      */
-    public function withValue($value): static
+    public function withValue(array|string|float|int|bool $value): static
     {
         $new = clone $this;
         $new->_setValue($value);
@@ -529,9 +531,10 @@ class Cookie implements CookieInterface
     /**
      * @inheritDoc
      */
-    public function withExpiry($dateTime): static
+    public function withExpiry(DateTimeInterface $dateTime): static
     {
         $new = clone $this;
+        /** @psalm-suppress UndefinedInterfaceMethod */
         $new->expiresAt = $dateTime->setTimezone(new DateTimeZone('GMT'));
 
         return $new;
@@ -572,7 +575,7 @@ class Cookie implements CookieInterface
     /**
      * @inheritDoc
      */
-    public function isExpired($time = null): bool
+    public function isExpired(?DateTimeInterface $time = null): bool
     {
         $time = $time ?: new DateTimeImmutable('now', new DateTimeZone('UTC'));
         if (!$this->expiresAt) {

+ 1 - 2
src/Http/ServerRequest.php

@@ -1268,11 +1268,10 @@ class ServerRequest implements ServerRequestInterface
         if ($name === null) {
             return $this->data;
         }
-        if (!is_array($this->data) && $name) {
+        if (!is_array($this->data)) {
             return $default;
         }
 
-        /** @psalm-suppress PossiblyNullArgument */
         return Hash::get($this->data, $name, $default);
     }
 

+ 17 - 2
src/I18n/DateFormatTrait.php

@@ -309,9 +309,24 @@ trait DateFormatTrait
     }
 
     /**
-     * @inheritDoc
+     * Sets the default format used when converting this object to JSON
+     *
+     * The format should be either the formatting constants from IntlDateFormatter as
+     * described in (https://secure.php.net/manual/en/class.intldateformatter.php) or a pattern
+     * as specified in (http://www.icu-project.org/apiref/icu4c/classSimpleDateFormat.html#details)
+     *
+     * It is possible to provide an array of 2 constants. In this case, the first position
+     * will be used for formatting the date part of the object and the second position
+     * will be used to format the time part.
+     *
+     * Alternatively, the format can provide a callback. In this case, the callback
+     * can receive this datetime object and return a formatted string.
+     *
+     * @see \Cake\I18n\Time::i18nFormat()
+     * @param \Closure|array|string|int $format Format.
+     * @return void
      */
-    public static function setJsonEncodeFormat($format): void
+    public static function setJsonEncodeFormat(Closure|array|string|int $format): void
     {
         static::$_jsonEncodeFormat = $format;
     }

+ 8 - 0
src/I18n/functions.php

@@ -35,6 +35,7 @@ if (!function_exists('__')) {
             $args = $args[0];
         }
 
+        /** @psalm-suppress InternalMethod */
         return I18n::getTranslator()->translate($singular, $args);
     }
 
@@ -61,6 +62,7 @@ if (!function_exists('__n')) {
             $args = $args[0];
         }
 
+        /** @psalm-suppress InternalMethod */
         return I18n::getTranslator()->translate(
             $plural,
             ['_count' => $count, '_singular' => $singular] + $args
@@ -88,6 +90,7 @@ if (!function_exists('__d')) {
             $args = $args[0];
         }
 
+        /** @psalm-suppress InternalMethod */
         return I18n::getTranslator($domain)->translate($msg, $args);
     }
 
@@ -116,6 +119,7 @@ if (!function_exists('__dn')) {
             $args = $args[0];
         }
 
+        /** @psalm-suppress InternalMethod */
         return I18n::getTranslator($domain)->translate(
             $plural,
             ['_count' => $count, '_singular' => $singular] + $args
@@ -145,6 +149,7 @@ if (!function_exists('__x')) {
             $args = $args[0];
         }
 
+        /** @psalm-suppress InternalMethod */
         return I18n::getTranslator()->translate($singular, ['_context' => $context] + $args);
     }
 
@@ -174,6 +179,7 @@ if (!function_exists('__xn')) {
             $args = $args[0];
         }
 
+        /** @psalm-suppress InternalMethod */
         return I18n::getTranslator()->translate(
             $plural,
             ['_count' => $count, '_singular' => $singular, '_context' => $context] + $args
@@ -204,6 +210,7 @@ if (!function_exists('__dx')) {
             $args = $args[0];
         }
 
+        /** @psalm-suppress InternalMethod */
         return I18n::getTranslator($domain)->translate(
             $msg,
             ['_context' => $context] + $args
@@ -243,6 +250,7 @@ if (!function_exists('__dxn')) {
             $args = $args[0];
         }
 
+        /** @psalm-suppress InternalMethod */
         return I18n::getTranslator($domain)->translate(
             $plural,
             ['_count' => $count, '_singular' => $singular, '_context' => $context] + $args

+ 1 - 1
src/ORM/Association.php

@@ -852,7 +852,7 @@ abstract class Association
      * @see \Cake\ORM\Table::exists()
      * @return bool
      */
-    public function exists(ExpressionInterface|Closure|array $conditions): bool
+    public function exists(ExpressionInterface|Closure|array|string|null $conditions): bool
     {
         $conditions = $this->find()
             ->where($conditions)

+ 1 - 0
src/ORM/Locator/TableLocator.php

@@ -49,6 +49,7 @@ class TableLocator extends AbstractLocator implements LocatorInterface
      * Instances that belong to the registry.
      *
      * @var array<string, \Cake\ORM\Table>
+     * @psalm-suppress NonInvariantDocblockPropertyType
      */
     protected array $instances = [];
 

+ 0 - 3
src/Validation/Validator.php

@@ -2541,9 +2541,6 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
             $message = __d('cake', 'The provided value is invalid');
         }
 
-        /**
-         * @var \Cake\Validation\ValidationRule $rule
-         */
         foreach ($rules as $name => $rule) {
             $result = $rule->process($data[$field], $this->_providers, compact('newRecord', 'data', 'field'));
             if ($result === true) {

+ 3 - 3
src/View/Widget/SelectBoxWidget.php

@@ -199,7 +199,7 @@ class SelectBoxWidget extends BasicWidget
      * @param string $label The optgroup label text
      * @param \ArrayAccess|array $optgroup The opt group data.
      * @param array|null $disabled The options to disable.
-     * @param array|string|bool|null $selected The options to select.
+     * @param array|string|int|bool|null $selected The options to select.
      * @param array $templateVars Additional template variables.
      * @param bool $escape Toggle HTML escaping
      * @return string Formatted template string
@@ -208,7 +208,7 @@ class SelectBoxWidget extends BasicWidget
         string $label,
         ArrayAccess|array $optgroup,
         ?array $disabled,
-        array|string|bool|null $selected,
+        array|string|int|bool|null $selected,
         array $templateVars,
         bool $escape
     ): string {
@@ -236,7 +236,7 @@ class SelectBoxWidget extends BasicWidget
      *
      * @param iterable $options The options to render.
      * @param array<string>|null $disabled The options to disable.
-     * @param array|string|null $selected The options to select.
+     * @param array|string|int|bool|null $selected The options to select.
      * @param array $templateVars Additional template variables.
      * @param bool $escape Toggle HTML escaping.
      * @return array<string> Option elements.