xref: /PHP-Parser/test/PhpParser/Node/NameTest.php (revision daaadc3b)
1<?php declare(strict_types=1);
2
3namespace PhpParser\Node;
4
5class NameTest extends \PHPUnit\Framework\TestCase {
6    public function testConstruct(): void {
7        $name = new Name(['foo', 'bar']);
8        $this->assertSame('foo\bar', $name->name);
9
10        $name = new Name('foo\bar');
11        $this->assertSame('foo\bar', $name->name);
12
13        $name = new Name($name);
14        $this->assertSame('foo\bar', $name->name);
15    }
16
17    public function testGet(): void {
18        $name = new Name('foo');
19        $this->assertSame('foo', $name->getFirst());
20        $this->assertSame('foo', $name->getLast());
21        $this->assertSame(['foo'], $name->getParts());
22
23        $name = new Name('foo\bar');
24        $this->assertSame('foo', $name->getFirst());
25        $this->assertSame('bar', $name->getLast());
26        $this->assertSame(['foo', 'bar'], $name->getParts());
27    }
28
29    public function testToString(): void {
30        $name = new Name('Foo\Bar');
31
32        $this->assertSame('Foo\Bar', (string) $name);
33        $this->assertSame('Foo\Bar', $name->toString());
34        $this->assertSame('foo\bar', $name->toLowerString());
35    }
36
37    public function testSlice(): void {
38        $name = new Name('foo\bar\baz');
39        $this->assertEquals(new Name('foo\bar\baz'), $name->slice(0));
40        $this->assertEquals(new Name('bar\baz'), $name->slice(1));
41        $this->assertNull($name->slice(3));
42        $this->assertEquals(new Name('foo\bar\baz'), $name->slice(-3));
43        $this->assertEquals(new Name('bar\baz'), $name->slice(-2));
44        $this->assertEquals(new Name('foo\bar'), $name->slice(0, -1));
45        $this->assertNull($name->slice(0, -3));
46        $this->assertEquals(new Name('bar'), $name->slice(1, -1));
47        $this->assertNull($name->slice(1, -2));
48        $this->assertEquals(new Name('bar'), $name->slice(-2, 1));
49        $this->assertEquals(new Name('bar'), $name->slice(-2, -1));
50        $this->assertNull($name->slice(-2, -2));
51    }
52
53    public function testSliceOffsetTooLarge(): void {
54        $this->expectException(\OutOfBoundsException::class);
55        $this->expectExceptionMessage('Offset 4 is out of bounds');
56        (new Name('foo\bar\baz'))->slice(4);
57    }
58
59    public function testSliceOffsetTooSmall(): void {
60        $this->expectException(\OutOfBoundsException::class);
61        $this->expectExceptionMessage('Offset -4 is out of bounds');
62        (new Name('foo\bar\baz'))->slice(-4);
63    }
64
65    public function testSliceLengthTooLarge(): void {
66        $this->expectException(\OutOfBoundsException::class);
67        $this->expectExceptionMessage('Length 4 is out of bounds');
68        (new Name('foo\bar\baz'))->slice(0, 4);
69    }
70
71    public function testSliceLengthTooSmall(): void {
72        $this->expectException(\OutOfBoundsException::class);
73        $this->expectExceptionMessage('Length -4 is out of bounds');
74        (new Name('foo\bar\baz'))->slice(0, -4);
75    }
76
77    public function testSliceLengthTooLargeWithOffset(): void {
78        $this->expectException(\OutOfBoundsException::class);
79        $this->expectExceptionMessage('Length 3 is out of bounds');
80        (new Name('foo\bar\baz'))->slice(1, 3);
81    }
82
83    public function testConcat(): void {
84        $this->assertEquals(new Name('foo\bar\baz'), Name::concat('foo', 'bar\baz'));
85        $this->assertEquals(
86            new Name\FullyQualified('foo\bar'),
87            Name\FullyQualified::concat(['foo'], new Name('bar'))
88        );
89
90        $attributes = ['foo' => 'bar'];
91        $this->assertEquals(
92            new Name\Relative('foo\bar\baz', $attributes),
93            Name\Relative::concat(new Name\FullyQualified('foo\bar'), 'baz', $attributes)
94        );
95
96        $this->assertEquals(new Name('foo'), Name::concat(null, 'foo'));
97        $this->assertEquals(new Name('foo'), Name::concat('foo', null));
98        $this->assertNull(Name::concat(null, null));
99    }
100
101    public function testNameTypes(): void {
102        $name = new Name('foo');
103        $this->assertTrue($name->isUnqualified());
104        $this->assertFalse($name->isQualified());
105        $this->assertFalse($name->isFullyQualified());
106        $this->assertFalse($name->isRelative());
107        $this->assertSame('foo', $name->toCodeString());
108
109        $name = new Name('foo\bar');
110        $this->assertFalse($name->isUnqualified());
111        $this->assertTrue($name->isQualified());
112        $this->assertFalse($name->isFullyQualified());
113        $this->assertFalse($name->isRelative());
114        $this->assertSame('foo\bar', $name->toCodeString());
115
116        $name = new Name\FullyQualified('foo');
117        $this->assertFalse($name->isUnqualified());
118        $this->assertFalse($name->isQualified());
119        $this->assertTrue($name->isFullyQualified());
120        $this->assertFalse($name->isRelative());
121        $this->assertSame('\foo', $name->toCodeString());
122
123        $name = new Name\Relative('foo');
124        $this->assertFalse($name->isUnqualified());
125        $this->assertFalse($name->isQualified());
126        $this->assertFalse($name->isFullyQualified());
127        $this->assertTrue($name->isRelative());
128        $this->assertSame('namespace\foo', $name->toCodeString());
129    }
130
131    public function testInvalidArg(): void {
132        $this->expectException(\InvalidArgumentException::class);
133        $this->expectExceptionMessage('Expected string, array of parts or Name instance');
134        Name::concat('foo', new \stdClass());
135    }
136
137    public function testInvalidEmptyString(): void {
138        $this->expectException(\InvalidArgumentException::class);
139        $this->expectExceptionMessage('Name cannot be empty');
140        new Name('');
141    }
142
143    public function testInvalidEmptyArray(): void {
144        $this->expectException(\InvalidArgumentException::class);
145        $this->expectExceptionMessage('Name cannot be empty');
146        new Name([]);
147    }
148
149    /** @dataProvider provideTestIsSpecialClassName */
150    public function testIsSpecialClassName($name, $expected): void {
151        $name = new Name($name);
152        $this->assertSame($expected, $name->isSpecialClassName());
153    }
154
155    public static function provideTestIsSpecialClassName() {
156        return [
157            ['self', true],
158            ['PARENT', true],
159            ['Static', true],
160            ['self\not', false],
161            ['not\self', false],
162        ];
163    }
164}
165