1
0
mirror of https://github.com/danog/psalm.git synced 2024-12-11 00:39:38 +01:00
psalm/tests/Internal/Codebase/MethodGetCompletionItemsForClassishThingTest.php
Ivan Sidorov 715f6f51e1 Ignore annotated magic properties with usage static gap
In PHP is not exists methods for implementation magic static properties.
So, these magic static properties must not be presented.
2023-11-17 15:14:56 +00:00

508 lines
15 KiB
PHP

<?php
declare(strict_types=1);
namespace Psalm\Tests\Internal\Codebase;
use Psalm\Codebase;
use Psalm\Context;
use Psalm\Internal\Analyzer\ProjectAnalyzer;
use Psalm\Internal\Provider\FakeFileProvider;
use Psalm\Internal\Provider\Providers;
use Psalm\Tests\Internal\Provider\FakeFileReferenceCacheProvider;
use Psalm\Tests\Internal\Provider\ParserInstanceCacheProvider;
use Psalm\Tests\Internal\Provider\ProjectCacheProvider;
use Psalm\Tests\TestCase;
use Psalm\Tests\TestConfig;
use function array_map;
/**
* Fat tests for method `getCompletionItemsForClassishThing` of class `Psalm\Codebase`.
*/
final class MethodGetCompletionItemsForClassishThingTest extends TestCase
{
private Codebase $codebase;
public function setUp(): void
{
parent::setUp();
$this->file_provider = new FakeFileProvider();
$config = new TestConfig();
$providers = new Providers(
$this->file_provider,
new ParserInstanceCacheProvider(),
null,
null,
new FakeFileReferenceCacheProvider(),
new ProjectCacheProvider(),
);
$this->codebase = new Codebase($config, $providers);
$this->project_analyzer = new ProjectAnalyzer(
$config,
$providers,
null,
[],
1,
null,
$this->codebase,
);
$this->project_analyzer->setPhpVersion('7.3', 'tests');
$this->project_analyzer->getCodebase()->store_node_types = true;
$this->codebase->config->throw_exception = false;
}
/**
* @return list<string>
*/
protected function getCompletionLabels(string $content, string $class_name, string $gap): array
{
$this->addFile('somefile.php', $content);
$this->analyzeFile('somefile.php', new Context());
$items = $this->codebase->getCompletionItemsForClassishThing($class_name, $gap, true);
return array_map(fn($item) => $item->label, $items);
}
/**
* @return iterable<array-key, array{0: string}>
*/
public function providerGaps(): iterable
{
return [
'object-gap' => ['->'],
'static-gap' => ['::'],
];
}
/**
* @dataProvider providerGaps
*/
public function testSimpleOnceClass(string $gap): void
{
$content = <<<'EOF'
<?php
namespace B;
/**
* @property int $magicObjProp1
* @property-read string $magicObjProp2
* @method int magicObjMethod()
* @method static string magicStaticMethod()
*/
class A {
public $publicObjProp;
protected $protectedObjProp;
private $privateObjProp;
public static $publicStaticProp;
protected static $protectedStaticProp;
private static $privateStaticProp;
public function publicObjMethod() {}
protected function protectedObjMethod() {}
private function privateObjMethod() {}
public static function publicStaticMethod() {}
protected static function protectedStaticMethod() {}
private static function privateStaticMethod() {}
}
EOF;
$actual_labels = $this->getCompletionLabels($content, 'B\A', $gap);
$expected_labels = [
'->' => [
'magicObjProp1',
'magicObjProp2',
'magicObjMethod',
'magicStaticMethod',
'publicObjProp',
'protectedObjProp',
'privateObjProp',
'publicObjMethod',
'protectedObjMethod',
'privateObjMethod',
'publicStaticMethod',
'protectedStaticMethod',
'privateStaticMethod',
],
'::' => [
'magicStaticMethod',
'publicStaticProp',
'protectedStaticProp',
'privateStaticProp',
'publicStaticMethod',
'protectedStaticMethod',
'privateStaticMethod',
],
];
$this->assertEqualsCanonicalizing($expected_labels[$gap], $actual_labels);
}
/**
* @dataProvider providerGaps
*/
public function testAbstractClass(string $gap): void
{
$content = <<<'EOF'
<?php
namespace B;
/**
* @property int $magicObjProp1
* @property-read string $magicObjProp2
* @method int magicObjMethod()
* @method static string magicStaticMethod()
*/
abstract class A {
public $publicObjProp;
protected $protectedObjProp;
private $privateObjProp;
public static $publicStaticProp;
protected static $protectedStaticProp;
private static $privateStaticProp;
abstract public function abstractPublicMethod();
abstract protected function abstractProtectedMethod();
public function publicObjMethod() {}
protected function protectedObjMethod() {}
private function privateObjMethod() {}
public static function publicStaticMethod() {}
protected static function protectedStaticMethod() {}
private static function privateStaticMethod() {}
}
EOF;
$actual_labels = $this->getCompletionLabels($content, 'B\A', $gap);
$expected_labels = [
'->' => [
'magicObjProp1',
'magicObjProp2',
'magicObjMethod',
'magicStaticMethod',
'publicObjProp',
'protectedObjProp',
'privateObjProp',
'abstractPublicMethod',
'abstractProtectedMethod',
'publicObjMethod',
'protectedObjMethod',
'privateObjMethod',
'publicStaticMethod',
'protectedStaticMethod',
'privateStaticMethod',
],
'::' => [
'magicStaticMethod',
'publicStaticProp',
'protectedStaticProp',
'privateStaticProp',
'publicStaticMethod',
'protectedStaticMethod',
'privateStaticMethod',
],
];
$this->assertEqualsCanonicalizing($expected_labels[$gap], $actual_labels);
}
/**
* @dataProvider providerGaps
*/
public function testUseTrait(string $gap): void
{
$content = <<<'EOF'
<?php
namespace B;
/**
* @property int $magicObjProp1
* @property-read string $magicObjProp2
* @method int magicObjMethod()
* @method static string magicStaticMethod()
*/
trait C {
public $publicObjProp;
protected $protectedObjProp;
private $privateObjProp;
public static $publicStaticProp;
protected static $protectedStaticProp;
private static $privateStaticProp;
abstract public function abstractPublicMethod();
abstract protected function abstractProtectedMethod();
public function publicObjMethod() {}
protected function protectedObjMethod() {}
private function privateObjMethod() {}
public static function publicStaticMethod() {}
protected static function protectedStaticMethod() {}
private static function privateStaticMethod() {}
}
class A {
use C;
}
EOF;
$actual_labels = $this->getCompletionLabels($content, 'B\A', $gap);
$expected_labels = [
'->' => [
'magicObjProp1',
'magicObjProp2',
'magicObjMethod',
'publicObjProp',
'protectedObjProp',
'privateObjProp',
],
'::' => [
'publicStaticProp',
'protectedStaticProp',
'privateStaticProp',
],
];
$this->assertEqualsCanonicalizing($expected_labels[$gap], $actual_labels);
}
/**
* @dataProvider providerGaps
*/
public function testUseTraitWithAbstractClass(string $gap): void
{
$content = <<<'EOF'
<?php
namespace B;
/**
* @property int $magicObjProp1
* @property-read string $magicObjProp2
* @method int magicObjMethod()
* @method static string magicStaticMethod()
*/
trait C {
public $publicObjProp;
protected $protectedObjProp;
private $privateObjProp;
public static $publicStaticProp;
protected static $protectedStaticProp;
private static $privateStaticProp;
abstract public function abstractPublicMethod();
abstract protected function abstractProtectedMethod();
public function publicObjMethod() {}
protected function protectedObjMethod() {}
private function privateObjMethod() {}
public static function publicStaticMethod() {}
protected static function protectedStaticMethod() {}
private static function privateStaticMethod() {}
}
abstract class A {
use C;
}
EOF;
$actual_labels = $this->getCompletionLabels($content, 'B\A', $gap);
$expected_labels = [
'->' => [
'magicObjProp1',
'magicObjProp2',
'magicObjMethod',
'publicObjProp',
'protectedObjProp',
'privateObjProp',
],
'::' => [
'publicStaticProp',
'protectedStaticProp',
'privateStaticProp',
],
];
$this->assertEqualsCanonicalizing($expected_labels[$gap], $actual_labels);
}
/**
* @dataProvider providerGaps
*/
public function testClassWithExtends(string $gap): void
{
$content = <<<'EOF'
<?php
namespace B;
/**
* @property int $magicObjProp1
* @property-read string $magicObjProp2
* @method int magicObjMethod()
* @method static string magicStaticMethod()
*/
class C {
public $publicObjProp;
protected $protectedObjProp;
private $privateObjProp;
public static $publicStaticProp;
protected static $protectedStaticProp;
private static $privateStaticProp;
public function publicObjMethod() {}
protected function protectedObjMethod() {}
private function privateObjMethod() {}
public static function publicStaticMethod() {}
protected static function protectedStaticMethod() {}
private static function privateStaticMethod() {}
}
class A extends C {
}
EOF;
$actual_labels = $this->getCompletionLabels($content, 'B\A', $gap);
$expected_labels = [
'->' => [
'magicObjProp1',
'magicObjProp2',
'magicObjMethod',
'publicObjProp',
'protectedObjProp',
],
'::' => [
'publicStaticProp',
'protectedStaticProp',
],
];
$this->assertEqualsCanonicalizing($expected_labels[$gap], $actual_labels);
}
/**
* @dataProvider providerGaps
*/
public function testAstractClassWithInterface(string $gap): void
{
$content = <<<'EOF'
<?php
namespace B;
interface C {
public function publicObjMethod();
protected function protectedObjMethod();
}
abstract class A implements C {
abstract public function publicObjMethod();
abstract protected function protectedObjMethod();
}
EOF;
$actual_labels = $this->getCompletionLabels($content, 'B\A', $gap);
$expected_labels = [
'->' => [
'publicObjMethod',
'protectedObjMethod',
],
'::' => [],
];
$this->assertEqualsCanonicalizing($expected_labels[$gap], $actual_labels);
}
/**
* @dataProvider providerGaps
*/
public function testClassWithAnnotationMixin(string $gap): void
{
$content = <<<'EOF'
<?php
namespace B;
/**
* @property int $magicObjProp1
* @property-read string $magicObjProp2
* @method int magicObjMethod()
* @method static string magicStaticMethod()
*/
class C {
public $publicObjProp;
protected $protectedObjProp;
private $privateObjProp;
public static $publicStaticProp;
protected static $protectedStaticProp;
private static $privateStaticProp;
public function publicObjMethod() {}
protected function protectedObjMethod() {}
private function privateObjMethod() {}
public static function publicStaticMethod() {}
protected static function protectedStaticMethod() {}
private static function privateStaticMethod() {}
}
/**
* @mixin C
*/
class A {
}
EOF;
$actual_labels = $this->getCompletionLabels($content, 'B\A', $gap);
$expected_labels = [
'->' => [],
'::' => [],
];
$this->assertEqualsCanonicalizing($expected_labels[$gap], $actual_labels);
}
}