Preset a balík
Jak zabalit vlastní pravidla a styl do presetu a extension, distribuovat je přes Composer a nechat uživatele zapnout je jedním řádkem.
Preset
Preset je třída s atributem #[PresetInfo], která vrátí seznam pravidel s volbami a může vycházet
z jiných presetů:
namespace Acme\CodeStyle;
use DressCode\Preset;
use DressCode\PresetContext;
use DressCode\PresetInfo;
use DressCode\Presets\Per;
#[PresetInfo('acme/house', 'The Acme house style', indent: "\t", eol: "\n")]
final class HousePreset implements Preset
{
public function getRules(PresetContext $context): array
{
return [
'dresscode/ordered-imports' => true,
'dresscode/line-length' => ['limit' => 100],
'dresscode/no-alternative-syntax' => false,
ExceptionMessagePeriodRule::class => true,
'dresscode/octal-notation' => $context->getPhpVersion()->isAtLeast('8.1'),
];
}
public function getParents(): array
{
return [Per::class];
}
}
- Rodiče se použijí napřed; potomek přepisuje celé položky, takže volby se nikdy neslučují. Pořadí pravidel je pořadí první zmínky.
- Vestavěná pravidla lze uvést jménem, vlastní názvem třídy; jméno vlastního pravidla se zaregistruje při první zmínce.
- Hodnota může být
true,false, mapa voleb, nebo továrnafn(): Rulepro pravidlo se závislostmi. indentaeolvPresetInfoje styl, který preset předpokládá; konfigurace ho může přepsat.
Poslední řádek ukázky není potřeba: pravidlo s minPhpVersion se pod svou verzí vynechá samo.
PresetContext se hodí, když má preset pod různými verzemi PHP zapínat různá pravidla nebo volby.
Preset zapnete názvem třídy, dokud nemá extension, která ho zaregistruje jménem:
presets:
- Acme\CodeStyle\HousePreset
Extension
Extension je to, co balíček dodá místo konfiguračního souboru: invokable třída, která dostane prázdný
Config a nastaví do něj, co uzná za vhodné. Tak vypadá extension Nette Coding Standardu:
namespace Nette\CodingStandard;
use DressCode\Config;
final class Extension
{
public function __invoke(Config $config): void
{
$config
->registerPresets([Presets\Php::class, Presets\CleanCode::class, Presets\OptimizeFn::class, Presets\Types::class])
->preset('nette/php')
->excludePaths(['expected', 'tmp', 'fixtures*'])
->skipWhen(PhpVersionFilter::create());
}
}
Uživatel ji zapne jedním řádkem a dál pracuje se jmény, která zaregistrovala:
extensions:
- Nette\CodingStandard\Extension
presets:
- nette/clean-code
Extension může nastavit cokoli, co umí Config: registrovat pravidla (registerRules()) a presety
(registerPresets()), zapnout preset, přidat vyloučené cesty, přípony souborů, skipWhen podle
obsahu, analýzu s továrnou. Všechno, co nastaví, je vrstva pod konfigurací projektu: projekt cokoli z toho
přepíše, s výjimkou vyloučených cest, které se jen sčítají. Pořadí, v jakém se extensions v konfiguraci
uvádějí, nehraje roli; extension, kterou zapne jiná extension, se použije jednou.
Closures patří sem, ne do NEONu: skipWhen, továrna pravidla se závislostmi, továrna analýzy. NEON deklaruje,
extension implementuje.
Balíček
Balíček s presetem nebo pravidly je obyčejný Composer balíček, který požaduje dresscode/dresscode a
sdílí s projektem autoloader:
{
"name": "acme/code-style",
"require": {
"dresscode/dresscode": "^1.0"
},
"autoload": {
"psr-4": {"Acme\\CodeStyle\\": "src/"}
}
}
Uvnitř třídy pravidel, presety, extension a fixtury s testy. Jména pravidel nesou vendor balíčku
(acme/…), aby se nesrazila s jinými. Kdo chce, aby uživatel po composer require nemusel psát ani
řádek extensions, přidá do composer.json balíčku hint, podle kterého DressCode extension
najde sám:
{
"extra": {
"dresscode": {
"extensions": ["Acme\\CodeStyle\\Extension"]
}
}
}
Automaticky nalezená extension se chová stejně jako zapsaná; dresscode rules u každého pravidla řekne,
odkud přišlo.