Skip to content

Commit e4b6574

Browse files
committed
Tests: Introduce Psalm and fix all errors for level 5 and publish psalm report to pull request.
1 parent cd6d24e commit e4b6574

File tree

17 files changed

+192
-56
lines changed

17 files changed

+192
-56
lines changed

.github/workflows/integration.yaml

Lines changed: 73 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,79 @@ on:
1313
- 'README.md'
1414

1515
jobs:
16+
static-analysis:
17+
name: Static Code Analysis
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout code
21+
uses: actions/checkout@v2
22+
23+
- name: Install PHP with extensions
24+
uses: shivammathur/setup-php@v2
25+
with:
26+
php-version: ${{ matrix.php }}
27+
tools: 'composer:v2, flex'
28+
29+
- name: Install Package Deps
30+
uses: ramsey/composer-install@v2
31+
with:
32+
dependency-versions: stable
33+
composer-options: --prefer-dist
34+
35+
- name: Install Psalm
36+
uses: ramsey/composer-install@v2
37+
with:
38+
composer-options: --prefer-dist
39+
working-directory: tools/psalm
40+
41+
- name: Psalm
42+
run: tools/psalm/vendor/bin/psalm --report=psalm-report.sarif
43+
44+
- run: |
45+
wget https://github.com/zolex/go-sarif-to-markdown-table/raw/refs/heads/main/bin/sarif-to-markdown-table-linux-amd64
46+
chmod +x ./sarif-to-markdown-table-linux-amd64
47+
cat psalm-report.sarif | ./sarif-to-markdown-table-linux-amd64 > psalm-report.markdown
48+
49+
- uses: mshick/add-pr-comment@v2
50+
with:
51+
message-path: ./psalm-report.markdown
52+
message-id: psalm
53+
54+
55+
codestyle:
56+
name: Code Style
57+
runs-on: ubuntu-latest
58+
steps:
59+
- name: Checkout code
60+
uses: actions/checkout@v2
61+
62+
- name: Install PHP with extensions
63+
uses: shivammathur/setup-php@v2
64+
with:
65+
coverage: xdebug
66+
php-version: ${{ matrix.php }}
67+
tools: 'composer:v2, flex'
68+
69+
- name: Install Package Deps
70+
uses: ramsey/composer-install@v2
71+
with:
72+
dependency-versions: stable
73+
composer-options: --prefer-dist
74+
75+
- name: Install PHP-CS-Fixer
76+
uses: ramsey/composer-install@v2
77+
with:
78+
dependency-versions: stable
79+
composer-options: --prefer-dist
80+
working-directory: tools/php-cs-fixer
81+
82+
- name: PHP-CS-Fixer
83+
run: PHP_CS_FIXER_IGNORE_ENV=1 tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --diff --dry-run --show-progress=dots --ansi --verbose
84+
1685
tests:
1786
name: Test ${{ matrix.php }}, symfony=${{ matrix.symfony }}, deps=${{ matrix.deps }}
1887
runs-on: ubuntu-latest
88+
needs: [ codestyle, static-analysis ]
1989
env:
2090
SYMFONY_DEPRECATIONS_HELPER: 'max[self]=0'
2191
strategy:
@@ -72,10 +142,10 @@ jobs:
72142
- name: Run tests
73143
run: tools/phpunit/vendor/bin/phpunit --colors=always --testdox
74144

75-
cs:
76-
name: Code Style & Coverage
145+
coverage:
146+
name: Coverage Report
77147
runs-on: ubuntu-latest
78-
needs: [ tests ]
148+
needs: [ codestyle, static-analysis, tests ]
79149
steps:
80150
- name: Checkout code
81151
uses: actions/checkout@v2
@@ -99,16 +169,6 @@ jobs:
99169
composer-options: --prefer-dist
100170
working-directory: tools/phpunit
101171

102-
- name: Install PHP-CS-Fixer
103-
uses: ramsey/composer-install@v2
104-
with:
105-
dependency-versions: stable
106-
composer-options: --prefer-dist
107-
working-directory: tools/php-cs-fixer
108-
109-
- name: PHP-CS-Fixer
110-
run: PHP_CS_FIXER_IGNORE_ENV=1 tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --diff --dry-run --show-progress=dots --ansi --verbose
111-
112172
- name: Create Coverage Report
113173
run: tools/phpunit/vendor/bin/phpunit --colors=always --coverage-text --coverage-clover=./clover.xml
114174

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66
/composer.lock
77
/.php-cs-fixer.cache
88
/.phpunit.result.cache
9+
/psalm-report.sarif
910
/test-results

Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: deps deps-test deps-codestyle test test-lowest test-stable codestyle-fix codestyle help
1+
.PHONY: deps deps-test deps-codestyle deps-static-analysis test test-lowest test-stable static-analysis codestyle-fix codestyle help
22
.DEFAULT_GOAL:=help
33

