@@ -147,6 +147,28 @@ public function assertFileAsserts(
147147 $ actual ,
148148 $ failureMessage ,
149149 );
150+ } elseif ($ assertType === 'superType ' ) {
151+ $ expected = $ args [0 ];
152+ $ actual = $ args [1 ];
153+ $ isCorrect = $ args [2 ];
154+
155+ $ failureMessage = sprintf ('Expected subtype of %s, got type %s in %s on line %d. ' , $ expected , $ actual , $ file , $ args [3 ]);
156+
157+ $ delayedErrors = $ args [4 ] ?? [];
158+ if (count ($ delayedErrors ) > 0 ) {
159+ $ failureMessage .= sprintf (
160+ "\n\nThis failure might be reported because of the following misconfiguration %s: \n\n" ,
161+ count ($ delayedErrors ) === 1 ? 'issue ' : 'issues ' ,
162+ );
163+ foreach ($ delayedErrors as $ delayedError ) {
164+ $ failureMessage .= sprintf ("* %s \n" , $ delayedError );
165+ }
166+ }
167+
168+ $ this ->assertTrue (
169+ $ isCorrect ,
170+ $ failureMessage ,
171+ );
150172 } elseif ($ assertType === 'variableCertainty ' ) {
151173 $ expectedCertainty = $ args [0 ];
152174 $ actualCertainty = $ args [1 ];
@@ -214,7 +236,7 @@ public static function gatherAssertTypes(string $file): array
214236 }
215237
216238 $ functionName = $ nameNode ->toString ();
217- if (in_array (strtolower ($ functionName ), ['asserttype ' , 'assertnativetype ' , 'assertvariablecertainty ' ], true )) {
239+ if (in_array (strtolower ($ functionName ), ['asserttype ' , 'assertnativetype ' , 'assertsupertype ' , ' assertvariablecertainty ' ], true )) {
218240 self ::fail (sprintf (
219241 'Missing use statement for %s() in %s on line %d. ' ,
220242 $ functionName ,
@@ -246,6 +268,18 @@ public static function gatherAssertTypes(string $file): array
246268
247269 $ actualType = $ scope ->getNativeType ($ node ->getArgs ()[1 ]->value );
248270 $ assert = ['type ' , $ file , $ expectedType ->getValue (), $ actualType ->describe (VerbosityLevel::precise ()), $ node ->getStartLine ()];
271+ } elseif ($ functionName === 'PHPStan \\Testing \\assertSuperType ' ) {
272+ $ expectedType = $ scope ->getType ($ node ->getArgs ()[0 ]->value );
273+ if (!$ expectedType instanceof ConstantScalarType) {
274+ self ::fail (sprintf (
275+ 'Expected super type must be a literal string, %s given in %s on line %d. ' ,
276+ $ expectedType ->describe (VerbosityLevel::precise ()),
277+ $ relativePathHelper ->getRelativePath ($ file ),
278+ $ node ->getStartLine (),
279+ ));
280+ }
281+ $ actualType = $ scope ->getType ($ node ->getArgs ()[1 ]->value );
282+ $ assert = ['superType ' , $ file , $ expectedType ->getValue (), $ actualType ->describe (VerbosityLevel::precise ()), $ expectedType ->isSuperTypeOf ($ actualType )->yes (), $ node ->getStartLine ()];
249283 } elseif ($ functionName === 'PHPStan \\Testing \\assertVariableCertainty ' ) {
250284 $ certainty = $ node ->getArgs ()[0 ]->value ;
251285 if (!$ certainty instanceof StaticCall) {
@@ -284,6 +318,7 @@ public static function gatherAssertTypes(string $file): array
284318 $ assertFunctions = [
285319 'assertType ' => 'PHPStan \\Testing \\assertType ' ,
286320 'assertNativeType ' => 'PHPStan \\Testing \\assertNativeType ' ,
321+ 'assertSuperType ' => 'PHPStan \\Testing \\assertSuperType ' ,
287322 'assertVariableCertainty ' => 'PHPStan \\Testing \\assertVariableCertainty ' ,
288323 ];
289324 foreach ($ assertFunctions as $ assertFn => $ fqFunctionName ) {
0 commit comments