-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathphparkitect-rules-optional.php
More file actions
47 lines (42 loc) · 1.99 KB
/
Copy pathphparkitect-rules-optional.php
File metadata and controls
47 lines (42 loc) · 1.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php
declare(strict_types=1);
/**
* php-qa-ci PHPArkitect — OPTIONAL generic ruleset (the "rules-optional" tier).
*
* Stricter, opinionated naming conventions that are NOT safe to force on every
* project, so they are OPT-IN — a project enables them by composing this file
* into its qaConfig/phparkitect.php (mirrors rules-optional.neon for PHPStan):
*
* $default = require getenv('PHPQACI_ARKITECT_RULES_DEFAULT');
* $optional = require getenv('PHPQACI_ARKITECT_RULES_OPTIONAL');
* $config->add($classSet, ...$default, ...$optional, ...$projectRules);
*
* This is a curated set meant to grow. Keep each rule generic (no project
* namespaces); project-specific rules belong in the project's own config.
*
* NOTE: the *Exception rule below keys off `IsA(\Throwable)`, which makes
* PHPArkitect resolve each class's ancestry — so it requires a COMPLETE
* autoloader (a class implementing/extending a type missing from
* vendor/autoload.php aborts the run). That fragility is exactly why it is
* opt-in here rather than in the safe-everywhere default tier.
*
* @return list<\Arkitect\Rules\ArchRule>
*/
use Arkitect\Expression\ForClasses\HaveNameMatching;
use Arkitect\Expression\ForClasses\IsA;
use Arkitect\Expression\ForClasses\IsAbstract;
use Arkitect\Rules\Rule;
return [
// Every \Throwable is suffixed *Exception, so throw/catch sites and
// signatures are unambiguous. (Ancestry-resolving — see NOTE above.)
Rule::allClasses()
->that(new IsA(\Throwable::class))
->should(new HaveNameMatching('*Exception'))
->because('a consistent Exception suffix makes throw/catch sites and signatures unambiguous'),
// Abstract classes are prefixed Abstract*, so the abstract-ness of a base
// type is obvious at the use site without opening the file.
Rule::allClasses()
->that(new IsAbstract())
->should(new HaveNameMatching('Abstract*'))
->because('an Abstract prefix signals a non-instantiable base type at every use site'),
];