Skip to content

Commit

Permalink
ClassType::add*() throws exception when method/property/etc already e…
Browse files Browse the repository at this point in the history
…xists (BC break)
  • Loading branch information
dg committed Feb 20, 2022
1 parent c48096c commit 93166ff
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 14 deletions.
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ Readonly properties introduced by PHP 8.1 can be marked via `setReadOnly()`.

------

If the added property, constant, method or parameter already exist, it will be overwritten.
If the added property, constant, method or parameter already exist, it throws exception.

Members can be removed using `removeProperty()`, `removeConstant()`, `removeMethod()` or `removeParameter()`.

Expand Down
35 changes: 28 additions & 7 deletions src/PhpGenerator/ClassType.php
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@ public function getTraits(): array

public function addTrait(string $name, array|bool|null $deprecatedParam = null): TraitUse
{
if (isset($this->traits[$name])) {
throw new Nette\InvalidStateException("Cannot add trait '$name', because it already exists.");
}
$this->traits[$name] = $trait = new TraitUse($name, $this);
if (is_array($deprecatedParam)) {
array_map(fn($item) => $trait->addResolution($item), $deprecatedParam);
Expand All @@ -356,13 +359,18 @@ public function removeTrait(string $name): static

public function addMember(Method|Property|Constant|EnumCase|TraitUse $member): static
{
match (true) {
$member instanceof Method => $this->methods[strtolower($member->getName())] = $member,
$member instanceof Property => $this->properties[$member->getName()] = $member,
$member instanceof Constant => $this->consts[$member->getName()] = $member,
$member instanceof EnumCase => $this->cases[$member->getName()] = $member,
$member instanceof TraitUse => $this->traits[$member->getName()] = $member,
$name = $member->getName();
[$type, $n] = match (true) {
$member instanceof Method => ['methods', strtolower($name)],
$member instanceof Property => ['properties', $name],
$member instanceof Constant => ['consts', $name],
$member instanceof EnumCase => ['cases', $name],
$member instanceof TraitUse => ['traits', $name],
};
if (isset($this->$type[$n])) {
throw new Nette\InvalidStateException("Cannot add member '$name', because it already exists.");
}
$this->$type[$n] = $member;
return $this;
}

Expand Down Expand Up @@ -395,6 +403,9 @@ public function getConstants(): array

public function addConstant(string $name, $value): Constant
{
if (isset($this->consts[$name])) {
throw new Nette\InvalidStateException("Cannot add constant '$name', because it already exists.");
}
return $this->consts[$name] = (new Constant($name))
->setValue($value)
->setPublic();
Expand Down Expand Up @@ -434,6 +445,9 @@ public function getCases(): array
/** Adds case to enum */
public function addCase(string $name, string|int|null $value = null): EnumCase
{
if (isset($this->cases[$name])) {
throw new Nette\InvalidStateException("Cannot add cases '$name', because it already exists.");
}
return $this->cases[$name] = (new EnumCase($name))
->setValue($value);
}
Expand Down Expand Up @@ -483,6 +497,9 @@ public function getProperty(string $name): Property
*/
public function addProperty(string $name, $value = null): Property
{
if (isset($this->properties[$name])) {
throw new Nette\InvalidStateException("Cannot add property '$name', because it already exists.");
}
return $this->properties[$name] = func_num_args() > 1
? (new Property($name))->setValue($value)
: new Property($name);
Expand Down Expand Up @@ -545,12 +562,16 @@ public function getMethod(string $name): Method

public function addMethod(string $name): Method
{
$lower = strtolower($name);
if (isset($this->methods[$lower])) {
throw new Nette\InvalidStateException("Cannot add method '$name', because it already exists.");
}
$method = new Method($name);
if (!$this->isInterface()) {
$method->setPublic();
}

return $this->methods[strtolower($name)] = $method;
return $this->methods[$lower] = $method;
}


Expand Down
10 changes: 6 additions & 4 deletions tests/PhpGenerator/ClassType.addMember.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ require __DIR__ . '/../bootstrap.php';


$class = (new ClassType('Example'))
->addMember($method = new Nette\PhpGenerator\Method('GETHANDLE'))
->addMember($method = new Nette\PhpGenerator\Method('getHandle'))
->addMember($property = new Nette\PhpGenerator\Property('handle'))
->addMember($const = new Nette\PhpGenerator\Constant('ROLE'))
Expand All @@ -23,6 +22,9 @@ Assert::same(['Foo\Bar' => $trait], $class->getTraits());
Assert::same('', $method->getBody());


$class = (new ClassType('Example'))
->setType('interface')
->addMember($method = new Nette\PhpGenerator\Method('getHandle'));
// duplicity
$class = new ClassType('Example');
$class->addMember(new Nette\PhpGenerator\Method('foo'));
Assert::exception(function () use ($class) {
$class->addMember(new Nette\PhpGenerator\Method('FOO'));
}, Nette\InvalidStateException::class, "Cannot add member 'FOO', because it already exists.");
30 changes: 28 additions & 2 deletions tests/PhpGenerator/ClassType.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,33 @@ Assert::exception(function () {
}, Nette\InvalidArgumentException::class, 'Argument must be public|protected|private.');


// duplicity
$class = new ClassType('Example');
$class->addConstant('a', 1);
Assert::exception(function () use ($class) {
$class->addConstant('a', 1);
}, Nette\InvalidStateException::class, "Cannot add constant 'a', because it already exists.");

$class->addProperty('a');
Assert::exception(function () use ($class) {
$class->addProperty('a');
}, Nette\InvalidStateException::class, "Cannot add property 'a', because it already exists.");

$class->addMethod('a');
Assert::exception(function () use ($class) {
$class->addMethod('a');
}, Nette\InvalidStateException::class, "Cannot add method 'a', because it already exists.");

Assert::exception(function () use ($class) {
$class->addMethod('A');
}, Nette\InvalidStateException::class, "Cannot add method 'A', because it already exists.");

$class->addTrait('A');
Assert::exception(function () use ($class) {
$class->addTrait('A');
}, Nette\InvalidStateException::class, "Cannot add trait 'A', because it already exists.");


// remove members
$class = new ClassType('Example');
$class->addConstant('a', 1);
Expand All @@ -188,8 +215,7 @@ $class->removeProperty('b')->removeProperty('c');
Assert::same(['a'], array_keys($class->getProperties()));

$class->addMethod('a');
$class->addMethod('A');
$class->addMethod('b');
$class->removeMethod('B')->removeMethod('c');

Assert::same(['A'], array_keys($class->getMethods()));
Assert::same(['a'], array_keys($class->getMethods()));

0 comments on commit 93166ff

Please sign in to comment.