Skip to content

Commit 3af8630

Browse files
committed
TypeInfereceTest - allow 3rd parties same modern style of type inference testing as in NodeScopeResolverTest
1 parent 93baca0 commit 3af8630

File tree

2 files changed

+112
-98
lines changed

2 files changed

+112
-98
lines changed

src/Testing/TypeInferenceTest.php

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
namespace PHPStan\Testing;
44

5+
use PhpParser\Node;
6+
use PhpParser\Node\Expr\StaticCall;
7+
use PhpParser\Node\Name;
58
use PHPStan\Analyser\DirectScopeFactory;
69
use PHPStan\Analyser\NodeScopeResolver;
10+
use PHPStan\Analyser\Scope;
711
use PHPStan\Analyser\ScopeContext;
812
use PHPStan\Broker\AnonymousClassNameHelper;
913
use PHPStan\Broker\Broker;
@@ -15,9 +19,11 @@
1519
use PHPStan\PhpDoc\PhpDocNodeResolver;
1620
use PHPStan\PhpDoc\PhpDocStringResolver;
1721
use PHPStan\Reflection\ReflectionProvider\DirectReflectionProviderProvider;
22+
use PHPStan\TrinaryLogic;
1823
use PHPStan\Type\DynamicMethodReturnTypeExtension;
1924
use PHPStan\Type\DynamicStaticMethodReturnTypeExtension;
2025
use PHPStan\Type\FileTypeMapper;
26+
use PHPStan\Type\VerbosityLevel;
2127

2228
abstract class TypeInferenceTest extends \PHPStan\Testing\TestCase
2329
{
@@ -97,6 +103,111 @@ public function processFile(
97103
);
98104
}
99105