44
deps: ## Install project dependencies
@@ -10,6 +10,9 @@ deps-test: ## Install PHPUnit dependencies
1010
deps-codestyle: ## Install PHP-CS-Fixer dependencies
1111
XDEBUG_MODE=off composer update --prefer-dist --no-plugins --no-scripts $(COMPOSER_ARGS) --working-dir=tools/php-cs-fixer
1212

13+
deps-static-analysis: ## Install dependencies for psalm
14+
XDEBUG_MODE=off composer update --prefer-dist --no-plugins --no-scripts $(COMPOSER_ARGS) --working-dir=tools/psalm
15+
1316
test: deps deps-test ## Run the test with locked dependencies
1417
XDEBUG_MODE=coverage tools/phpunit/vendor/bin/phpunit --colors=always --coverage-text --testdox
1518

@@ -19,6 +22,9 @@ test-lowest: COMPOSER_ARGS=--prefer-lowest
1922
test-stable: test ## Run the tests with stable dependencies
2023
test-stable: COMPOSER_ARGS=--prefer-stable
2124

25+
static-analysis: deps deps-static-analysis ## Run static code analysis
26+
XDEBUG_MODE=off tools/psalm/vendor/bin/psalm --report=psalm-report.sarif
27+
2228
codestyle-fix: deps-codestyle ## Fix Codestyle issues
2329
PHP_CS_FIXER_IGNORE_ENV=1 XDEBUG_MODE=off tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --diff --show-progress=dots --ansi --verbose $(CS_FIXER_ARGS)
2430

psalm.xml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0"?>
2+
<psalm
3+
errorLevel="5"
4+
resolveFromConfigFile="true"
5+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6+
xmlns="https://getpsalm.org/schema/config"
7+
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
8+
findUnusedBaselineEntry="false"
9+
findUnusedCode="false"
10+
findUnusedIssueHandlerSuppression="false"
11+
ensureOverrideAttribute="false"
12+
>
13+
<projectFiles>
14+
<directory name="src" />
15+
<ignoreFiles>
16+
<directory name="vendor" />
17+
<file name="src/Symfony/Bundle/DependencyInjection/Configuration.php" />
18+
</ignoreFiles>
19+
</projectFiles>
20+
21+
<forbiddenFunctions>
22+
<function name="empty"/>
23+
</forbiddenFunctions>
24+
</psalm>

src/Mapping/AbstractProperty.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515

1616
use Zolex\VOM\Metadata\ModelMetadata;
1717

