Skip to content

Commit 971f58e

Browse files
committed
Reworked dynamic return type extension tests
1 parent 3f40f5c commit 971f58e

File tree

6 files changed

+288
-310
lines changed

6 files changed

+288
-310
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser;
4+
5+
use PHPStan\Testing\TypeInferenceTestCase;
6+
7+
class DynamicReturnTypeExtensionTypeInferenceTest extends TypeInferenceTestCase
8+
{
9+
10+
public function dataAsserts(): iterable
11+
{
12+
yield from $this->gatherAssertTypes(__DIR__ . '/data/dynamic-method-return-types.php');
13+
yield from $this->gatherAssertTypes(__DIR__ . '/data/dynamic-method-return-compound-types.php');
14+
}
15+
16+
/**
17+
* @dataProvider dataAsserts
18+
* @param string $assertType
19+
* @param string $file
20+
* @param mixed ...$args
21+
*/
22+
public function testAsserts(
23+
string $assertType,
24+
string $file,
25+
...$args
26+
): void
27+
{
28+
$this->assertFileAsserts($assertType, $file, ...$args);
29+
}
30+
31+
public static function getAdditionalConfigFiles(): array
32+
{
33+
return [
34+
__DIR__ . '/dynamic-return-type.neon',
35+
];
36+
}
37+
38+
}

tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php

Lines changed: 0 additions & 308 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,13 @@
44

55
use Generator;
66
use PhpParser\Node\Expr\Exit_;
7-
use PhpParser\Node\Expr\MethodCall;
8-
use PhpParser\Node\Expr\StaticCall;
97
use PHPStan\Node\VirtualNode;
10-
use PHPStan\Reflection\MethodReflection;
11-
use PHPStan\Reflection\ParametersAcceptorSelector;
128
use PHPStan\Testing\TypeInferenceTestCase;
139
use PHPStan\TrinaryLogic;
1410
use PHPStan\Type\Constant\ConstantBooleanType;
1511
use PHPStan\Type\Constant\ConstantFloatType;
1612
use PHPStan\Type\Constant\ConstantIntegerType;
1713
use PHPStan\Type\Constant\ConstantStringType;
18-
use PHPStan\Type\DynamicMethodReturnTypeExtension;
19-
use PHPStan\Type\DynamicStaticMethodReturnTypeExtension;
20-
use PHPStan\Type\ObjectType;
21-
use PHPStan\Type\ObjectWithoutClassType;
2214
use PHPStan\Type\Type;
2315
use PHPStan\Type\VerbosityLevel;
2416
use SomeNodeScopeResolverNamespace\Foo;
@@ -4234,306 +4226,6 @@ public function testSwitchTypeElimination(
42344226
);
42354227
}
42364228

