mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Tests of current behaviors in the auto-completion feature
This commit is contained in:
parent
d9d08f76f4
commit
650b8fcd1b
@ -0,0 +1,539 @@
|
||||
<?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',
|
||||
|
||||
'$publicStaticProp',
|
||||
'$protectedStaticProp',
|
||||
'$privateStaticProp',
|
||||
|
||||
'publicObjMethod',
|
||||
'protectedObjMethod',
|
||||
'privateObjMethod',
|
||||
|
||||
'publicStaticMethod',
|
||||
'protectedStaticMethod',
|
||||
'privateStaticMethod',
|
||||
],
|
||||
'::' => [
|
||||
'magicObjProp1',
|
||||
'magicObjProp2',
|
||||
'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',
|
||||
|
||||
'$publicStaticProp',
|
||||
'$protectedStaticProp',
|
||||
'$privateStaticProp',
|
||||
|
||||
'abstractPublicMethod',
|
||||
'abstractProtectedMethod',
|
||||
|
||||
'publicObjMethod',
|
||||
'protectedObjMethod',
|
||||
'privateObjMethod',
|
||||
|
||||
'publicStaticMethod',
|
||||
'protectedStaticMethod',
|
||||
'privateStaticMethod',
|
||||
],
|
||||
'::' => [
|
||||
'magicObjProp1',
|
||||
'magicObjProp2',
|
||||
'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',
|
||||
],
|
||||
'::' => [
|
||||
'magicObjProp1',
|
||||
'magicObjProp2',
|
||||
|
||||
'$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',
|
||||
],
|
||||
'::' => [
|
||||
'magicObjProp1',
|
||||
'magicObjProp2',
|
||||
|
||||
'$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',
|
||||
],
|
||||
'::' => [
|
||||
'magicObjProp1',
|
||||
'magicObjProp2',
|
||||
|
||||
'$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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user