Skip to content

Commit

Permalink
Fix #126 improve error messages including classname when possible
Browse files Browse the repository at this point in the history
Added ViolationDescription, as input for a Violation
Added a description to the ViolationDescription
 - Only for Expressions where it made sense
  • Loading branch information
annervisser committed Aug 16, 2022
1 parent c76a3cf commit 78b739b
Show file tree
Hide file tree
Showing 26 changed files with 133 additions and 36 deletions.
6 changes: 5 additions & 1 deletion src/Expression/ForClasses/DependsOnlyOnTheseNamespaces.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class DependsOnlyOnTheseNamespaces implements Expression
Expand Down Expand Up @@ -44,7 +45,10 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str
if (!$dependency->matchesOneOf(...$this->namespaces)) {
$violation = Violation::createWithErrorLine(
$theClass->getFQCN(),
$this->describe($theClass, $because)->toString(),
ViolationMessage::withDescription(
$this->describe($theClass, $because),
"depends on {$dependency->getFQCN()->toString()}"
),
$dependency->getLine()
);

Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/DocBlockContains.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class DocBlockContains implements Expression
Expand All @@ -30,7 +31,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str
if (!$theClass->containsDocBlock($this->docBlock)) {
$violation = Violation::create(
$theClass->getFQCN(),
$this->describe($theClass, $because)->toString()
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
);
$violations->add($violation);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/DocBlockNotContains.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class DocBlockNotContains implements Expression
Expand All @@ -30,7 +31,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str
if ($theClass->containsDocBlock($this->docBlock)) {
$violation = Violation::create(
$theClass->getFQCN(),
$this->describe($theClass, $because)->toString()
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
);
$violations->add($violation);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/Extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class Extend implements Expression
Expand Down Expand Up @@ -35,7 +36,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str

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

$violations->add($violation);
Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/HaveAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

final class HaveAttribute implements Expression
Expand All @@ -33,7 +34,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str
$violations->add(
Violation::create(
$theClass->getFQCN(),
$this->describe($theClass, $because)->toString()
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
)
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/HaveNameMatching.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class HaveNameMatching implements Expression
Expand All @@ -32,7 +33,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str
if (!$fqcn->classMatches($this->name)) {
$violation = Violation::create(
$theClass->getFQCN(),
$this->describe($theClass, $because)->toString()
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
);
$violations->add($violation);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/Implement.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class Implement implements Expression
Expand Down Expand Up @@ -37,7 +38,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str
if (0 === \count(array_filter($interfaces, $implements))) {
$violation = Violation::create(
$theClass->getFQCN(),
$this->describe($theClass, $because)->toString()
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
);
$violations->add($violation);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/IsAbstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class IsAbstract implements Expression
Expand All @@ -25,7 +26,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str

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

$violations->add($violation);
Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/IsFinal.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class IsFinal implements Expression
Expand All @@ -25,7 +26,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str

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

$violations->add($violation);
Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/IsNotAbstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class IsNotAbstract implements Expression
Expand All @@ -25,7 +26,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str

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

$violations->add($violation);
Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/IsNotFinal.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class IsNotFinal implements Expression
Expand All @@ -25,7 +26,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str

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

$violations->add($violation);
Expand Down
6 changes: 5 additions & 1 deletion src/Expression/ForClasses/NotDependsOnTheseNamespaces.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class NotDependsOnTheseNamespaces implements Expression
Expand Down Expand Up @@ -41,7 +42,10 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str
if ($dependency->matchesOneOf(...$this->namespaces)) {
$violation = Violation::createWithErrorLine(
$theClass->getFQCN(),
$this->describe($theClass, $because)->toString(),
ViolationMessage::withDescription(
$this->describe($theClass, $because),
"depends on {$dependency->getFQCN()->toString()}"
),
$dependency->getLine()
);

Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/NotExtend.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class NotExtend implements Expression
Expand Down Expand Up @@ -39,7 +40,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str

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

$violations->add($violation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class NotHaveDependencyOutsideNamespace implements Expression
Expand Down Expand Up @@ -47,7 +48,10 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str

$violation = Violation::createWithErrorLine(
$theClass->getFQCN(),
$this->describe($theClass, $because)->toString(),
ViolationMessage::withDescription(
$this->describe($theClass, $because),
"depends on {$externalDep->getFQCN()->toString()}"
),
$externalDep->getLine()
);
$violations->add($violation);
Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/NotHaveNameMatching.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class NotHaveNameMatching implements Expression
Expand All @@ -32,7 +33,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str
if ($fqcn->classMatches($this->name)) {
$violation = Violation::create(
$theClass->getFQCN(),
$this->describe($theClass, $because)->toString()
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
);
$violations->add($violation);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/NotImplement.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class NotImplement implements Expression
Expand Down Expand Up @@ -37,7 +38,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str
if (\count(array_filter($interfaces, $implements)) > 0) {
$violation = Violation::create(
$theClass->getFQCN(),
$this->describe($theClass, $because)->toString()
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
);
$violations->add($violation);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/NotResideInTheseNamespaces.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class NotResideInTheseNamespaces implements Expression
Expand Down Expand Up @@ -39,7 +40,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str
if ($resideInNamespace) {
$violation = Violation::create(
$theClass->getFQCN(),
$this->describe($theClass, $because)->toString()
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
);
$violations->add($violation);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Expression/ForClasses/ResideInOneOfTheseNamespaces.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

class ResideInOneOfTheseNamespaces implements Expression
Expand Down Expand Up @@ -39,7 +40,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str
if (!$resideInNamespace) {
$violation = Violation::create(
$theClass->getFQCN(),
$this->describe($theClass, $because)->toString()
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
);
$violations->add($violation);
}
Expand Down
8 changes: 4 additions & 4 deletions src/Rules/Violation.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ public function __construct(string $fqcn, string $error, ?int $line = null)
$this->line = $line;
}

public static function create(string $fqcn, string $error): self
public static function create(string $fqcn, ViolationMessage $error): self
{
return new self($fqcn, $error);
return new self($fqcn, $error->toString());
}

public static function createWithErrorLine(string $fqcn, string $error, int $line): self
public static function createWithErrorLine(string $fqcn, ViolationMessage $error, int $line): self
{
return new self($fqcn, $error, $line);
return new self($fqcn, $error->toString(), $line);
}

public function getFqcn(): string
Expand Down
40 changes: 40 additions & 0 deletions src/Rules/ViolationMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Arkitect\Rules;

use Arkitect\Expression\Description;

class ViolationMessage
{
/** @var string */
private $rule;
/** @var string|null */
private $violation;

private function __construct(string $rule, ?string $violation)
{
$this->rule = $rule;
$this->violation = $violation;
}

public static function withDescription(Description $brokenRule, string $description): self
{
return new self($brokenRule->toString(), $description);
}

public static function selfExplanatory(Description $brokenRule): self
{
return new self($brokenRule->toString(), null);
}

public function toString(): string
{
if (null === $this->violation) {
return $this->rule;
}

return "$this->violation, but $this->rule";
}
}
4 changes: 2 additions & 2 deletions tests/E2E/Cli/CheckCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public function test_app_returns_error_with_multiple_violations(): void
should implement ContainerAwareInterface because all controllers should be container aware
App\Domain\Model violates rules
should not depend on classes outside namespace App\Domain because we want protect our domain (on line 14)
should not depend on classes outside namespace App\Domain because we want protect our domain (on line 15)';
depends on App\Services\UserService, but should not depend on classes outside namespace App\Domain because we want protect our domain (on line 14)
depends on App\Services\CartService, but should not depend on classes outside namespace App\Domain because we want protect our domain (on line 15)';

$this->assertCheckHasErrors($cmdTester, $expectedErrors);
}
Expand Down
Loading

0 comments on commit 78b739b

Please sign in to comment.