Skip to content

Commit 4148e23

Browse files
authored
Merge pull request #517 from goaop/feature/increase-phpstan-level
feat: Increase the phpstan level
2 parents 293a54e + 76b9409 commit 4148e23

38 files changed

+453
-152
lines changed

.github/workflows/phpstan.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ name: "PHPStan analysis"
33
on:
44
pull_request:
55
push:
6+
branches:
7+
- master
68

79
jobs:
810
build:

.github/workflows/phpunit.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ name: "PHPUnit tests"
33
on:
44
pull_request:
55
push:
6+
branches:
7+
- master
68

79
jobs:
810
phpunit:
9-
name: "PHPUnit tests"
11+
name: "PHPUnit tests (${{ matrix.dependencies }}, ${{ matrix.php-version }}, ${{ matrix.operating-system }})"
1012

1113
runs-on: ${{ matrix.operating-system }}
1214

phpstan-baseline.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,31 @@
1313
'count' => 1,
1414
'path' => __DIR__ . '/src/Proxy/Part/PropertyInterceptionTrait.php',
1515
];
16+
$ignoreErrors[] = [
17+
// ClassProxyGenerator is a code generator: the parent class name is valid but the class does not
18+
// exist yet at analysis time (it is defined in the weaved file after transformation).
19+
// class_exists() cannot be used here as the class is being generated, not loaded.
20+
'message' => '#^Parameter \#4 \$extends of class Laminas\\\\Code\\\\Generator\\\\ClassGenerator constructor expects class\-string\|null, string given\.$#',
21+
'identifier' => 'argument.type',
22+
'count' => 1,
23+
'path' => __DIR__ . '/src/Proxy/ClassProxyGenerator.php',
24+
];
25+
$ignoreErrors[] = [
26+
// Same reason as above: the introduced interface names are class names that will exist at runtime
27+
// but cannot be proven as class-string at static analysis time in a code generation context.
28+
'message' => '#^Parameter \#5 \$interfaces of class Laminas\\\\Code\\\\Generator\\\\ClassGenerator constructor expects array\<class\-string\>, array\<string\> given\.$#',
29+
'identifier' => 'argument.type',
30+
'count' => 1,
31+
'path' => __DIR__ . '/src/Proxy/ClassProxyGenerator.php',
32+
];
33+
$ignoreErrors[] = [
34+
// The __joinPoints property is generated by code generation at weave time and populated with
35+
// the proper array<array<array<Advice>>> structure. ReflectionProperty::getValue() returns mixed
36+
// because PHP reflection cannot know the type of dynamically generated properties.
37+
'message' => '#^Parameter \#1 \$classAdvices of static method Go\\\\Proxy\\\\ClassProxyGenerator::wrapWithJoinPoints\(\) expects array\<array\<array\<Go\\\\Aop\\\\Advice\>\>\>, mixed given\.$#',
38+
'identifier' => 'argument.type',
39+
'count' => 1,
40+
'path' => __DIR__ . '/src/Proxy/ClassProxyGenerator.php',
41+
];
1642

1743
return ['parameters' => ['ignoreErrors' => $ignoreErrors]];

phpstan.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ includes:
22
- phpstan-baseline.php
33

44
parameters:
5-
level: 4
5+
level: 9
66
paths:
77
- src

