1<?php declare(strict_types=1);
2
3namespace PhpParser\Node\Stmt;
4
5use PhpParser\Modifiers;
6use PhpParser\Node\Expr\Variable;
7use PhpParser\Node\Name;
8use PhpParser\Node\Param;
9
10class ClassMethodTest extends \PHPUnit\Framework\TestCase {
11    /**
12     * @dataProvider provideModifiers
13     */
14    public function testModifiers($modifier): void {
15        $node = new ClassMethod('foo', [
16            'type' => constant(Modifiers::class . '::' . strtoupper($modifier))
17        ]);
18
19        $this->assertTrue($node->{'is' . $modifier}());
20    }
21
22    public function testNoModifiers(): void {
23        $node = new ClassMethod('foo', ['type' => 0]);
24
25        $this->assertTrue($node->isPublic());
26        $this->assertFalse($node->isProtected());
27        $this->assertFalse($node->isPrivate());
28        $this->assertFalse($node->isAbstract());
29        $this->assertFalse($node->isFinal());
30        $this->assertFalse($node->isStatic());
31        $this->assertFalse($node->isMagic());
32    }
33
34    public static function provideModifiers() {
35        return [
36            ['public'],
37            ['protected'],
38            ['private'],
39            ['abstract'],
40            ['final'],
41            ['static'],
42        ];
43    }
44
45    /**
46     * Checks that implicit public modifier detection for method is working
47     *
48     * @dataProvider implicitPublicModifiers
49     *
50     * @param string $modifier Node type modifier
51     */
52    public function testImplicitPublic(string $modifier): void {
53        $node = new ClassMethod('foo', [
54            'type' => constant(Modifiers::class . '::' . strtoupper($modifier))
55        ]);
56
57        $this->assertTrue($node->isPublic(), 'Node should be implicitly public');
58    }
59
60    public static function implicitPublicModifiers() {
61        return [
62            ['abstract'],
63            ['final'],
64            ['static'],
65        ];
66    }
67
68    /**
69     * @dataProvider provideMagics
70     *
71     * @param string $name Node name
72     */
73    public function testMagic(string $name): void {
74        $node = new ClassMethod($name);
75        $this->assertTrue($node->isMagic(), 'Method should be magic');
76    }
77
78    public static function provideMagics() {
79        return [
80             ['__construct'],
81             ['__DESTRUCT'],
82             ['__caLL'],
83             ['__callstatic'],
84             ['__get'],
85             ['__set'],
86             ['__isset'],
87             ['__unset'],
88             ['__sleep'],
89             ['__wakeup'],
90             ['__tostring'],
91             ['__set_state'],
92             ['__clone'],
93             ['__invoke'],
94             ['__debuginfo'],
95        ];
96    }
97
98    public function testFunctionLike(): void {
99        $param = new Param(new Variable('a'));
100        $type = new Name('Foo');
101        $return = new Return_(new Variable('a'));
102        $method = new ClassMethod('test', [
103            'byRef' => false,
104            'params' => [$param],
105            'returnType' => $type,
106            'stmts' => [$return],
107        ]);
108
109        $this->assertFalse($method->returnsByRef());
110        $this->assertSame([$param], $method->getParams());
111        $this->assertSame($type, $method->getReturnType());
112        $this->assertSame([$return], $method->getStmts());
113
114        $method = new ClassMethod('test', [
115            'byRef' => true,
116            'stmts' => null,
117        ]);
118
119        $this->assertTrue($method->returnsByRef());
120        $this->assertNull($method->getStmts());
121    }
122}
123