From 9c2263d0816469251ebeebf76022cc4f30baf1e6 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kondas Date: Sun, 28 May 2023 12:01:10 +0200 Subject: [PATCH 1/3] Implmenet logical or expression --- src/Expression/Boolean/Orx.php | 43 ++++++++++++++++++++++ tests/Unit/Expressions/Boolean/OrxTest.php | 28 ++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 src/Expression/Boolean/Orx.php create mode 100644 tests/Unit/Expressions/Boolean/OrxTest.php diff --git a/src/Expression/Boolean/Orx.php b/src/Expression/Boolean/Orx.php new file mode 100644 index 00000000..02773912 --- /dev/null +++ b/src/Expression/Boolean/Orx.php @@ -0,0 +1,43 @@ +expressions = $expressions; + } + + public function describe(ClassDescription $theClass, string $because): Description + { + return new Description('at least one expression must be true', $because); + } + + public function evaluate(ClassDescription $theClass, Violations $violations, string $because): void + { + foreach ($this->expressions as $expression) { + $newViolations = new Violations(); + $expression->evaluate($theClass, $newViolations, $because); + if (0 === $newViolations->count()) { + return; + } + } + + $violations->add(Violation::create( + $theClass->getFQCN(), + ViolationMessage::selfExplanatory($this->describe($theClass, $because)) + )); + } +} diff --git a/tests/Unit/Expressions/Boolean/OrxTest.php b/tests/Unit/Expressions/Boolean/OrxTest.php new file mode 100644 index 00000000..5cbe4fd7 --- /dev/null +++ b/tests/Unit/Expressions/Boolean/OrxTest.php @@ -0,0 +1,28 @@ +setClassName('My\Class') + ->setExtends('My\BaseClass', 10) + ->build(); + + $violations = new Violations(); + $or->evaluate($classDescription, $violations, 'because'); + + self::assertEquals(0, $violations->count()); + } +} From 2a6c4ee7a56020c16d06ae982cae32aab6c6ddd0 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kondas Date: Wed, 31 May 2023 18:00:53 +0200 Subject: [PATCH 2/3] Fix code style --- src/Analyzer/ClassDescriptionBuilder.php | 4 ++-- src/Analyzer/FileVisitor.php | 20 +++++++++---------- src/Analyzer/NameResolver.php | 4 +--- src/Analyzer/PatternString.php | 8 ++++---- .../DependsOnlyOnTheseNamespaces.php | 4 ++-- src/Rules/Violation.php | 2 +- tests/E2E/Cli/CheckCommandTest.php | 2 +- .../ResideInOneOfTheseNamespacesTest.php | 4 ---- 8 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/Analyzer/ClassDescriptionBuilder.php b/src/Analyzer/ClassDescriptionBuilder.php index d754d11a..dce71533 100644 --- a/src/Analyzer/ClassDescriptionBuilder.php +++ b/src/Analyzer/ClassDescriptionBuilder.php @@ -11,13 +11,13 @@ class ClassDescriptionBuilder private $classDependencies = []; /** @var ?FullyQualifiedClassName */ - private $FQCN = null; + private $FQCN; /** @var list */ private $interfaces = []; /** @var ?FullyQualifiedClassName */ - private $extend = null; + private $extend; /** @var bool */ private $final = false; diff --git a/src/Analyzer/FileVisitor.php b/src/Analyzer/FileVisitor.php index 222c4c87..d729038f 100644 --- a/src/Analyzer/FileVisitor.php +++ b/src/Analyzer/FileVisitor.php @@ -72,8 +72,8 @@ public function enterNode(Node $node): void * * @see FileVisitorTest::test_it_should_return_errors_for_const_outside_namespace */ - if ($node instanceof Node\Expr\ClassConstFetch && - method_exists($node->class, 'toString') + if ($node instanceof Node\Expr\ClassConstFetch + && method_exists($node->class, 'toString') ) { if ($this->isSelfOrStaticOrParent($node->class->toString())) { return; @@ -89,8 +89,8 @@ public function enterNode(Node $node): void * * @see FileVisitorTest::test_should_returns_all_dependencies */ - if ($node instanceof Node\Expr\StaticCall && - method_exists($node->class, 'toString') + if ($node instanceof Node\Expr\StaticCall + && method_exists($node->class, 'toString') ) { if ($this->isSelfOrStaticOrParent($node->class->toString())) { return; @@ -100,8 +100,8 @@ public function enterNode(Node $node): void ->addDependency(new ClassDependency($node->class->toString(), $node->getLine())); } - if ($node instanceof Node\Expr\Instanceof_ && - method_exists($node->class, 'toString') + if ($node instanceof Node\Expr\Instanceof_ + && method_exists($node->class, 'toString') ) { if ($this->isSelfOrStaticOrParent($node->class->toString())) { return; @@ -110,11 +110,11 @@ public function enterNode(Node $node): void ->addDependency(new ClassDependency($node->class->toString(), $node->getLine())); } - if ($node instanceof Node\Expr\New_ && - !($node->class instanceof Node\Expr\Variable) + if ($node instanceof Node\Expr\New_ + && !($node->class instanceof Node\Expr\Variable) ) { - if ((method_exists($node->class, 'isAnonymous') && $node->class->isAnonymous()) || - !method_exists($node->class, 'toString')) { + if ((method_exists($node->class, 'isAnonymous') && $node->class->isAnonymous()) + || !method_exists($node->class, 'toString')) { return; } diff --git a/src/Analyzer/NameResolver.php b/src/Analyzer/NameResolver.php index bc367b40..e6f88c3f 100644 --- a/src/Analyzer/NameResolver.php +++ b/src/Analyzer/NameResolver.php @@ -175,7 +175,7 @@ public function enterNode(Node $node) if ($this->parseCustomAnnotations && !($node->type instanceof FullyQualified)) { foreach ($phpDocNode->getTags() as $tagValue) { - if ('@' === $tagValue->name[0] && false === strpos($tagValue->name, '@var')) { + if ('@' === $tagValue->name[0] && !str_contains($tagValue->name, '@var')) { $customTag = str_replace('@', '', $tagValue->name); $type = $this->resolveName(new Node\Name($customTag), Use_::TYPE_NORMAL); $node->type = $type; @@ -365,8 +365,6 @@ private function resolveSignature($node): void * @psalm-suppress MissingParamType * @psalm-suppress PossiblyNullArgument * @psalm-suppress MissingReturnType - * - * @param mixed $node */ private function resolveType($node) { diff --git a/src/Analyzer/PatternString.php b/src/Analyzer/PatternString.php index 50c97481..60ab84c7 100644 --- a/src/Analyzer/PatternString.php +++ b/src/Analyzer/PatternString.php @@ -38,10 +38,10 @@ public function toString(): string private function containsWildcard(string $pattern): bool { return - str_contains($pattern, '*') || - str_contains($pattern, '?') || - str_contains($pattern, '.') || - str_contains($pattern, '['); + str_contains($pattern, '*') + || str_contains($pattern, '?') + || str_contains($pattern, '.') + || str_contains($pattern, '['); } private function startsWithPattern(string $pattern): bool diff --git a/src/Expression/ForClasses/DependsOnlyOnTheseNamespaces.php b/src/Expression/ForClasses/DependsOnlyOnTheseNamespaces.php index 646a36b2..55a346f3 100644 --- a/src/Expression/ForClasses/DependsOnlyOnTheseNamespaces.php +++ b/src/Expression/ForClasses/DependsOnlyOnTheseNamespaces.php @@ -36,8 +36,8 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str /** @var ClassDependency $dependency */ foreach ($dependencies as $dependency) { if ( - '' === $dependency->getFQCN()->namespace() || - $theClass->namespaceMatches($dependency->getFQCN()->namespace()) + '' === $dependency->getFQCN()->namespace() + || $theClass->namespaceMatches($dependency->getFQCN()->namespace()) ) { continue; } diff --git a/src/Rules/Violation.php b/src/Rules/Violation.php index dd1bfb8f..f91d2a5e 100644 --- a/src/Rules/Violation.php +++ b/src/Rules/Violation.php @@ -15,7 +15,7 @@ class Violation implements \JsonSerializable /** @var string */ private $error; - public function __construct(string $fqcn, string $error, ?int $line = null) + public function __construct(string $fqcn, string $error, int $line = null) { $this->fqcn = $fqcn; $this->error = $error; diff --git a/tests/E2E/Cli/CheckCommandTest.php b/tests/E2E/Cli/CheckCommandTest.php index 86ff4bc2..ffc479f1 100644 --- a/tests/E2E/Cli/CheckCommandTest.php +++ b/tests/E2E/Cli/CheckCommandTest.php @@ -149,7 +149,7 @@ public function test_you_can_ignore_the_default_baseline(): void protected function runCheck( $configFilePath = null, bool $stopOnFailure = null, - ?string $useBaseline = null, + string $useBaseline = null, $generateBaseline = false, bool $skipBaseline = false ): ApplicationTester { diff --git a/tests/Unit/Expressions/ForClasses/ResideInOneOfTheseNamespacesTest.php b/tests/Unit/Expressions/ForClasses/ResideInOneOfTheseNamespacesTest.php index 95b526ff..e9e19b93 100644 --- a/tests/Unit/Expressions/ForClasses/ResideInOneOfTheseNamespacesTest.php +++ b/tests/Unit/Expressions/ForClasses/ResideInOneOfTheseNamespacesTest.php @@ -30,10 +30,6 @@ public function shouldMatchNamespacesProvider(): array /** * @dataProvider shouldMatchNamespacesProvider - * - * @param mixed $expectedNamespace - * @param mixed $actualFQCN - * @param mixed $explanation */ public function test_it_should_match_namespace_and_descendants($expectedNamespace, $actualFQCN, $explanation): void { From 55c8e745685346ccc57e839668abc0ceea515b75 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kondas Date: Sat, 24 Jun 2023 20:08:43 +0200 Subject: [PATCH 3/3] Require at least two expressions --- src/Expression/Boolean/Orx.php | 3 +++ tests/Unit/Expressions/Boolean/OrxTest.php | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/Expression/Boolean/Orx.php b/src/Expression/Boolean/Orx.php index 02773912..0926ccff 100644 --- a/src/Expression/Boolean/Orx.php +++ b/src/Expression/Boolean/Orx.php @@ -17,6 +17,9 @@ final class Orx implements Expression public function __construct(array $expressions) { + if (\count($expressions) <= 1) { + throw new \InvalidArgumentException('at least two expression are required'); + } $this->expressions = $expressions; } diff --git a/tests/Unit/Expressions/Boolean/OrxTest.php b/tests/Unit/Expressions/Boolean/OrxTest.php index 5cbe4fd7..3ac0dd77 100644 --- a/tests/Unit/Expressions/Boolean/OrxTest.php +++ b/tests/Unit/Expressions/Boolean/OrxTest.php @@ -11,6 +11,20 @@ final class OrxTest extends TestCase { + public function test_it_should_throw_exception_if_no_expressions_provided(): void + { + $this->expectException(\InvalidArgumentException::class); + + new Orx([]); + } + + public function test_it_should_throw_exception_if_only_one_expression_provided(): void + { + $this->expectException(\InvalidArgumentException::class); + + new Orx([new Extend('My\BaseClass')]); + } + public function test_it_should_return_no_violation_on_success(): void { $or = new Orx([new Extend('My\BaseClass'), new Extend('Your\OtherClass')]);