Skip to content

Commit

Permalink
Merge pull request phparkitect#422 from helyakin/feature/addIsReadonl…
Browse files Browse the repository at this point in the history
…yCheck

feature: Add IsReadonly Expression
  • Loading branch information
fain182 authored Jan 24, 2024
2 parents 8f13907 + f16c7f9 commit b78ecce
Show file tree
Hide file tree
Showing 26 changed files with 348 additions and 0 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,15 @@ $rules[] = Rule::allClasses()
->because('we want to be sure that aggregates are final classes');
```

### Is readonly

```php
$rules[] = Rule::allClasses()
->that(new ResideInOneOfTheseNamespaces('App\Domain\ValueObjects'))
->should(new IsReadonly())
->because('we want to be sure that value objects are readonly classes');
```

### Is interface

```php
Expand Down Expand Up @@ -296,6 +305,15 @@ $rules[] = Rule::allClasses()
->because('we want to be sure that our adapters are not final classes');
```

### Is not readonly

```php
$rules[] = Rule::allClasses()
->that(new ResideInOneOfTheseNamespaces('App\Domain\Entity'))
->should(new IsNotReadonly())
->because('we want to be sure that there are no readonly entities');
```

### Is not interface

```php
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzer/ClassDescription.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ class ClassDescription
/** @var bool */
private $final;

/** @var bool */
private $readonly;

/** @var bool */
private $abstract;

Expand Down Expand Up @@ -50,6 +53,7 @@ public function __construct(
array $interfaces,
?FullyQualifiedClassName $extends,
bool $final,
bool $readonly,
bool $abstract,
bool $interface,
bool $trait,
Expand All @@ -62,6 +66,7 @@ public function __construct(
$this->interfaces = $interfaces;
$this->extends = $extends;
$this->final = $final;
$this->readonly = $readonly;
$this->abstract = $abstract;
$this->docBlock = $docBlock;
$this->attributes = $attributes;
Expand Down Expand Up @@ -130,6 +135,11 @@ public function isFinal(): bool
return $this->final;
}

public function isReadonly(): bool
{
return $this->readonly;
}

public function isAbstract(): bool
{
return $this->abstract;
Expand Down
12 changes: 12 additions & 0 deletions src/Analyzer/ClassDescriptionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ class ClassDescriptionBuilder
/** @var bool */
private $final = false;

/** @var bool */
private $readonly = false;

/** @var bool */
private $abstract = false;

Expand All @@ -47,6 +50,7 @@ public function clear(): void
$this->interfaces = [];
$this->extend = null;
$this->final = false;
$this->readonly = false;
$this->abstract = false;
$this->docBlock = [];
$this->attributes = [];
Expand Down Expand Up @@ -92,6 +96,13 @@ public function setFinal(bool $final): self
return $this;
}

public function setReadonly(bool $readonly): self
{
$this->readonly = $readonly;

return $this;
}

public function setAbstract(bool $abstract): self
{
$this->abstract = $abstract;
Expand Down Expand Up @@ -145,6 +156,7 @@ public function build(): ClassDescription
$this->interfaces,
$this->extend,
$this->final,
$this->readonly,
$this->abstract,
$this->interface,
$this->trait,
Expand Down
4 changes: 4 additions & 0 deletions src/Analyzer/FileVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ public function enterNode(Node $node): void
$this->classDescriptionBuilder->setFinal(true);
}

if ($node->isReadonly()) {
$this->classDescriptionBuilder->setReadonly(true);
}

if ($node->isAbstract()) {
$this->classDescriptionBuilder->setAbstract(true);
}
Expand Down
34 changes: 34 additions & 0 deletions src/Expression/ForClasses/IsNotReadonly.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Arkitect\Expression\ForClasses;

use Arkitect\Analyzer\ClassDescription;
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class IsNotReadonly implements Expression
{
public function describe(ClassDescription $theClass, string $because): Description
{
return new Description("{$theClass->getName()} should not be readonly", $because);
}

public function evaluate(ClassDescription $theClass, Violations $violations, string $because): void
{
if (!$theClass->isReadonly()) {
return;
}

$violation = Violation::create(
$theClass->getFQCN(),
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
);

$violations->add($violation);
}
}
34 changes: 34 additions & 0 deletions src/Expression/ForClasses/IsReadonly.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Arkitect\Expression\ForClasses;

use Arkitect\Analyzer\ClassDescription;
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class IsReadonly implements Expression
{
public function describe(ClassDescription $theClass, string $because): Description
{
return new Description("{$theClass->getName()} should be readonly", $because);
}

public function evaluate(ClassDescription $theClass, Violations $violations, string $because): void
{
if ($theClass->isReadonly()) {
return;
}

$violation = Violation::create(
$theClass->getFQCN(),
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
);

$violations->add($violation);
}
}
3 changes: 3 additions & 0 deletions tests/Unit/Expressions/ForClasses/ContainDocBlockLikeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function test_it_should_return_true_if_contains_doc_block(): void
false,
false,
false,
false,
['/** */myDocBlock with other information']
);
$because = 'we want to add this rule for our software';
Expand Down Expand Up @@ -53,6 +54,7 @@ public function test_it_should_return_true_if_contains_doc_block_without_because
false,
false,
false,
false,
['/** */myDocBlock with other information']
);
$violations = new Violations();
Expand All @@ -79,6 +81,7 @@ public function test_it_should_return_false_if_not_contains_doc_block(): void
false,
false,
false,
false,
['/** */myDocBlock with other information']
);
$because = 'we want to add this rule for our software';
Expand Down
1 change: 1 addition & 0 deletions tests/Unit/Expressions/ForClasses/ExtendTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public function test_it_should_return_violation_error_if_extend_is_null(): void
false,
false,
false,
false,
false
);

