Skip to content

Commit 5018f35

Browse files
Fix assertSuperType logic
1 parent 7538546 commit 5018f35

8 files changed

+97
-5
lines changed

phpstan-baseline.neon

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,7 @@ parameters:
774774
-
775775
message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#'
776776
identifier: phpstanApi.instanceofType
777-
count: 3
777+
count: 2
778778
path: src/Testing/TypeInferenceTestCase.php
779779

780780
-
@@ -2004,7 +2004,7 @@ parameters:
20042004
-
20052005
message: '#^Access to constant on internal class PHPUnit\\Framework\\AssertionFailedError\.$#'
20062006
identifier: classConstant.internalClass
2007-
count: 1
2007+
count: 2
20082008
path: tests/PHPStan/Testing/TypeInferenceTestCaseTest.php
20092009

20102010
-

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: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ public static function dataFileAssertionFailedErrors(): iterable
3737
$fileHelper->normalizePath('tests/PHPStan/Testing/data/assert-type-missing-namespace.php'),
3838
),
3939
];
40+
yield [
41+
__DIR__ . '/data/assert-super-type-missing-namespace.php',
42+
sprintf(
43+
'Missing use statement for assertSuperType() in %s on line 6.',
44+
$fileHelper->normalizePath('tests/PHPStan/Testing/data/assert-super-type-missing-namespace.php'),
45+
),
46+
];
4047
yield [
4148
__DIR__ . '/data/assert-certainty-wrong-namespace.php',
4249
sprintf(
@@ -58,6 +65,13 @@ public static function dataFileAssertionFailedErrors(): iterable
5865
$fileHelper->normalizePath('tests/PHPStan/Testing/data/assert-type-wrong-namespace.php'),
5966
),
6067
];
68+
yield [
69+
__DIR__ . '/data/assert-super-type-wrong-namespace.php',
70+
sprintf(
71+
'Function PHPStan\Testing\assertSuperType imported with wrong namespace SomeWrong\Namespace\assertSuperType called in %s on line 8.',
72+
$fileHelper->normalizePath('tests/PHPStan/Testing/data/assert-super-type-wrong-namespace.php'),
73+
),
74+
];
6175
yield [
6276
__DIR__ . '/data/assert-certainty-case-insensitive.php',
6377
sprintf(
@@ -79,6 +93,13 @@ public static function dataFileAssertionFailedErrors(): iterable
7993
$fileHelper->normalizePath('tests/PHPStan/Testing/data/assert-type-case-insensitive.php'),
8094
),
8195
];
96+
yield [
97+
__DIR__ . '/data/assert-super-type-case-insensitive.php',
98+
sprintf(
99+
'Missing use statement for assertSuperTYPe() in %s on line 6.',
100+
$fileHelper->normalizePath('tests/PHPStan/Testing/data/assert-super-type-case-insensitive.php'),
101+
),
102+
];
82103
}
83104

84105
#[DataProvider('dataFileAssertionFailedErrors')]
@@ -100,6 +121,28 @@ public function testVariableOrOffsetDescription(): void
100121
$this->assertSame("offset 'email'", $offsetAssert[4]);
101122
}
102123

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+
/**
137+
* @param mixed ...$args
138+
*/
139+
#[DataProvider('dataSuperTypeFailed')]
140+
public function testSuperTypeFailed(...$args): void
141+
{
142+
$this->expectException(AssertionFailedError::class);
143+
$this->assertFileAsserts(...$args);
144+
}
145+
103146
public function testNonexistentClassInAnalysedFile(): void
104147
{
105148
foreach (self::gatherAssertTypes(__DIR__ . '/../../notAutoloaded/nonexistentClasses.php') as $data) {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php // lint >= 8.0
2+
3+
namespace MissingTypeCaseSensitive;
4+
5+
function doFoo(string $s) {
6+
assertSuperTYPe('string', $s);
7+
}
8+
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 // lint >= 8.0
2+
3+
namespace MissingAssertTypeNamespace;
4+
5+
function doFoo(string $s) {
6+
assertSuperType('string', $s);
7+
}
8+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php // lint >= 8.0
2+
3+
namespace WrongAssertTypeNamespace;
4+
5+
use function SomeWrong\Namespace\assertSuperType;
6+
7+
function doFoo(string $s) {
8+
assertSuperType('string', $s);
9+
}
10+
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)