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