2
2
3
3
namespace mglaman \PHPStanDrupal \Type ;
4
4
5
- use mglaman \PHPStanDrupal \Drupal \DrupalServiceDefinition ;
6
5
use mglaman \PHPStanDrupal \Drupal \ServiceMap ;
7
- use PhpParser \Node ;
8
- use PhpParser \Node \Expr \ClassConstFetch ;
9
6
use PhpParser \Node \Expr \MethodCall ;
10
- use PhpParser \Node \Name \FullyQualified ;
11
- use PhpParser \Node \Scalar \String_ ;
12
- use PhpParser \Node \VariadicPlaceholder ;
13
7
use PHPStan \Analyser \Scope ;
14
8
use PHPStan \Reflection \MethodReflection ;
15
9
use PHPStan \Reflection \ParametersAcceptorSelector ;
16
- use PHPStan \ShouldNotHappenException ;
17
10
use PHPStan \Type \Constant \ConstantBooleanType ;
18
11
use PHPStan \Type \DynamicMethodReturnTypeExtension ;
12
+ use PHPStan \Type \Type ;
13
+ use PHPStan \Type \TypeCombinator ;
19
14
use Psr \Container \ContainerInterface ;
20
15
21
16
class ContainerDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
22
17
{
23
18
/**
24
19
* @var ServiceMap
25
20
*/
26
- private $ serviceMap ;
21
+ private ServiceMap $ serviceMap ;
27
22
28
23
public function __construct (ServiceMap $ serviceMap )
29
24
{
@@ -44,49 +39,26 @@ public function getTypeFromMethodCall(
44
39
MethodReflection $ methodReflection ,
45
40
MethodCall $ methodCall ,
46
41
Scope $ scope
47
- ): \ PHPStan \ Type \ Type {
42
+ ): Type {
48
43
$ returnType = ParametersAcceptorSelector::selectSingle ($ methodReflection ->getVariants ())->getReturnType ();
49
- if (!isset ($ methodCall ->args [0 ])) {
44
+ $ args = $ methodCall ->getArgs ();
45
+ if (count ($ args ) !== 1 ) {
50
46
return $ returnType ;
51
47
}
52
48
53
- $ arg1 = $ methodCall ->args [0 ];
54
- if ($ arg1 instanceof VariadicPlaceholder) {
55
- throw new ShouldNotHappenException ();
56
- }
57
- $ arg1 = $ arg1 ->value ;
58
-
59
- $ serviceId = $ this ->getServiceId ($ arg1 );
60
- if ($ serviceId === null ) {
61
- return $ returnType ;
62
- }
49
+ $ methodName = $ methodReflection ->getName ();
50
+ $ types = [];
51
+ $ argType = $ scope ->getType ($ args [0 ]->value );
63
52
64
- if ($ methodReflection ->getName () === 'get ' ) {
53
+ foreach ($ argType ->getConstantStrings () as $ constantStringType ) {
54
+ $ serviceId = $ constantStringType ->getValue ();
65
55
$ service = $ this ->serviceMap ->getService ($ serviceId );
66
- if ($ service instanceof DrupalServiceDefinition) {
67
- return $ service ->getType ();
56
+ if ($ methodName === 'get ' ) {
57
+ $ types [] = $ service !== null ? $ service ->getType () : $ returnType ;
58
+ } elseif ($ methodName === 'has ' ) {
59
+ $ types [] = new ConstantBooleanType ($ service !== null );
68
60
}
69
- return $ returnType ;
70
- }
71
-
72
- if ($ methodReflection ->getName () === 'has ' ) {
73
- return new ConstantBooleanType ($ this ->serviceMap ->getService ($ serviceId ) instanceof DrupalServiceDefinition);
74
61
}
75
-
76
- throw new ShouldNotHappenException ();
77
- }
78
-
79
- protected function getServiceId (Node $ arg1 ): ?string
80
- {
81
- if ($ arg1 instanceof String_) {
82
- // @todo determine what these types are.
83
- return $ arg1 ->value ;
84
- }
85
-
86
- if ($ arg1 instanceof ClassConstFetch && $ arg1 ->class instanceof FullyQualified) {
87
- return (string ) $ arg1 ->class ;
88
- }
89
-
90
- return null ;
62
+ return TypeCombinator::union (...$ types );
91
63
}
92
64
}
0 commit comments