diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c2a5a11..bab1467 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: uses: ramsey/composer-install@v3 - name: Run Psalm - run: vendor/bin/psalm --show-info=false --find-unused-psalm-suppress --no-progress + run: vendor/bin/psalm --show-info=false --no-progress phpunit: name: PHPUnit diff --git a/composer.json b/composer.json index c74a100..a9700dd 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ "require-dev": { "ext-pdo": "*", "phpunit/phpunit": "^9.0", - "vimeo/psalm": "4.2.1" + "vimeo/psalm": "5.24.0" }, "autoload": { "psr-4": { diff --git a/psalm-baseline.xml b/psalm-baseline.xml new file mode 100644 index 0000000..f0174ed --- /dev/null +++ b/psalm-baseline.xml @@ -0,0 +1,36 @@ + + + + + ]]> + + + + + + + + + + + + entities[$class]]]> + entities[$class]]]> + + + + + + + + + + + + + + + + + + diff --git a/psalm.xml b/psalm.xml index 40b6cd5..d96ebef 100644 --- a/psalm.xml +++ b/psalm.xml @@ -5,6 +5,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" + errorBaseline="psalm-baseline.xml" + findUnusedPsalmSuppress="true" + findUnusedBaselineEntry="true" + findUnusedCode="false" > @@ -15,7 +19,6 @@ - diff --git a/src/Configuration.php b/src/Configuration.php index 663af71..4ca2c62 100644 --- a/src/Configuration.php +++ b/src/Configuration.php @@ -374,7 +374,7 @@ public function getCustomPropertyMappings() : array */ public function setTransientProperties(string $class, string ...$properties) : Configuration { - $this->transientProperties[$class] = $properties; + $this->transientProperties[$class] = array_values($properties); return $this; } diff --git a/src/EntityConfiguration.php b/src/EntityConfiguration.php index dd4caf0..8bb1b99 100644 --- a/src/EntityConfiguration.php +++ b/src/EntityConfiguration.php @@ -143,6 +143,8 @@ public function setIdentityProperties(string ...$identityProperties) : EntityCon throw new \InvalidArgumentException('The list of identity properties cannot be empty.'); } + $identityProperties = array_values($identityProperties); + $this->checkProperties($identityProperties); $this->identityProperties = $identityProperties; diff --git a/src/Gateway.php b/src/Gateway.php index f470084..06576b3 100644 --- a/src/Gateway.php +++ b/src/Gateway.php @@ -280,6 +280,7 @@ public function hydrate(object $entity, int $options = 0, string ...$props) : vo $class = $this->getEntityClass($entity); $identity = $this->getIdentity($class, $entity); + $props = array_values($props); $values = $this->loadProps($class, $identity, $props, $options); if ($values === null) { @@ -294,8 +295,6 @@ public function hydrate(object $entity, int $options = 0, string ...$props) : vo /** * Finds entities using a query object. * - * @psalm-suppress MixedOperand See: https://github.com/vimeo/psalm/issues/4739 - * * @psalm-return list * * @param Query $query The query object. @@ -492,7 +491,7 @@ private function doFind(Query $query, int $options = 0) : array } else { $expressionsAndOutputValues = $propertyMapping->convertPropToFields($value); - foreach ($fieldNames as $fieldNameIndex => $fieldName) { + foreach ($fieldNames as $fieldNameIndex => $_) { foreach ($expressionsAndOutputValues[$fieldNameIndex] as $index => $expressionOrValue) { if ($index === 0) { /** @var string $expressionOrValue */ @@ -592,9 +591,6 @@ private function doFind(Query $query, int $options = 0) : array * * @psalm-return array{string, PropertyMapping} * - * @psalm-suppress LessSpecificReturnStatement - * @psalm-suppress MoreSpecificReturnType - * * @throws Exception\UnknownPropertyException */ private function addJoins(EntityMetadata $classMetadata, SelectQueryBuilder $selectBuilder, TableAliasGenerator $tableAliasGenerator, string $mainTableAlias, array & $tableAliases, string $dottedProperty) : array diff --git a/src/ObjectFactory.php b/src/ObjectFactory.php index e240b08..e9094d3 100644 --- a/src/ObjectFactory.php +++ b/src/ObjectFactory.php @@ -64,7 +64,7 @@ public function instantiate(ClassMetadata $classMetadata, array $values = []) : $object = $reflectionClass->newInstanceWithoutConstructor(); - /** @psalm-suppress PossiblyInvalidFunctionCall bindTo() should never return false here */ + /** @psalm-suppress PossiblyNullFunctionCall bindTo() should never return null here */ (function() use ($classMetadata, $values, $reflectionClass) { // Unset persistent properties // @todo PHP 7.4: for even better performance, only unset typed properties that have a default value, as @@ -79,7 +79,6 @@ public function instantiate(ClassMetadata $classMetadata, array $values = []) : // @todo temporary fix: do not set null values when typed property is not nullable; // needs investigation to see why these null values are being passed in the first place - /** @var \ReflectionType|null $reflectionType */ $reflectionType = $reflectionClass->getProperty($key)->getType(); if ($reflectionType !== null && ! $reflectionType->allowsNull()) { @@ -221,11 +220,8 @@ private function getPropertyValueConverter(\ReflectionProperty $property) : Clos throw new \InvalidArgumentException(sprintf('Expected array for property $%s of class %s, got %s.', $propertyName, $className, gettype($value))); } - /** @psalm-var class-string $typeName */ - $typeName = $type->getName(); - /** @psalm-var array $value */ - return $this->instantiateDTO($typeName, $value); + return $this->instantiateDTO($type->getName(), $value); }; } @@ -249,7 +245,7 @@ private function getPropertyValueConverter(\ReflectionProperty $property) : Clos */ public function read(object $object) : array { - /** @psalm-suppress PossiblyInvalidFunctionCall bindTo() should never return false here */ + /** @psalm-suppress PossiblyNullFunctionCall bindTo() should never return null here */ return (function() { return get_object_vars($this); })->bindTo($object, $object)(); @@ -267,7 +263,7 @@ public function read(object $object) : array */ public function write(object $object, array $values) : void { - /** @psalm-suppress PossiblyInvalidFunctionCall bindTo() should never return false here */ + /** @psalm-suppress PossiblyNullFunctionCall bindTo() should never return null here */ (function() use ($values) { foreach ($values as $key => $value) { $this->{$key} = $value; diff --git a/src/PropertyMapping/EmbeddableMapping.php b/src/PropertyMapping/EmbeddableMapping.php index 74013ef..97fcee4 100644 --- a/src/PropertyMapping/EmbeddableMapping.php +++ b/src/PropertyMapping/EmbeddableMapping.php @@ -129,15 +129,16 @@ public function convertPropToFields(mixed $propValue) : array /** @var object|null $entity */ $entity = $propValue; - if ($entity !== null) { - $r = new \ReflectionObject($entity); - } + $r = null; foreach ($this->classMetadata->properties as $prop) { if ($entity === null) { $idPropValue = null; } else { - /** @psalm-var ReflectionObject $r */ + if ($r === null) { + $r = new ReflectionObject($entity); + } + $p = $r->getProperty($prop); $idPropValue = $p->getValue($entity); } diff --git a/src/PropertyMapping/EntityMapping.php b/src/PropertyMapping/EntityMapping.php index 14ae3c3..0c5705b 100644 --- a/src/PropertyMapping/EntityMapping.php +++ b/src/PropertyMapping/EntityMapping.php @@ -150,9 +150,6 @@ public function convertInputValuesToProp(Gateway $gateway, array $values) : mixe /** * @todo use Gateway::getIdentity() instead; currently does not check that the object has an identity - * - * @psalm-suppress MixedArrayAccess Psalm does not understand references - * @psalm-suppress MixedArrayAssignment Psalm does not understand references */ public function convertPropToFields(mixed $propValue) : array { @@ -176,7 +173,7 @@ public function convertPropToFields(mixed $propValue) : array $identity = []; if ($entity !== null) { - /** @psalm-suppress PossiblyInvalidFunctionCall bindTo() should never return false here */ + /** @psalm-suppress PossiblyNullFunctionCall bindTo() should never return null here */ (function() use ($idProperties, & $identity) { foreach ($idProperties as $prop) { $identity[$prop] = $this->{$prop}; diff --git a/src/Query.php b/src/Query.php index 616e91a..9aca544 100644 --- a/src/Query.php +++ b/src/Query.php @@ -48,7 +48,7 @@ public function __construct(string $className) public function setProperties(string ...$properties) : Query { - $this->properties = $properties; + $this->properties = array_values($properties); return $this; } diff --git a/src/SelectQueryBuilder.php b/src/SelectQueryBuilder.php index 2c23360..587c759 100644 --- a/src/SelectQueryBuilder.php +++ b/src/SelectQueryBuilder.php @@ -137,9 +137,6 @@ public function setOptions(int $options) : void $this->options = $options; } - /** - * @psalm-suppress MixedOperand See: https://github.com/vimeo/psalm/issues/4739 - */ public function build() : string { $query = 'SELECT ' . implode(', ', $this->selectFields) . ' FROM ' . $this->tableName;