Skip to content

Commit c819778

Browse files
committed
Add support for ObjectStorage::next() and current()
Add some very basic support for ObjectStorage methods next() and current(). This one could be very unstable but works in my usecase.
1 parent c10daa4 commit c819778

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

extension.neon

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,7 @@ services:
1515
class: SaschaEgerer\PhpstanTypo3\Type\QueryInterfaceDynamicReturnTypeExtension
1616
tags:
1717
- phpstan.broker.dynamicMethodReturnTypeExtension
18+
-
19+
class: SaschaEgerer\PhpstanTypo3\Type\ObjectStorageDynamicReturnTypeExtension
20+
tags:
21+
- phpstan.broker.dynamicMethodReturnTypeExtension
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace SaschaEgerer\PhpstanTypo3\Type;
5+
6+
use PhpParser\Node\Expr\MethodCall;
7+
use PHPStan\Analyser\Scope;
8+
use PHPStan\Type\DynamicMethodReturnTypeExtension;
9+
use PHPStan\Type\ObjectType;
10+
use PHPStan\Type\Type;
11+
use PHPStan\Reflection\MethodReflection;
12+
use PHPStan\Type\TypeCombinator;
13+
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
14+
15+
/**
16+
* Add support for ObjectStorage methods "current" and "next".
17+
* The target type is fetched by getting the propertyName, calculated by the getter,
18+
* and then getting the property annotation of the class.
19+
* This one could be very unstable but works for "my" current usecase.
20+
*/
21+
class ObjectStorageDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
22+
{
23+
public function getClass(): string
24+
{
25+
return ObjectStorage::class;
26+
}
27+
28+
public function isMethodSupported(
29+
MethodReflection $methodReflection
30+
): bool {
31+
return in_array($methodReflection->getName(), ['current', 'next']);
32+
}
33+
34+
public function getTypeFromMethodCall(
35+
MethodReflection $methodReflection,
36+
MethodCall $methodCall,
37+
Scope $scope
38+
): Type {
39+
if (strpos($methodCall->var->name, 'get') === 0) {
40+
$propertyName = lcfirst(substr($methodCall->var->name, 3));
41+
42+
$class = $scope->getClassReflection();
43+
if ($class->hasProperty($propertyName)) {
44+
preg_match(
45+
'/@var\\ \\\\TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\ObjectStorage<(.*)>/',
46+
$class->getNativeReflection()->getProperty($propertyName)->getDocComment(),
47+
$phpDocVarAnnotations
48+
);
49+
if (!empty($phpDocVarAnnotations[1])) {
50+
return TypeCombinator::addNull(new ObjectType($phpDocVarAnnotations[1]));
51+
}
52+
}
53+
}
54+
55+
return $methodReflection->getReturnType();
56+
}
57+
}

0 commit comments

Comments
 (0)