Vlastní preset a rozšíření
Jak zabalit vlastní pravidla a styl do presetu, jak z něj udělat rozšíření (extension), rozdávat ho přes Composer a nechat uživatele zapnout ho jediným řádkem.
Preset
Preset je třída s atributem #[PresetInfo], která vrátí sadu 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' => version_compare($context->getPhpVersion(), '8.1', '>='),
];
}
public function getParents(): array
{
return [Per::class];
}
}
- Rodičovské presety se použijí nejdřív. Potomek pak přepisuje celé položky, takže se volby nikdy neslučují. Pořadí pravidel odpovídá 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.
- Hodnotou je
true,false, mapa voleb, nebo továrnafn(): Rulepro pravidlo se závislostmi. indentaeolv atributuPresetInfoje styl, se kterým preset počítá; konfigurace projektu ho může přepsat.
Poslední řádek ukázky je vlastně zbytečný: pravidlo s minPhpVersion se pod svou verzí vynechá samo.
PresetContext se hodí spíš tam, kde má preset pod různými verzemi PHP zapínat různá pravidla nebo jim dávat
jiné volby. Verze je řetězec ve tvaru major.minor a porovnává se funkcí version_compare().
Preset se dá zapnout názvem třídy, dokud nemá rozšíření, které mu dá jméno:
presets:
- Acme\CodeStyle\HousePreset
Rozšíření
Rozšíření (extension) je to, co balíček dodá místo konfiguračního souboru: třída s metodou
__invoke(), která dostane prázdný objekt Config a nastaví do něj, co uzná za vhodné. Takhle
vypadá rozšíření Nette Coding Standardu:
namespace Nette\CodingStandard;
use DressCode\Config;
final class Extension
{
public function __invoke(Config $config): void
{
$config
->registerPresets([Presets\CleanCode::class, Presets\OptimizeFn::class, Presets\Types::class])
->excludePaths(['expected', 'tmp', 'fixtures*'])
->skipWhen(PhpVersionFilter::create());
}
}
Všimněte si, co tam není: žádné volání preset(). Rozšíření dělá jména dostupnými a
nastavuje výchozí hodnoty, ale který styl se nakonec použije, je rozhodnutí projektu. Uživatel rozšíření zapne jedním
řádkem a presety si vybere sám:
extensions:
- Nette\CodingStandard\Extension
presets:
- dresscode/nette
- nette/clean-code
Rozšíření může nastavit cokoli, co umí Config: zaregistrovat pravidla (registerRules()) a
presety (registerPresets()), zapnout preset, přidat vyloučené cesty, přípony souborů, filtr
skipWhen podle obsahu souboru nebo analýzu s továrnou. Všechno, co nastaví, je vrstva pod konfigurací
projektu, takže to projekt může přepsat. Výjimkou jsou vyloučené cesty, které se jen sčítají. Na pořadí rozšíření
v konfiguraci nezáleží a rozšíření, které zapnulo jiné rozšíření, se použije jen jednou.
Anonymní funkce patří sem, ne do NEONu: filtr skipWhen, továrna pravidla se závislostmi, továrna analýzy.
NEON deklaruje, rozšíření implementuje.
Balíček
Balíček s presetem nebo s pravidly je obyčejný Composer balíček, který vyž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ř jsou třídy pravidel, presety, rozšíření a fixtury s testy. Jména pravidel nesou vendor balíčku
(acme/…), aby se nesrazila s jinými. A kdo chce, aby uživatel po composer require nemusel psát
ani řádek extensions, přidá do composer.json balíčku záznam, podle kterého si DressCode
rozšíření najde sám:
{
"extra": {
"dresscode": {
"extensions": ["Acme\\CodeStyle\\Extension"]
}
}
}
Automaticky nalezené rozšíření se chová stejně jako ručně zapsané. U každého pravidla pak
dresscode rules řekne, odkud přišlo.