Skip to content

Commit

Permalink
Added builders for enum and enum case
Browse files Browse the repository at this point in the history
  • Loading branch information
kukulich authored and nikic committed Nov 5, 2021
1 parent 63a79e8 commit 99a24b6
Show file tree
Hide file tree
Showing 6 changed files with 470 additions and 1 deletion.
85 changes: 85 additions & 0 deletions lib/PhpParser/Builder/EnumCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

declare(strict_types=1);

namespace PhpParser\Builder;

use PhpParser;
use PhpParser\BuilderHelpers;
use PhpParser\Node;
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt;

class EnumCase implements PhpParser\Builder
{
protected $name;
protected $value = null;
protected $attributes = [];

/** @var Node\AttributeGroup[] */
protected $attributeGroups = [];

/**
* Creates an enum case builder.
*
* @param string|Identifier $name Name
*/
public function __construct($name) {
$this->name = $name;
}

/**
* Sets the value.
*
* @param Node\Expr|string|int $value
*
* @return $this
*/
public function setValue($value) {
$this->value = BuilderHelpers::normalizeValue($value);

return $this;
}

/**
* Sets doc comment for the constant.
*
* @param PhpParser\Comment\Doc|string $docComment Doc comment to set
*
* @return $this The builder instance (for fluid interface)
*/
public function setDocComment($docComment) {
$this->attributes = [
'comments' => [BuilderHelpers::normalizeDocComment($docComment)]
];

return $this;
}

/**
* Adds an attribute group.
*
* @param Node\Attribute|Node\AttributeGroup $attribute
*
* @return $this The builder instance (for fluid interface)
*/
public function addAttribute($attribute) {
$this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute);

return $this;
}

/**
* Returns the built enum case node.
*
* @return Stmt\EnumCase The built constant node
*/
public function getNode(): PhpParser\Node {
return new Stmt\EnumCase(
$this->name,
$this->value,
$this->attributes,
$this->attributeGroups
);
}
}
117 changes: 117 additions & 0 deletions lib/PhpParser/Builder/Enum_.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php declare(strict_types=1);

namespace PhpParser\Builder;

use PhpParser;
use PhpParser\BuilderHelpers;
use PhpParser\Node;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt;

class Enum_ extends Declaration
{
protected $name;
protected $scalarType = null;

protected $implements = [];

protected $uses = [];
protected $enumCases = [];
protected $constants = [];
protected $methods = [];

/** @var Node\AttributeGroup[] */
protected $attributeGroups = [];

/**
* Creates an enum builder.
*
* @param string $name Name of the enum
*/
public function __construct(string $name) {
$this->name = $name;
}

/**
* Sets the scalar type.
*
* @param string|Identifier $type
*
* @return $this
*/
public function setScalarType($scalarType) {
$this->scalarType = BuilderHelpers::normalizeType($scalarType);

return $this;
}

/**
* Implements one or more interfaces.
*
* @param Name|string ...$interfaces Names of interfaces to implement
*
* @return $this The builder instance (for fluid interface)
*/
public function implement(...$interfaces) {
foreach ($interfaces as $interface) {
$this->implements[] = BuilderHelpers::normalizeName($interface);
}

return $this;
}

/**
* Adds a statement.
*
* @param Stmt|PhpParser\Builder $stmt The statement to add
*
* @return $this The builder instance (for fluid interface)
*/
public function addStmt($stmt) {
$stmt = BuilderHelpers::normalizeNode($stmt);

$targets = [
Stmt\TraitUse::class => &$this->uses,
Stmt\EnumCase::class => &$this->enumCases,
Stmt\ClassConst::class => &$this->constants,
Stmt\ClassMethod::class => &$this->methods,
];

$class = \get_class($stmt);
if (!isset($targets[$class])) {
throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType()));
}

$targets[$class][] = $stmt;

return $this;
}

/**
* Adds an attribute group.
*
* @param Node\Attribute|Node\AttributeGroup $attribute
*
* @return $this The builder instance (for fluid interface)
*/
public function addAttribute($attribute) {
$this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute);

return $this;
}

/**
* Returns the built class node.
*
* @return Stmt\Enum_ The built enum node
*/
public function getNode() : PhpParser\Node {
return new Stmt\Enum_($this->name, [
'scalarType' => $this->scalarType,
'implements' => $this->implements,
'stmts' => array_merge($this->uses, $this->enumCases, $this->constants, $this->methods),
'attrGroups' => $this->attributeGroups,
], $this->attributes);
}
}
24 changes: 23 additions & 1 deletion lib/PhpParser/BuilderFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,17 @@ public function trait(string $name) : Builder\Trait_ {
return new Builder\Trait_($name);
}

/**
* Creates an enum builder.
*
* @param string $name Name of the enum
*
* @return Builder\Enum_ The created enum builder
*/
public function enum(string $name) : Builder\Enum_ {
return new Builder\Enum_($name);
}

/**
* Creates a trait use builder.
*
Expand Down Expand Up @@ -188,6 +199,17 @@ public function classConst($name, $value) : Builder\ClassConst {
return new Builder\ClassConst($name, $value);
}

/**
* Creates an enum case builder.
*
* @param string|Identifier $name Name
*
* @return Builder\EnumCase The created use const builder
*/
public function enumCase($name) : Builder\EnumCase {
return new Builder\EnumCase($name);
}

/**
* Creates node a for a literal value.
*
Expand Down Expand Up @@ -311,7 +333,7 @@ public function new($class, array $args = []) : Expr\New_ {
public function constFetch($name) : Expr\ConstFetch {
return new Expr\ConstFetch(BuilderHelpers::normalizeName($name));
}

/**
* Creates a property fetch node.
*
Expand Down
84 changes: 84 additions & 0 deletions test/PhpParser/Builder/EnumCaseTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php declare(strict_types=1);

namespace PhpParser\Builder;

use PhpParser\Comment;
use PhpParser\Node\Arg;
use PhpParser\Node\Attribute;
use PhpParser\Node\AttributeGroup;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Stmt;

class EnumCaseTest extends \PHPUnit\Framework\TestCase
{
public function createEnumCaseBuilder($name) {
return new EnumCase($name);
}

public function testDocComment() {
$node = $this->createEnumCaseBuilder('TEST')
->setDocComment('/** Test */')
->getNode();

$this->assertEquals(
new Stmt\EnumCase(
"TEST",
null,
[
'comments' => [new Comment\Doc('/** Test */')]
]
),
$node
);
}

public function testAddAttribute() {
$attribute = new Attribute(
new Name('Attr'),
[new Arg(new LNumber(1), false, false, [], new Identifier('name'))]
);
$attributeGroup = new AttributeGroup([$attribute]);

$node = $this->createEnumCaseBuilder('ATTR_GROUP')
->addAttribute($attributeGroup)
->getNode();

$this->assertEquals(
new Stmt\EnumCase(
"ATTR_GROUP",
null,
[],
[$attributeGroup]
),
$node
);
}

/**
* @dataProvider provideTestDefaultValues
*/
public function testValues($value, $expectedValueNode) {
$node = $this->createEnumCaseBuilder('TEST')
->setValue($value)
->getNode()
;

$this->assertEquals($expectedValueNode, $node->expr);
}

public function provideTestDefaultValues() {
return [
[
31415,
new Scalar\LNumber(31415)
],
[
'Hallo World',
new Scalar\String_('Hallo World')
],
];
}
}
Loading

0 comments on commit 99a24b6

Please sign in to comment.