diff --git a/lib/PhpParser/BuilderHelpers.php b/lib/PhpParser/BuilderHelpers.php index 1a26dab..f5bfae9 100644 --- a/lib/PhpParser/BuilderHelpers.php +++ b/lib/PhpParser/BuilderHelpers.php @@ -27,7 +27,9 @@ final class BuilderHelpers public static function normalizeNode($node) : Node { if ($node instanceof Builder) { return $node->getNode(); - } elseif ($node instanceof Node) { + } + + if ($node instanceof Node) { return $node; } @@ -127,18 +129,22 @@ final class BuilderHelpers private static function normalizeNameCommon($name, bool $allowExpr) { if ($name instanceof Name) { return $name; - } elseif (is_string($name)) { + } + + if (is_string($name)) { if (!$name) { throw new \LogicException('Name cannot be empty'); } if ($name[0] === '\\') { return new Name\FullyQualified(substr($name, 1)); - } elseif (0 === strpos($name, 'namespace\\')) { - return new Name\Relative(substr($name, strlen('namespace\\'))); - } else { - return new Name($name); } + + if (0 === strpos($name, 'namespace\\')) { + return new Name\Relative(substr($name, strlen('namespace\\'))); + } + + return new Name($name); } if ($allowExpr) { @@ -148,9 +154,9 @@ final class BuilderHelpers throw new \LogicException( 'Name must be a string or an instance of Node\Name or Node\Expr' ); - } else { - throw new \LogicException('Name must be a string or an instance of Node\Name'); } + + throw new \LogicException('Name must be a string or an instance of Node\Name'); } /** @@ -215,21 +221,33 @@ final class BuilderHelpers public static function normalizeValue($value) : Expr { if ($value instanceof Node\Expr) { return $value; - } elseif (is_null($value)) { + } + + if (is_null($value)) { return new Expr\ConstFetch( new Name('null') ); - } elseif (is_bool($value)) { + } + + if (is_bool($value)) { return new Expr\ConstFetch( new Name($value ? 'true' : 'false') ); - } elseif (is_int($value)) { + } + + if (is_int($value)) { return new Scalar\LNumber($value); - } elseif (is_float($value)) { + } + + if (is_float($value)) { return new Scalar\DNumber($value); - } elseif (is_string($value)) { + } + + if (is_string($value)) { return new Scalar\String_($value); - } elseif (is_array($value)) { + } + + if (is_array($value)) { $items = []; $lastKey = -1; foreach ($value as $itemKey => $itemValue) { @@ -248,9 +266,9 @@ final class BuilderHelpers } return new Expr\Array_($items); - } else { - throw new \LogicException('Invalid value'); } + + throw new \LogicException('Invalid value'); } /** @@ -263,11 +281,13 @@ final class BuilderHelpers public static function normalizeDocComment($docComment) : Comment\Doc { if ($docComment instanceof Comment\Doc) { return $docComment; - } elseif (is_string($docComment)) { - return new Comment\Doc($docComment); - } else { - throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc'); } + + if (is_string($docComment)) { + return new Comment\Doc($docComment); + } + + throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc'); } /** diff --git a/test/PhpParser/BuilderHelpersTest.php b/test/PhpParser/BuilderHelpersTest.php index 72f2b84..9376cda 100644 --- a/test/PhpParser/BuilderHelpersTest.php +++ b/test/PhpParser/BuilderHelpersTest.php @@ -2,15 +2,205 @@ namespace PhpParser; -use PhpParser\Node\Attribute; -use PhpParser\Node\AttributeGroup; -use PhpParser\Node\Name; +use PhpParser\Builder\Class_; +use PhpParser\Node\Scalar; +use PhpParser\Node\Stmt; +use PhpParser\Node\Expr; class BuilderHelpersTest extends \PHPUnit\Framework\TestCase { + public function testNormalizeNode() { + $builder = new Class_('SomeClass'); + $this->assertEquals($builder->getNode(), BuilderHelpers::normalizeNode($builder)); + + $attribute = new Node\Attribute(new Node\Name('Test')); + $this->assertSame($attribute, BuilderHelpers::normalizeNode($attribute)); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Expected node or builder object'); + BuilderHelpers::normalizeNode('test'); + } + + public function testNormalizeStmt() { + $stmt = new Node\Stmt\Class_('Class'); + $this->assertSame($stmt, BuilderHelpers::normalizeStmt($stmt)); + + $expr = new Expr\Variable('fn'); + $normalizedExpr = BuilderHelpers::normalizeStmt($expr); + $this->assertEquals(new Stmt\Expression($expr), $normalizedExpr); + $this->assertSame($expr, $normalizedExpr->expr); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Expected statement or expression node'); + BuilderHelpers::normalizeStmt(new Node\Attribute(new Node\Name('Test'))); + } + + public function testNormalizeStmtInvalidType() { + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Expected node or builder object'); + BuilderHelpers::normalizeStmt('test'); + } + + public function testNormalizeIdentifier() { + $identifier = new Node\Identifier('fn'); + $this->assertSame($identifier, BuilderHelpers::normalizeIdentifier($identifier)); + $this->assertEquals($identifier, BuilderHelpers::normalizeIdentifier('fn')); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Expected string or instance of Node\Identifier'); + BuilderHelpers::normalizeIdentifier(1); + } + + public function testNormalizeIdentifierOrExpr() { + $identifier = new Node\Identifier('fn'); + $this->assertSame($identifier, BuilderHelpers::normalizeIdentifierOrExpr($identifier)); + + $expr = new Expr\Variable('fn'); + $this->assertSame($expr, BuilderHelpers::normalizeIdentifierOrExpr($expr)); + $this->assertEquals($identifier, BuilderHelpers::normalizeIdentifierOrExpr('fn')); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Expected string or instance of Node\Identifier'); + BuilderHelpers::normalizeIdentifierOrExpr(1); + } + + public function testNormalizeName() { + $name = new Node\Name('test'); + $this->assertSame($name, BuilderHelpers::normalizeName($name)); + $this->assertEquals( + new Node\Name\FullyQualified(['Namespace', 'Test']), + BuilderHelpers::normalizeName('\\Namespace\\Test') + ); + $this->assertEquals( + new Node\Name\Relative(['Test']), + BuilderHelpers::normalizeName('namespace\\Test') + ); + $this->assertEquals($name, BuilderHelpers::normalizeName('test')); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Name cannot be empty'); + BuilderHelpers::normalizeName(''); + } + + public function testNormalizeNameInvalidType() { + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Name must be a string or an instance of Node\Name'); + BuilderHelpers::normalizeName(1); + } + + public function testNormalizeNameOrExpr() { + $expr = new Expr\Variable('fn'); + $this->assertSame($expr, BuilderHelpers::normalizeNameOrExpr($expr)); + + $name = new Node\Name('test'); + $this->assertSame($name, BuilderHelpers::normalizeNameOrExpr($name)); + $this->assertEquals( + new Node\Name\FullyQualified(['Namespace', 'Test']), + BuilderHelpers::normalizeNameOrExpr('\\Namespace\\Test') + ); + $this->assertEquals( + new Node\Name\Relative(['Test']), + BuilderHelpers::normalizeNameOrExpr('namespace\\Test') + ); + $this->assertEquals($name, BuilderHelpers::normalizeNameOrExpr('test')); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Name cannot be empty'); + BuilderHelpers::normalizeNameOrExpr(''); + } + + public function testNormalizeNameOrExpInvalidType() { + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Name must be a string or an instance of Node\Name or Node\Expr'); + BuilderHelpers::normalizeNameOrExpr(1); + } + + public function testNormalizeType() { + $this->assertEquals(new Node\Identifier('array'), BuilderHelpers::normalizeType('array')); + $this->assertEquals(new Node\Identifier('callable'), BuilderHelpers::normalizeType('callable')); + $this->assertEquals(new Node\Identifier('string'), BuilderHelpers::normalizeType('string')); + $this->assertEquals(new Node\Identifier('int'), BuilderHelpers::normalizeType('int')); + $this->assertEquals(new Node\Identifier('float'), BuilderHelpers::normalizeType('float')); + $this->assertEquals(new Node\Identifier('bool'), BuilderHelpers::normalizeType('bool')); + $this->assertEquals(new Node\Identifier('iterable'), BuilderHelpers::normalizeType('iterable')); + $this->assertEquals(new Node\Identifier('void'), BuilderHelpers::normalizeType('void')); + $this->assertEquals(new Node\Identifier('object'), BuilderHelpers::normalizeType('object')); + $this->assertEquals(new Node\Identifier('mixed'), BuilderHelpers::normalizeType('mixed')); + + $intIdentifier = new Node\Identifier('int'); + $this->assertSame($intIdentifier, BuilderHelpers::normalizeType($intIdentifier)); + + $intName = new Node\Name('int'); + $this->assertSame($intName, BuilderHelpers::normalizeType($intName)); + + $intNullable = new Node\NullableType('int'); + $this->assertSame($intNullable, BuilderHelpers::normalizeType($intNullable)); + + $unionType = new Node\UnionType([new Node\Identifier('int'), new Node\Identifier('string')]); + $this->assertSame($unionType, BuilderHelpers::normalizeType($unionType)); + + $expectedNullable = new Node\NullableType($intIdentifier); + $nullable = BuilderHelpers::normalizeType('?int'); + $this->assertEquals($expectedNullable, $nullable); + $this->assertEquals($intIdentifier, $nullable->type); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Type must be a string, or an instance of Name, Identifier, NullableType or UnionType'); + BuilderHelpers::normalizeType(1); + } + + public function testNormalizeTypeNullableVoid() { + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('void type cannot be nullable'); + BuilderHelpers::normalizeType('?void'); + } + + public function testNormalizeTypeNullableMixed() { + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('mixed type cannot be nullable'); + BuilderHelpers::normalizeType('?mixed'); + } + + public function testNormalizeValue() { + $expression = new Scalar\LNumber(1); + $this->assertSame($expression, BuilderHelpers::normalizeValue($expression)); + + $this->assertEquals(new Expr\ConstFetch(new Node\Name('null')), BuilderHelpers::normalizeValue(null)); + $this->assertEquals(new Expr\ConstFetch(new Node\Name('true')), BuilderHelpers::normalizeValue(true)); + $this->assertEquals(new Expr\ConstFetch(new Node\Name('false')), BuilderHelpers::normalizeValue(false)); + $this->assertEquals(new Scalar\LNumber(2), BuilderHelpers::normalizeValue(2)); + $this->assertEquals(new Scalar\DNumber(2.5), BuilderHelpers::normalizeValue(2.5)); + $this->assertEquals(new Scalar\String_('text'), BuilderHelpers::normalizeValue('text')); + $this->assertEquals( + new Expr\Array_([ + new Expr\ArrayItem(new Scalar\LNumber(0)), + new Expr\ArrayItem(new Scalar\LNumber(1), new Scalar\String_('test')), + ]), + BuilderHelpers::normalizeValue([ + 0, + 'test' => 1, + ]) + ); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Invalid value'); + BuilderHelpers::normalizeValue(new \stdClass()); + } + + public function testNormalizeDocComment() { + $docComment = new Comment\Doc('Some doc comment'); + $this->assertSame($docComment, BuilderHelpers::normalizeDocComment($docComment)); + + $this->assertEquals($docComment, BuilderHelpers::normalizeDocComment('Some doc comment')); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Doc comment must be a string or an instance of PhpParser\Comment\Doc'); + BuilderHelpers::normalizeDocComment(1); + } + public function testNormalizeAttribute() { - $attribute = new Attribute(new Name('Test')); - $attributeGroup = new AttributeGroup([$attribute]); + $attribute = new Node\Attribute(new Node\Name('Test')); + $attributeGroup = new Node\AttributeGroup([$attribute]); $this->assertEquals($attributeGroup, BuilderHelpers::normalizeAttribute($attribute)); $this->assertSame($attributeGroup, BuilderHelpers::normalizeAttribute($attributeGroup));