4237-
public function dataDynamicMethodReturnTypeExtensions(): array
4238-
{
4239-
return [
4240-
[
4241-
'*ERROR*',
4242-
'$em->getByFoo($foo)',
4243-
],
4244-
[
4245-
'DynamicMethodReturnTypesNamespace\Entity',
4246-
'$em->getByPrimary()',
4247-
],
4248-
[
4249-
'DynamicMethodReturnTypesNamespace\Entity',
4250-
'$em->getByPrimary($foo)',
4251-
],
4252-
[
4253-
'DynamicMethodReturnTypesNamespace\Foo',
4254-
'$em->getByPrimary(DynamicMethodReturnTypesNamespace\Foo::class)',
4255-
],
4256-
[
4257-
'*ERROR*',
4258-
'$iem->getByFoo($foo)',
4259-
],
4260-
[
4261-
'DynamicMethodReturnTypesNamespace\Entity',
4262-
'$iem->getByPrimary()',
4263-
],
4264-
[
4265-
'DynamicMethodReturnTypesNamespace\Entity',
4266-
'$iem->getByPrimary($foo)',
4267-
],
4268-
[
4269-
'DynamicMethodReturnTypesNamespace\Foo',
4270-
'$iem->getByPrimary(DynamicMethodReturnTypesNamespace\Foo::class)',
4271-
],
4272-
[
4273-
'*ERROR*',
4274-
'EntityManager::getByFoo($foo)',
4275-
],
4276-
[
4277-
'DynamicMethodReturnTypesNamespace\EntityManager',
4278-
'\DynamicMethodReturnTypesNamespace\EntityManager::createManagerForEntity()',
4279-
],
4280-
[
4281-
'DynamicMethodReturnTypesNamespace\EntityManager',
4282-
'\DynamicMethodReturnTypesNamespace\EntityManager::createManagerForEntity($foo)',
4283-
],
4284-
[
4285-
'DynamicMethodReturnTypesNamespace\Foo',
4286-
'\DynamicMethodReturnTypesNamespace\EntityManager::createManagerForEntity(DynamicMethodReturnTypesNamespace\Foo::class)',
4287-
],
4288-
[
4289-
'*ERROR*',
4290-
'\DynamicMethodReturnTypesNamespace\InheritedEntityManager::getByFoo($foo)',
4291-
],
4292-
[
4293-
'DynamicMethodReturnTypesNamespace\EntityManager',
4294-
'\DynamicMethodReturnTypesNamespace\InheritedEntityManager::createManagerForEntity()',
4295-
],
4296-
[
4297-
'DynamicMethodReturnTypesNamespace\EntityManager',
4298-
'\DynamicMethodReturnTypesNamespace\InheritedEntityManager::createManagerForEntity($foo)',
4299-
],
4300-
[
4301-
'DynamicMethodReturnTypesNamespace\Foo',
4302-
'\DynamicMethodReturnTypesNamespace\InheritedEntityManager::createManagerForEntity(DynamicMethodReturnTypesNamespace\Foo::class)',
4303-
],
4304-
[
4305-
'DynamicMethodReturnTypesNamespace\Foo',
4306-
'$container[\DynamicMethodReturnTypesNamespace\Foo::class]',
4307-
],
4308-
[
4309-
'object',
4310-
'new \DynamicMethodReturnTypesNamespace\Foo()',
4311-
],
4312-
[
4313-
'object',
4314-
'new \DynamicMethodReturnTypesNamespace\FooWithoutConstructor()',
4315-
],
4316-
];
4317-
}
4318-
4319-
/**
4320-
* @dataProvider dataDynamicMethodReturnTypeExtensions
4321-
* @param string $description
4322-
* @param string $expression
4323-
*/
4324-
public function testDynamicMethodReturnTypeExtensions(
4325-
string $description,
4326-
string $expression
4327-
): void
4328-
{
4329-
$this->assertTypes(
4330-
__DIR__ . '/data/dynamic-method-return-types.php',
4331-
$description,
4332-
$expression,
4333-
[
4334-
new class() implements DynamicMethodReturnTypeExtension {
4335-
4336-
public function getClass(): string
4337-
{
4338-
return \DynamicMethodReturnTypesNamespace\EntityManager::class;
4339-
}
4340-
4341-
public function isMethodSupported(MethodReflection $methodReflection): bool
4342-
{
4343-
return in_array($methodReflection->getName(), ['getByPrimary'], true);
4344-
}
4345-
4346-
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): \PHPStan\Type\Type
4347-
{
4348-
$args = $methodCall->args;
4349-
if (count($args) === 0) {
4350-
return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
4351-
}
4352-
4353-
$arg = $args[0]->value;
4354-
if (!($arg instanceof \PhpParser\Node\Expr\ClassConstFetch)) {
4355-
return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
4356-
}
4357-
4358-
if (!($arg->class instanceof \PhpParser\Node\Name)) {
4359-
return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
4360-
}
4361-
4362-
return new ObjectType((string) $arg->class);
4363-
}
4364-
4365-
},
4366-
new class() implements DynamicMethodReturnTypeExtension {
4367-
4368-
public function getClass(): string
4369-
{
4370-
return \DynamicMethodReturnTypesNamespace\ComponentContainer::class;
4371-
}
4372-
4373-
public function isMethodSupported(MethodReflection $methodReflection): bool
4374-
{
4375-
return $methodReflection->getName() === 'offsetGet';
4376-
}
4377-
4378-
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
4379-
{
4380-
$args = $methodCall->args;
4381-
if (count($args) === 0) {
4382-
return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
4383-
}
4384-
4385-
$argType = $scope->getType($args[0]->value);
4386-
if (!$argType instanceof ConstantStringType) {
4387-
return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
4388-
}
4389-
4390-
return new ObjectType($argType->getValue());
4391-
}
4392-
4393-
},
4394-
],
4395-
[
4396-
new class() implements DynamicStaticMethodReturnTypeExtension {
4397-
4398-
public function getClass(): string
4399-
{
4400-
return \DynamicMethodReturnTypesNamespace\EntityManager::class;
4401-
}
4402-
4403-
public function isStaticMethodSupported(MethodReflection $methodReflection): bool
4404-
{
4405-
return in_array($methodReflection->getName(), ['createManagerForEntity'], true);
4406-
}
4407-
4408-
public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope): \PHPStan\Type\Type
4409-
{
4410-
$args = $methodCall->args;
4411-
if (count($args) === 0) {
4412-
return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
4413-
}
4414-
4415-
$arg = $args[0]->value;
4416-
if (!($arg instanceof \PhpParser\Node\Expr\ClassConstFetch)) {
4417-
return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
4418-
}
4419-
4420-
if (!($arg->class instanceof \PhpParser\Node\Name)) {
4421-
return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
4422-
}
4423-
4424-
return new ObjectType((string) $arg->class);
4425-
}
4426-
4427-
},
4428-
new class() implements DynamicStaticMethodReturnTypeExtension {
4429-
4430-
public function getClass(): string
4431-
{
4432-
return \DynamicMethodReturnTypesNamespace\Foo::class;
4433-
}
4434-
4435-
public function isStaticMethodSupported(MethodReflection $methodReflection): bool
4436-
{
4437-
return $methodReflection->getName() === '__construct';
4438-
}
4439-
4440-
public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope): \PHPStan\Type\Type
4441-
{
4442-
return new ObjectWithoutClassType();
4443-
}
4444-
4445-
},
4446-
new class() implements DynamicStaticMethodReturnTypeExtension {
4447-
4448-
public function getClass(): string
4449-
{
4450-
return \DynamicMethodReturnTypesNamespace\FooWithoutConstructor::class;
4451-
}
4452-
4453-
public function isStaticMethodSupported(MethodReflection $methodReflection): bool
4454-
{
4455-
return $methodReflection->getName() === '__construct';
4456-
}
4457-
4458-
public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope): \PHPStan\Type\Type
4459-
{
4460-
return new ObjectWithoutClassType();
4461-
}
4462-
4463-
},
4464-
]
4465-
);
4466-
}
4467-
4468-
public function dataDynamicReturnTypeExtensionsOnCompoundTypes(): array
4469-
{
4470-
return [
4471-
[
4472-
'DynamicMethodReturnCompoundTypes\Collection',
4473-
'$collection->getSelf()',
4474-
],
4475-
[
4476-
'DynamicMethodReturnCompoundTypes\Collection|DynamicMethodReturnCompoundTypes\Foo',
4477-
'$collectionOrFoo->getSelf()',
4478-
],
4479-
];
4480-
}
4481-
4482-
/**
4483-
* @dataProvider dataDynamicReturnTypeExtensionsOnCompoundTypes
4484-
* @param string $description
4485-
* @param string $expression
4486-
*/
4487-
public function testDynamicReturnTypeExtensionsOnCompoundTypes(
4488-
string $description,
4489-
string $expression
4490-
): void
4491-
{
4492-
$this->assertTypes(
4493-
__DIR__ . '/data/dynamic-method-return-compound-types.php',
4494-
$description,
4495-
$expression,
4496-
[
4497-
new class () implements DynamicMethodReturnTypeExtension {
4498-
4499-
public function getClass(): string
4500-
{
4501-
return \DynamicMethodReturnCompoundTypes\Collection::class;
4502-
}
4503-
4504-
public function isMethodSupported(MethodReflection $methodReflection): bool
4505-
{
4506-
return $methodReflection->getName() === 'getSelf';
4507-
}
4508-
4509-
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
4510-
{
4511-
return new ObjectType(\DynamicMethodReturnCompoundTypes\Collection::class);
4512-
}
4513-
4514-
},
4515-
new class () implements DynamicMethodReturnTypeExtension {
4516-
4517-
public function getClass(): string
4518-
{
4519-
return \DynamicMethodReturnCompoundTypes\Foo::class;
4520-
}
4521-
4522-
public function isMethodSupported(MethodReflection $methodReflection): bool
4523-
{
4524-
return $methodReflection->getName() === 'getSelf';
4525-
}
4526-
4527-
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
4528-
{
4529-
return new ObjectType(\DynamicMethodReturnCompoundTypes\Foo::class);
4530-
}
4531-
4532-
},
4533-
]
4534-
);
4535-
}
4536-
45374229
public function dataOverwritingVariable(): array
45384230
{
45394231
return [

0 commit comments

Comments
 (0)