Skip to content

Commit 9a7f0e0

Browse files
committed
Fix assertSuperType logic
1 parent dc76f12 commit 9a7f0e0

File tree

5 files changed

+46
-4
lines changed

5 files changed

+46
-4
lines changed

phpstan-baseline.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ parameters:
780780
-
781781
message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#'
782782
identifier: phpstanApi.instanceofType
783-
count: 3
783+
count: 2
784784
path: src/Testing/TypeInferenceTestCase.php
785785

786786
-

src/Testing/TypeInferenceTestCase.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use PHPStan\Php\PhpVersion;
1818
use PHPStan\PhpDoc\PhpDocInheritanceResolver;
1919
use PHPStan\PhpDoc\StubPhpDocProvider;
20+
use PHPStan\PhpDoc\TypeStringResolver;
2021
use PHPStan\Reflection\AttributeReflectionFactory;
2122
use PHPStan\Reflection\Deprecation\DeprecationProvider;
2223
use PHPStan\Reflection\InitializerExprTypeResolver;
@@ -203,12 +204,13 @@ public static function gatherAssertTypes(string $file): array
203204

204205
$relativePathHelper = new SystemAgnosticSimpleRelativePathHelper($fileHelper);
205206
$reflectionProvider = self::getContainer()->getByType(ReflectionProvider::class);
207+
$typeStringResolver = self::getContainer()->getByType(TypeStringResolver::class);
206208

207209
$file = $fileHelper->normalizePath($file);
208210

209211
$asserts = [];
210212
$delayedErrors = [];
211-
self::processFile($file, static function (Node $node, Scope $scope) use (&$asserts, &$delayedErrors, $file, $relativePathHelper, $reflectionProvider): void {
213+
self::processFile($file, static function (Node $node, Scope $scope) use (&$asserts, &$delayedErrors, $file, $relativePathHelper, $reflectionProvider, $typeStringResolver): void {
212214
if ($node instanceof InClassNode) {
213215
if (!$reflectionProvider->hasClass($node->getClassReflection()->getName())) {
214216
$delayedErrors[] = sprintf(
@@ -270,16 +272,20 @@ public static function gatherAssertTypes(string $file): array
270272
$assert = ['type', $file, $expectedType->getValue(), $actualType->describe(VerbosityLevel::precise()), $node->getStartLine()];
271273
} elseif ($functionName === 'PHPStan\\Testing\\assertSuperType') {
272274
$expectedType = $scope->getType($node->getArgs()[0]->value);
273-
if (!$expectedType instanceof ConstantScalarType) {
275+
$expectedTypeStrings = $expectedType->getConstantStrings();
276+
if (count($expectedTypeStrings) !== 1) {
274277
self::fail(sprintf(
275278
'Expected super type must be a literal string, %s given in %s on line %d.',
276279
$expectedType->describe(VerbosityLevel::precise()),
277280
$relativePathHelper->getRelativePath($file),
278281
$node->getStartLine(),
279282
));
280283
}
284+
281285
$actualType = $scope->getType($node->getArgs()[1]->value);
282-
$assert = ['superType', $file, $expectedType->getValue(), $actualType->describe(VerbosityLevel::precise()), $expectedType->isSuperTypeOf($actualType)->yes(), $node->getStartLine()];
286+
$isCorrect = $typeStringResolver->resolve($expectedTypeStrings[0]->getValue())->isSuperTypeOf($actualType)->yes();
287+
288+
$assert = ['superType', $file, $expectedTypeStrings[0]->getValue(), $actualType->describe(VerbosityLevel::precise()), $isCorrect, $node->getStartLine()];
283289
} elseif ($functionName === 'PHPStan\\Testing\\assertVariableCertainty') {
284290
$certainty = $node->getArgs()[0]->value;
285291
if (!$certainty instanceof StaticCall) {

tests/PHPStan/Testing/TypeInferenceTestCaseTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,25 @@ public function testVariableOrOffsetDescription(): void
121121
$this->assertSame("offset 'email'", $offsetAssert[4]);
122122
}
123123

124+
public function testSuperType(): void
125+
{
126+
foreach (self::gatherAssertTypes(__DIR__ . '/data/assert-super-type.php') as $data) {
127+
$this->assertFileAsserts(...$data);
128+
}
129+
}
130+
131+
public static function dataSuperTypeFailed(): array
132+
{
133+
return self::gatherAssertTypes(__DIR__ . '/data/assert-super-type-failed.php');
134+
}
135+
136+
#[DataProvider('dataSuperTypeFailed')]
137+
public function testSuperTypeFailed(...$data): void
138+
{
139+
$this->expectException(AssertionFailedError::class);
140+
$this->assertFileAsserts(...$data);
141+
}
142+
124143
public function testNonexistentClassInAnalysedFile(): void
125144
{
126145
foreach (self::gatherAssertTypes(__DIR__ . '/../../notAutoloaded/nonexistentClasses.php') as $data) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
use function PHPStan\Testing\assertSuperType;
4+
5+
$a = 'Alice';
6+
7+
assertSuperType('never', $a);
8+
assertSuperType('bool', $a);
9+
assertSuperType('"Bob"', $a);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
use function PHPStan\Testing\assertSuperType;
4+
5+
$a = 'Alice';
6+
7+
assertSuperType('string', $a);
8+
assertSuperType('mixed', $a);

0 commit comments

Comments
 (0)