106+
/**
107+
* @param string $assertType
108+
* @param string $file
109+
* @param mixed ...$args
110+
*/
111+
public function assertFileAsserts(
112+
string $assertType,
113+
string $file,
114+
...$args
115+
): void
116+
{
117+
if ($assertType === 'type') {
118+
$expectedType = $args[0];
119+
$expected = $expectedType->getValue();
120+
$actualType = $args[1];
121+
$actual = $actualType->describe(VerbosityLevel::precise());
122+
$this->assertSame(
123+
$expected,
124+
$actual,
125+
sprintf('Expected type %s, got type %s in %s on line %d.', $expected, $actual, $file, $args[2])
126+
);
127+
} elseif ($assertType === 'variableCertainty') {
128+
$expectedCertainty = $args[0];
129+
$actualCertainty = $args[1];
130+
$variableName = $args[2];
131+
$this->assertTrue(
132+
$expectedCertainty->equals($actualCertainty),
133+
sprintf('Expected %s, actual certainty of variable $%s is %s', $expectedCertainty->describe(), $variableName, $actualCertainty->describe())
134+
);
135+
}
136+
}
137+
138+
/**
139+
* @param string $file
140+
* @return array<string, mixed[]>
141+
*/
142+
public function gatherAssertTypes(string $file): array
143+
{
144+
$asserts = [];
145+
$this->processFile($file, function (Node $node, Scope $scope) use (&$asserts, $file): void {
146+
if (!$node instanceof Node\Expr\FuncCall) {
147+
return;
148+
}
149+
150+
$nameNode = $node->name;
151+
if (!$nameNode instanceof Name) {
152+
return;
153+
}
154+
155+
$functionName = $nameNode->toString();
156+
if ($functionName === 'PHPStan\\Analyser\\assertType') {
157+
$expectedType = $scope->getType($node->args[0]->value);
158+
$actualType = $scope->getType($node->args[1]->value);
159+
$assert = ['type', $file, $expectedType, $actualType, $node->getLine()];
160+
} elseif ($functionName === 'PHPStan\\Analyser\\assertNativeType') {
161+
$expectedType = $scope->getNativeType($node->args[0]->value);
162+
$actualType = $scope->getNativeType($node->args[1]->value);
163+
$assert = ['type', $file, $expectedType, $actualType, $node->getLine()];
164+
} elseif ($functionName === 'PHPStan\\Analyser\\assertVariableCertainty') {
165+
$certainty = $node->args[0]->value;
166+
if (!$certainty instanceof StaticCall) {
167+
$this->fail(sprintf('First argument of %s() must be TrinaryLogic call', $functionName));
168+
}
169+
if (!$certainty->class instanceof Node\Name) {
170+
$this->fail(sprintf('ERROR: Invalid TrinaryLogic call.'));
171+
}
172+
173+
if ($certainty->class->toString() !== 'PHPStan\\TrinaryLogic') {
174+
$this->fail(sprintf('ERROR: Invalid TrinaryLogic call.'));
175+
}
176+
177+
if (!$certainty->name instanceof Node\Identifier) {
178+
$this->fail(sprintf('ERROR: Invalid TrinaryLogic call.'));
179+
}
180+
181+
// @phpstan-ignore-next-line
182+
$expectedertaintyValue = TrinaryLogic::{$certainty->name->toString()}();
183+
$variable = $node->args[1]->value;
184+
if (!$variable instanceof Node\Expr\Variable) {
185+
$this->fail(sprintf('ERROR: Invalid assertVariableCertainty call.'));
186+
}
187+
if (!is_string($variable->name)) {
188+
$this->fail(sprintf('ERROR: Invalid assertVariableCertainty call.'));
189+
}
190+
191+
$actualCertaintyValue = $scope->hasVariableType($variable->name);
192+
$assert = ['variableCertainty', $file, $expectedertaintyValue, $actualCertaintyValue, $variable->name];
193+
} else {
194+
return;
195+
}
196+
197+
if (count($node->args) !== 2) {
198+
$this->fail(sprintf(
199+
'ERROR: Wrong %s() call on line %d.',
200+
$functionName,
201+
$node->getLine()
202+
));
203+
}
204+
205+
$asserts[$file . ':' . $node->getLine()] = $assert;
206+
});
207+
208+
return $asserts;
209+
}
210+
100211
/** @return string[] */
101212
protected function getAdditionalAnalysedFiles(): array
102213
{

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 1 addition & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@
22

33
namespace PHPStan\Analyser;
44

5-
use PhpParser\Node;
6-
use PhpParser\Node\Expr\StaticCall;
7-
use PhpParser\Node\Name;
85
use PHPStan\Testing\TypeInferenceTest;
9-
use PHPStan\TrinaryLogic;
10-
use PHPStan\Type\VerbosityLevel;
11-
use const PHP_VERSION_ID;
126

137
class NodeScopeResolverTest extends TypeInferenceTest
148
{
@@ -399,98 +393,7 @@ public function testFileAsserts(
399393
...$args
400394
): void
401395
{
402-
if ($assertType === 'type') {
403-
$expectedType = $args[0];
404-
$expected = $expectedType->getValue();
405-
$actualType = $args[1];
406-
$actual = $actualType->describe(VerbosityLevel::precise());
407-
$this->assertSame(
408-
$expected,
409-
$actual,
410-
sprintf('Expected type %s, got type %s in %s on line %d.', $expected, $actual, $file, $args[2])
411-
);
412-
} elseif ($assertType === 'variableCertainty') {
413-
$expectedCertainty = $args[0];
414-
$actualCertainty = $args[1];
415-
$variableName = $args[2];
416-
$this->assertTrue(
417-
$expectedCertainty->equals($actualCertainty),
418-
sprintf('Expected %s, actual certainty of variable $%s is %s', $expectedCertainty->describe(), $variableName, $actualCertainty->describe())
419-
);
420-
}
421-
}
422-
423-
/**
424-
* @param string $file
425-
* @return array<string, mixed[]>
426-
*/
427-
private function gatherAssertTypes(string $file): array
428-
{
429-
$asserts = [];
430-
$this->processFile($file, function (Node $node, Scope $scope) use (&$asserts, $file): void {
431-
if (!$node instanceof Node\Expr\FuncCall) {
432-
return;
433-
}
434-
435-
$nameNode = $node->name;
436-
if (!$nameNode instanceof Name) {
437-
return;
438-
}
439-
440-
$functionName = $nameNode->toString();
441-
if ($functionName === 'PHPStan\\Analyser\\assertType') {
442-
$expectedType = $scope->getType($node->args[0]->value);
443-
$actualType = $scope->getType($node->args[1]->value);
444-
$assert = ['type', $file, $expectedType, $actualType, $node->getLine()];
445-
} elseif ($functionName === 'PHPStan\\Analyser\\assertNativeType') {
446-
$expectedType = $scope->getNativeType($node->args[0]->value);
447-
$actualType = $scope->getNativeType($node->args[1]->value);
448-
$assert = ['type', $file, $expectedType, $actualType, $node->getLine()];
449-
} elseif ($functionName === 'PHPStan\\Analyser\\assertVariableCertainty') {
450-
$certainty = $node->args[0]->value;
451-
if (!$certainty instanceof StaticCall) {
452-
$this->fail(sprintf('First argument of %s() must be TrinaryLogic call', $functionName));
453-
}
454-
if (!$certainty->class instanceof Node\Name) {
455-
$this->fail(sprintf('ERROR: Invalid TrinaryLogic call.'));
456-
}
457-
458-
if ($certainty->class->toString() !== 'PHPStan\\TrinaryLogic') {
459-
$this->fail(sprintf('ERROR: Invalid TrinaryLogic call.'));
460-
}
461-
462-
if (!$certainty->name instanceof Node\Identifier) {
463-
$this->fail(sprintf('ERROR: Invalid TrinaryLogic call.'));
464-
}
465-
466-
// @phpstan-ignore-next-line
467-
$expectedertaintyValue = TrinaryLogic::{$certainty->name->toString()}();
468-
$variable = $node->args[1]->value;
469-
if (!$variable instanceof Node\Expr\Variable) {
470-
$this->fail(sprintf('ERROR: Invalid assertVariableCertainty call.'));
471-
}
472-
if (!is_string($variable->name)) {
473-
$this->fail(sprintf('ERROR: Invalid assertVariableCertainty call.'));
474-
}
475-
476-
$actualCertaintyValue = $scope->hasVariableType($variable->name);
477-
$assert = ['variableCertainty', $file, $expectedertaintyValue, $actualCertaintyValue, $variable->name];
478-
} else {
479-
return;
480-
}
481-
482-
if (count($node->args) !== 2) {
483-
$this->fail(sprintf(
484-
'ERROR: Wrong %s() call on line %d.',
485-
$functionName,
486-
$node->getLine()
487-
));
488-
}
489-
490-
$asserts[$file . ':' . $node->getLine()] = $assert;
491-
});
492-
493-
return $asserts;
396+
$this->assertFileAsserts($assertType, $file, ...$args);
494397
}
495398

496399
public static function getAdditionalConfigFiles(): array

0 commit comments

Comments
 (0)