18+
/**
19+
* @psalm-inheritors Property|Argument
20+
*/
1821
abstract class AbstractProperty
1922
{
2023
public function __construct(
@@ -32,7 +35,7 @@ public function __construct(
3235
private ?array $map = null,
3336
private bool $serialized = false,
3437
private ?string $extractor = null,
35-
private ?string $scenario = ModelMetadata::DEFAULT_SCENARIO,
38+
private string $scenario = ModelMetadata::DEFAULT_SCENARIO,
3639
private ?int $relative = null,
3740
) {
3841
}

src/Mapping/Normalizer.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ final class Normalizer
2020
{
2121
public function __construct(
2222
private readonly ?string $accessor = null,
23-
private readonly ?string $scenario = ModelMetadata::DEFAULT_SCENARIO,
23+
private readonly string $scenario = ModelMetadata::DEFAULT_SCENARIO,
2424
) {
2525
}
2626

@@ -29,7 +29,7 @@ public function getAccessor(): ?string
2929
return $this->accessor;
3030
}
3131

32-
public function getScenario(): ?string
32+
public function getScenario(): string
3333
{
3434
return $this->scenario;
3535
}

src/Metadata/Factory/ModelMetadataFactory.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ public function getMetadataFor(string|\ReflectionClass $class, ?ModelMetadata $m
124124
$modelMetadata->addConstructorArgument($propertyMetadata);
125125
}
126126

127-
if (!$hasPropertyMetadata && ($type = $reflectionParameter->getType()?->getName())) {
127+
$reflectionType = $reflectionParameter->getType();
128+
if (!$hasPropertyMetadata && $reflectionType instanceof \ReflectionNamedType && ($type = $reflectionType->getName())) {
128129
$dependencies = $this->addDependencyInjectionArgument($type, $reflectionParameter, $class, $constructor, []);
129130
$modelMetadata->addConstructorDependency(reset($dependencies));
130131
}
@@ -210,7 +211,8 @@ private function createNormalizerMetadata(
210211

211212
$dependencyInjectionArguments = [];
212213
foreach ($reflectionMethod->getParameters() as $reflectionParameter) {
213-
if ($type = $reflectionParameter->getType()?->getName()) {
214+
$reflectionType = $reflectionParameter->getType();
215+
if ($reflectionType instanceof \ReflectionNamedType && ($type = $reflectionType->getName())) {
214216
$dependencyInjectionArguments = $this->addDependencyInjectionArgument($type, $reflectionParameter, $reflectionClass, $reflectionMethod, $dependencyInjectionArguments);
215217
}
216218
}
@@ -258,7 +260,8 @@ private function createDenormalizerMetadata(
258260
$methodArguments[$scenario][$reflectionParameter->getName()] = $propertyMetadata;
259261
}
260262

261-
if (!$hasPropertyMetadata && ($type = $reflectionParameter->getType()?->getName())) {
263+
$reflectionType = $reflectionParameter->getType();
264+
if (!$hasPropertyMetadata && $reflectionType instanceof \ReflectionNamedType && ($type = $reflectionType->getName())) {
262265
$dependencyInjectionArguments = $this->addDependencyInjectionArgument($type, $reflectionParameter, $reflectionClass, $reflectionMethod, $dependencyInjectionArguments);
263266
}
264267
}
@@ -308,7 +311,8 @@ private function createFactoryMetadata(
308311
$methodArguments[$scenario][$reflectionParameter->getName()] = $propertyMetadata;
309312
}
310313

311-
if (!$hasPropertyMetadata && ($type = $reflectionParameter->getType()?->getName())) {
314+
$reflectionType = $reflectionParameter->getType();
315+
if (!$hasPropertyMetadata && $reflectionType instanceof \ReflectionNamedType && ($type = $reflectionType->getName())) {
312316
$dependencyInjectionArguments = $this->addDependencyInjectionArgument($type, $reflectionParameter, $reflectionClass, $reflectionMethod, $dependencyInjectionArguments);
313317
}
314318
}

src/Metadata/ModelMetadata.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public function addConstructorDependency(DependencyInjectionMetadata $dependency
136136
}
137137

138138
/**
139-
* @return DenormalizerMetadata[]
139+
* @return \Generator<int, DenormalizerMetadata>
140140
*/
141141
public function getDenormalizers(): iterable
142142
{
@@ -156,7 +156,7 @@ public function addDenormalizer(DenormalizerMetadata $denormalizerMetadata): voi
156156
}
157157

158158
/**
159-
* @return NormalizerMetadata[]
159+
* @return \Generator<int, NormalizerMetadata>
160160
*/
161161
public function getNormalizers(string $scenario = self::DEFAULT_SCENARIO): iterable
162162
{
@@ -181,7 +181,7 @@ public function addNormalizer(NormalizerMetadata $normalizerMetadata): void
181181
}
182182

183183
/**
184-
* @return FactoryMetadata[]
184+
* @return \Generator<int, FactoryMetadata>
185185
*/
186186
public function getFactories(): iterable
187187
{

src/Metadata/PropertyMetadata.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
class PropertyMetadata
2020
{
21-
private readonly mixed $defaultValue;
21+
private mixed $defaultValue;
2222
private bool $nullable = false;
2323

2424
public function __construct(
@@ -56,7 +56,10 @@ public function getName(): string
5656
return $this->name;
5757
}
5858

59-
public function getField(): ?string
59+
/**
60+
* @return non-empty-array<int|string, string>|string|null
61+
*/
62+
public function getField(): array|string|null
6063
{
6164
return $this->attribute->getField() ?? (($accessor = $this->getAccessor()) ? $accessor : null);
6265
}

src/Serializer/Factory/VersatileObjectMapperFactory.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class VersatileObjectMapperFactory
4040
private static ?ObjectNormalizer $objectNormalizer = null;
4141
private static ?ModelMetadataFactoryInterface $metadataFactory = null;
4242

43-
public static function destroy()
43+
public static function destroy(): void
4444
{
4545
self::$metadataFactory = null;
4646
self::$objectNormalizer = null;
@@ -83,7 +83,7 @@ public static function createObjectNormalizer(?CacheItemPoolInterface $cacheItem
8383
return new ObjectNormalizer(self::$metadataFactory, $propertyAccessor, $classMetadataFactory, $classDiscriminatorResolver);
8484
}
8585

86-
public static function getObjectNormalizer(?CacheItemPoolInterface $cacheItemPool = null): ObjectNormalizer
86+
public static function getObjectNormalizer(?CacheItemPoolInterface $cacheItemPool = null): ?ObjectNormalizer
8787
{
8888
if (!self::$objectNormalizer) {
8989
self::create($cacheItemPool);
@@ -92,7 +92,7 @@ public static function getObjectNormalizer(?CacheItemPoolInterface $cacheItemPoo
9292
return self::$objectNormalizer;
9393
}
9494

95-
public static function getMetadataFactory(?CacheItemPoolInterface $cacheItemPool = null): ModelMetadataFactoryInterface
95+
public static function getMetadataFactory(?CacheItemPoolInterface $cacheItemPool = null): ?ModelMetadataFactoryInterface
9696
{
9797
if (!self::$objectNormalizer) {
9898
self::create($cacheItemPool);

0 commit comments

Comments
 (0)