12
12
use PHPStan \Rules \RuleErrorBuilder ;
13
13
use PHPStan \TrinaryLogic ;
14
14
use PHPStan \Type \MixedType ;
15
+ use PHPStan \Type \Type ;
15
16
use PHPStan \Type \TypehintHelper ;
16
17
use PHPStan \Type \VerbosityLevel ;
17
18
use PHPStan \Type \VoidType ;
@@ -70,22 +71,22 @@ public function processNode(Node $node, Scope $scope): array
70
71
continue ;
71
72
}
72
73
73
- $ returnTypeCompatibility = $ this ->checkReturnTypeCompatibility ($ parameters , $ parentParameters );
74
+ [ $ returnTypeCompatibility, $ returnType , $ parentReturnType ] = $ this ->checkReturnTypeCompatibility ($ parameters , $ parentParameters );
74
75
if ($ returnTypeCompatibility ->no () || (!$ returnTypeCompatibility ->yes () && $ this ->reportMaybes )) {
75
76
$ errors [] = RuleErrorBuilder::message (sprintf (
76
77
'Return type (%s) of method %s::%s() should be %s with return type (%s) of method %s::%s() ' ,
77
- $ parameters -> getPhpDocReturnType () ->describe (VerbosityLevel::value ()),
78
+ $ returnType ->describe (VerbosityLevel::value ()),
78
79
$ method ->getDeclaringClass ()->getDisplayName (),
79
80
$ method ->getName (),
80
81
$ returnTypeCompatibility ->no () ? 'compatible ' : 'covariant ' ,
81
- $ parentParameters -> getPhpDocReturnType () ->describe (VerbosityLevel::value ()),
82
+ $ parentReturnType ->describe (VerbosityLevel::value ()),
82
83
$ parentMethod ->getDeclaringClass ()->getDisplayName (),
83
84
$ parentMethod ->getName ()
84
85
))->build ();
85
86
}
86
87
87
88
$ parameterResults = $ this ->checkParameterTypeCompatibility ($ parameters ->getParameters (), $ parentParameters ->getParameters ());
88
- foreach ($ parameterResults as $ parameterIndex => $ parameterResult ) {
89
+ foreach ($ parameterResults as $ parameterIndex => [ $ parameterResult, $ parameterType , $ parentParameterType ] ) {
89
90
if ($ parameterResult ->yes ()) {
90
91
continue ;
91
92
}
@@ -98,12 +99,12 @@ public function processNode(Node $node, Scope $scope): array
98
99
'Parameter #%d $%s (%s) of method %s::%s() should be %s with parameter $%s (%s) of method %s::%s() ' ,
99
100
$ parameterIndex + 1 ,
100
101
$ parameter ->getName (),
101
- $ parameter -> getType () ->describe (VerbosityLevel::value ()),
102
+ $ parameterType ->describe (VerbosityLevel::value ()),
102
103
$ method ->getDeclaringClass ()->getDisplayName (),
103
104
$ method ->getName (),
104
105
$ parameterResult ->no () ? 'compatible ' : 'contravariant ' ,
105
106
$ parentParameter ->getName (),
106
- $ parentParameter -> getType () ->describe (VerbosityLevel::value ()),
107
+ $ parentParameterType ->describe (VerbosityLevel::value ()),
107
108
$ parentMethod ->getDeclaringClass ()->getDisplayName (),
108
109
$ parentMethod ->getName ()
109
110
))->build ();
@@ -141,10 +142,15 @@ private function collectParentMethods(string $methodName, ClassReflection $class
141
142
return $ parentMethods ;
142
143
}
143
144
145
+ /**
146
+ * @param ParametersAcceptorWithPhpDocs $currentVariant
147
+ * @param ParametersAcceptorWithPhpDocs $parentVariant
148
+ * @return array{TrinaryLogic, Type, Type}
149
+ */
144
150
private function checkReturnTypeCompatibility (
145
151
ParametersAcceptorWithPhpDocs $ currentVariant ,
146
152
ParametersAcceptorWithPhpDocs $ parentVariant
147
- ): TrinaryLogic
153
+ ): array
148
154
{
149
155
$ returnType = TypehintHelper::decideType (
150
156
$ currentVariant ->getNativeReturnType (),
@@ -156,21 +162,21 @@ private function checkReturnTypeCompatibility(
156
162
);
157
163
// Allow adding `void` return type hints when the parent defines no return type
158
164
if ($ returnType instanceof VoidType && $ parentReturnType instanceof MixedType) {
159
- return TrinaryLogic::createYes ();
165
+ return [ TrinaryLogic::createYes (), $ returnType , $ parentReturnType ] ;
160
166
}
161
167
162
168
// We can return anything
163
169
if ($ parentReturnType instanceof VoidType) {
164
- return TrinaryLogic::createYes ();
170
+ return [ TrinaryLogic::createYes (), $ returnType , $ parentReturnType ] ;
165
171
}
166
172
167
- return $ parentReturnType ->isSuperTypeOf ($ returnType );
173
+ return [ $ parentReturnType ->isSuperTypeOf ($ returnType ), $ returnType , $ parentReturnType ] ;
168
174
}
169
175
170
176
/**
171
177
* @param \PHPStan\Reflection\ParameterReflectionWithPhpDocs[] $parameters
172
178
* @param \PHPStan\Reflection\ParameterReflectionWithPhpDocs[] $parentParameters
173
- * @return array<int, TrinaryLogic>
179
+ * @return array<int, array{ TrinaryLogic, Type, Type} >
174
180
*/
175
181
private function checkParameterTypeCompatibility (
176
182
array $ parameters ,
@@ -193,7 +199,7 @@ private function checkParameterTypeCompatibility(
193
199
$ parentParameter ->getPhpDocType ()
194
200
);
195
201
196
- $ parameterResults [] = $ parameterType ->isSuperTypeOf ($ parentParameterType );
202
+ $ parameterResults [] = [ $ parameterType ->isSuperTypeOf ($ parentParameterType ), $ parameterType , $ parentParameterType ] ;
197
203
}
198
204
199
205
return $ parameterResults ;
0 commit comments