src/Bridge/Doctrine/MetadataLoadInterceptor.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,23 +68,28 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $args): void
6868
/**
6969
* Remove fields in Go! AOP proxied class metadata that are inherited
7070
* from traits.
71+
*
72+
* @param ClassMetadata<object> $metadata
7173
*/
7274
private function removeMappingsFromTraits(ClassMetadata $metadata): void
7375
{
7476
$traits = $this->getTraits($metadata->name);
7577

7678
foreach ($traits as $trait) {
79+
if (!trait_exists($trait)) {
80+
continue;
81+
}
7782
$trait = new ReflectionClass($trait);
7883

7984
foreach ($trait->getProperties() as $property) {
8085
$name = $property->getName();
8186

8287
if (isset($metadata->fieldMappings[$name])) {
83-
$mapping = $metadata->fieldMappings[$name];
88+
$columnName = $metadata->getColumnName($name);
8489

8590
unset(
8691
$metadata->fieldMappings[$name],
87-
$metadata->fieldNames[$mapping['columnName']],
92+
$metadata->fieldNames[$columnName],
8893
$metadata->columnNames[$name]
8994
);
9095
}
@@ -101,6 +106,7 @@ private function removeMappingsFromTraits(ClassMetadata $metadata): void
101106
* @param class-string $className FQCN
102107
* @param bool $autoload Weather to autoload class.
103108
*
109+
* @return string[]
104110
* @throws InvalidArgumentException
105111
* @throws RuntimeException
106112
*/
@@ -113,22 +119,22 @@ private function getTraits(string $className, bool $autoload = true): array
113119
$traits = [];
114120
// Get traits of all parent classes
115121
do {
116-
$traits = array_merge(class_uses($className, $autoload), $traits);
122+
$traits = array_merge(class_uses($className, $autoload) ?: [], $traits);
117123
$className = get_parent_class($className);
118124
} while ($className);
119125

120126
$traitsToSearch = $traits;
121127

122128
while (count($traitsToSearch) > 0) {
123-
$newTraits = class_uses(array_pop($traitsToSearch), $autoload);
129+
$newTraits = class_uses(array_pop($traitsToSearch), $autoload) ?: [];
124130
$traits = array_merge($newTraits, $traits);
125131
$traitsToSearch = array_merge($newTraits, $traitsToSearch);
126132
}
127133

128134
foreach ($traits as $trait => $same) {
129-
$traits = array_merge(class_uses($trait, $autoload), $traits);
135+
$traits = array_merge(class_uses($trait, $autoload) ?: [], $traits);
130136
}
131137

132-
return array_unique(array_map(fn($fqcn) => ltrim($fqcn, '\\'), $traits));
138+
return array_values(array_unique(array_map(fn(string $fqcn) => ltrim($fqcn, '\\'), $traits)));
133139
}
134140
}

src/Console/Command/BaseAspectCommand.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,11 @@ protected function configure(): void
4949
protected function loadAspectKernel(InputInterface $input, OutputInterface $output): void
5050
{
5151
$loader = $input->getArgument('loader');
52-
$path = stream_resolve_include_path($loader);
53-
if (!is_readable($path)) {
52+
if (!is_string($loader)) {
53+
throw new InvalidArgumentException('Loader argument must be a string');
54+
}
55+
$path = stream_resolve_include_path($loader);
56+
if ($path === false || !is_readable($path)) {
5457
throw new InvalidArgumentException("Invalid loader path: {$loader}");
5558
}
5659

src/Console/Command/DebugAdvisorCommand.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ private function showAdvisorInformation(SymfonyStyle $io, string $advisorId): vo
135135
}
136136
}
137137

138+
/**
139+
* @param ReflectionClass<object> $reflectionClass
140+
* @param array<string, array<string, mixed>> $advices
141+
*/
138142
private function writeInfoAboutAdvices(SymfonyStyle $io, ReflectionClass $reflectionClass, array $advices): void
139143
{
140144
$className = $reflectionClass->getName();

src/Console/Command/DebugAspectCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,6 @@ private function getPrettyText(string $comment): string
131131
{
132132
$text = preg_replace('|^\s*/?\*+/?|m', '', $comment);
133133

134-
return $text;
134+
return $text ?? $comment;
135135
}
136136
}

src/Console/Command/DebugWeavingCommand.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7777
continue;
7878
}
7979

80-
if (isset($proxies[$path]) && $proxies[$path] !== $content) {
81-
$io->error(sprintf('Proxy on path "%s" is weaved differnlty on second "warmup" pass.', $path));
80+
if ($proxies[$path] !== $content) {
81+
$io->error(sprintf('Proxy on path "%s" is weaved differently on second "warmup" pass.', $path));
8282
$errors++;
8383
continue;
8484
}
@@ -99,6 +99,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
9999

100100
/**
101101
* Gets Go! AOP generated proxy classes (paths and their contents) from the cache.
102+
*
103+
* @return array<string, string>
102104
*/
103105
private function getProxies(CachePathManager $cachePathManager): array
104106
{
@@ -118,7 +120,10 @@ private function getProxies(CachePathManager $cachePathManager): array
118120
*/
119121
foreach ($iterator as $splFileInfo) {
120122
if ($splFileInfo->isFile()) {
121-
$proxies[$splFileInfo->getPathname()] = file_get_contents($splFileInfo->getPathname());
123+
$content = file_get_contents($splFileInfo->getPathname());
124+
if ($content !== false) {
125+
$proxies[$splFileInfo->getPathname()] = $content;
126+
}
122127
}
123128
}
124129

src/Core/AbstractAspectLoaderExtension.php

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,10 @@ private function makeLexicalAnalyze(
7676
$message,
7777
$pointcutExpression,
7878
(isset($reflection->class) ? $reflection->class . '->' : '') . $reflection->name,
79-
method_exists($reflection, 'getFileName')
80-
? $reflection->getFileName()
81-
: $reflection->getDeclaringClass()->getFileName(),
82-
method_exists($reflection, 'getStartLine')
83-
? $reflection->getStartLine()
84-
: 0
79+
$reflection instanceof ReflectionProperty
80+
? (string) $reflection->getDeclaringClass()->getFileName()
81+
: (string) $reflection->getFileName(),
82+
$reflection instanceof ReflectionProperty ? 0 : (int) $reflection->getStartLine()
8583
);
8684
throw new UnexpectedValueException($message, 0, $e);
8785
}
@@ -113,12 +111,10 @@ private function parseTokenStream(
113111
$token->getValue(),
114112
$pointcutExpression,
115113
(isset($reflection->class) ? $reflection->class . '->' : '') . $reflection->name,
116-
method_exists($reflection, 'getFileName')
117-
? $reflection->getFileName()
118-
: $reflection->getDeclaringClass()->getFileName(),
119-
method_exists($reflection, 'getStartLine')
120-
? $reflection->getStartLine()
121-
: 0,
114+
$reflection instanceof ReflectionProperty
115+
? (string) $reflection->getDeclaringClass()->getFileName()
116+
: (string) $reflection->getFileName(),
117+
$reflection instanceof ReflectionProperty ? 0 : (int) $reflection->getStartLine(),
122118
implode(', ', $e->getExpected())
123119
);
124120
throw new UnexpectedValueException($message, 0, $e);

0 commit comments

Comments
 (0)