Expand Down
3 changes: 3 additions & 0 deletions tests/Unit/Expressions/ForClasses/HaveAttributeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function test_it_should_return_true_if_contains_doc_block(): void
false,
false,
false,
false,
[],
[FullyQualifiedClassName::fromString('myAttribute')]
);
Expand Down Expand Up @@ -54,6 +55,7 @@ public function test_it_should_return_true_if_contains_doc_block_without_because
false,
false,
false,
false,
[],
[FullyQualifiedClassName::fromString('myAttribute')]
);
Expand Down Expand Up @@ -81,6 +83,7 @@ public function test_it_should_return_false_if_not_contains_doc_block(): void
false,
false,
false,
false,
[],
[FullyQualifiedClassName::fromString('myAttribute')]
);
Expand Down
5 changes: 5 additions & 0 deletions tests/Unit/Expressions/ForClasses/ImplementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function test_it_should_return_violation_error(): void
false,
false,
false,
false,
false
);

Expand Down Expand Up @@ -53,6 +54,7 @@ public function test_it_should_return_true_if_not_depends_on_namespace(): void
false,
false,
false,
false,
false
);
$because = 'we want to add this rule for our software';
Expand All @@ -75,6 +77,7 @@ public function test_it_should_return_false_if_depends_on_namespace(): void
false,
false,
false,
false,
false
);
$because = 'we want to add this rule for our software';
Expand All @@ -98,6 +101,7 @@ public function test_it_should_check_the_complete_fqcn(): void
false,
false,
false,
false,
false
);
$violations = new Violations();
Expand All @@ -118,6 +122,7 @@ public function test_it_should_return_if_is_an_interface(): void
false,
false,
false,
false,
true,
false
);
Expand Down
2 changes: 2 additions & 0 deletions tests/Unit/Expressions/ForClasses/IsAbstractTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public function test_it_should_return_violation_error(): void
false,
false,
false,
false,
false
);
$because = 'we want to add this rule for our software';
Expand All @@ -46,6 +47,7 @@ public function test_it_should_return_true_if_is_abstract(): void
null,
true,
true,
true,
false,
false,
false
Expand Down
2 changes: 2 additions & 0 deletions tests/Unit/Expressions/ForClasses/IsEnumTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public function test_it_should_return_violation_error(): void
false,
false,
false,
false,
false
);
$because = 'we want to add this rule for our software';
Expand All @@ -47,6 +48,7 @@ public function test_it_should_return_true_if_is_enum(): void
false,
false,
false,
false,
true
);
$because = 'we want to add this rule for our software';
Expand Down
6 changes: 6 additions & 0 deletions tests/Unit/Expressions/ForClasses/IsFinalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public function test_it_should_return_violation_error(): void
false,
false,
false,
false,
false
);
$because = 'we want to add this rule for our software';
Expand All @@ -50,6 +51,7 @@ public function test_it_should_return_true_if_is_final(): void
false,
false,
false,
false,
false
);
$because = 'we want to add this rule for our software';
Expand All @@ -69,6 +71,7 @@ public function test_abstract_classes_can_not_be_final_and_should_be_ignored():
[],
null,
false,
false,
true,
false,
false,
Expand All @@ -92,6 +95,7 @@ public function test_interfaces_can_not_be_final_and_should_be_ignored(): void
null,
false,
false,
false,
true,
false,
false
Expand All @@ -115,6 +119,7 @@ public function test_traits_can_not_be_final_and_should_be_ignored(): void
false,
false,
false,
false,
true,
false
);
Expand All @@ -138,6 +143,7 @@ public function test_enums_can_not_be_final_and_should_be_ignored(): void
false,
false,
false,
false,
true
);
$because = 'we want to add this rule for our software';
Expand Down
2 changes: 2 additions & 0 deletions tests/Unit/Expressions/ForClasses/IsInterfaceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public function test_it_should_return_violation_error(): void
false,
false,
false,
false,
false
);
$because = 'we want to add this rule for our software';
Expand All @@ -46,6 +47,7 @@ public function test_it_should_return_true_if_is_interface(): void
null,
false,
false,
false,
true,
false,
false
Expand Down
2 changes: 2 additions & 0 deletions tests/Unit/Expressions/ForClasses/IsNotAbstractTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public function test_it_should_return_violation_error(): void
[],
null,
true,
false,
true,
false,
false,
Expand Down Expand Up @@ -48,6 +49,7 @@ public function test_it_should_return_true_if_is_abstract(): void
false,
false,
false,
false,
false
);
$because = 'we want to add this rule for our software';
Expand Down
Loading

0 comments on commit b78ecce

Please sign in to comment.