1<?php declare(strict_types=1);
2
3namespace PhpParser\Builder;
4
5use PhpParser\Comment;
6use PhpParser\Node;
7use PhpParser\Node\Arg;
8use PhpParser\Node\Attribute;
9use PhpParser\Node\AttributeGroup;
10use PhpParser\Node\Identifier;
11use PhpParser\Node\Name;
12use PhpParser\Node\Scalar\Int_;
13use PhpParser\Node\Stmt;
14
15class EnumTest extends \PHPUnit\Framework\TestCase {
16    protected function createEnumBuilder($class) {
17        return new Enum_($class);
18    }
19
20    public function testImplements(): void {
21        $node = $this->createEnumBuilder('SomeEnum')
22            ->implement('Namespaced\SomeInterface', new Name('OtherInterface'))
23            ->getNode()
24        ;
25
26        $this->assertEquals(
27            new Stmt\Enum_('SomeEnum', [
28                'implements' => [
29                    new Name('Namespaced\SomeInterface'),
30                    new Name('OtherInterface'),
31                ],
32            ]),
33            $node
34        );
35    }
36
37    public function testSetScalarType(): void {
38        $node = $this->createEnumBuilder('Test')
39            ->setScalarType('int')
40            ->getNode()
41        ;
42
43        $this->assertEquals(
44            new Stmt\Enum_('Test', [
45                'scalarType' => new Identifier('int'),
46            ]),
47            $node
48        );
49    }
50
51    public function testStatementOrder(): void {
52        $method = new Stmt\ClassMethod('testMethod');
53        $enumCase = new Stmt\EnumCase(
54            'TEST_ENUM_CASE'
55        );
56        $const = new Stmt\ClassConst([
57            new Node\Const_('TEST_CONST', new Node\Scalar\String_('ABC'))
58        ]);
59        $use = new Stmt\TraitUse([new Name('SomeTrait')]);
60
61        $node = $this->createEnumBuilder('Test')
62            ->addStmt($method)
63            ->addStmt($enumCase)
64            ->addStmts([$const, $use])
65            ->getNode()
66        ;
67
68        $this->assertEquals(
69            new Stmt\Enum_('Test', [
70                'stmts' => [$use, $enumCase, $const, $method]
71            ]),
72            $node
73        );
74    }
75
76    public function testDocComment(): void {
77        $docComment = <<<'DOC'
78/**
79 * Test
80 */
81DOC;
82        $enum = $this->createEnumBuilder('Test')
83            ->setDocComment($docComment)
84            ->getNode();
85
86        $this->assertEquals(
87            new Stmt\Enum_('Test', [], [
88                'comments' => [
89                    new Comment\Doc($docComment)
90                ]
91            ]),
92            $enum
93        );
94
95        $enum = $this->createEnumBuilder('Test')
96            ->setDocComment(new Comment\Doc($docComment))
97            ->getNode();
98
99        $this->assertEquals(
100            new Stmt\Enum_('Test', [], [
101                'comments' => [
102                    new Comment\Doc($docComment)
103                ]
104            ]),
105            $enum
106        );
107    }
108
109    public function testAddAttribute(): void {
110        $attribute = new Attribute(
111            new Name('Attr'),
112            [new Arg(new Int_(1), false, false, [], new Identifier('name'))]
113        );
114        $attributeGroup = new AttributeGroup([$attribute]);
115
116        $enum = $this->createEnumBuilder('ATTR_GROUP')
117            ->addAttribute($attributeGroup)
118            ->getNode();
119
120        $this->assertEquals(
121            new Stmt\Enum_('ATTR_GROUP', [
122                'attrGroups' => [
123                    $attributeGroup,
124                ]
125            ], []),
126            $enum
127        );
128    }
129
130    public function testInvalidStmtError(): void {
131        $this->expectException(\LogicException::class);
132        $this->expectExceptionMessage('Unexpected node of type "PropertyItem"');
133        $this->createEnumBuilder('Test')
134            ->addStmt(new Node\PropertyItem('property'))
135        ;
136    }
137
138    public function testInvalidDocComment(): void {
139        $this->expectException(\LogicException::class);
140        $this->expectExceptionMessage('Doc comment must be a string or an instance of PhpParser\Comment\Doc');
141        $this->createEnumBuilder('Test')
142            ->setDocComment(new Comment('Test'));
143    }
144
145    public function testEmptyName(): void {
146        $this->expectException(\LogicException::class);
147        $this->expectExceptionMessage('Name cannot be empty');
148        $this->createEnumBuilder('Test')
149            ->implement('');
150    }
151
152    public function testInvalidName(): void {
153        $this->expectException(\LogicException::class);
154        $this->expectExceptionMessage('Name must be a string or an instance of Node\Name');
155        $this->createEnumBuilder('Test')
156            ->implement(['Foo']);
157    }
158}
159