Přechod na DressCode

Stará jména pravidel i potlačovací komentáře fungují dál, konfiguraci převede jeden příkaz a vypíše, co se nepodařilo přenést. Společný postup pro přechod z jakéhokoli nástroje a poctivý seznam toho, co bude jinak.

Proč to nebolí

Vím, jak to vypadá: máte konfiguraci, ve které jsou roky ladění, v kódu stovky komentářů phpcs:ignore, možná pár vlastních sniffů a k tomu CI, které to celé spouští. Nástroj se nemění proto, že je nový hezčí. Mění se, když přechod nebolí, a přesně tak je DressCode postavený.

Klíčová věc: DressCode zná svá pravidla nejen pod vlastním jménem, ale i pod tím, jak se jmenují v PHP CS Fixeru, PHP_CodeSniffer a Slevomatu. Když napíšete dresscode rules, uvidíte u každého pravidla cizí jména, která pokrývá. Z toho plyne všechno ostatní: komentáře v kódu fungují beze změny a konfigurace se dá převést strojově.

Postup má tři kroky a každý z nich se dá vrátit.

1. Kód nechte, jak je

Komentáře // phpcs:ignore, phpcs:disable, phpcs:enable, phpcs:ignoreFile i anotace @phpcsSuppress dělají dál to, co dělaly. DressCode je přečte, cizí jméno pravidla si přeloží na své, a potlačení platí. Do kódu tedy zatím vůbec nemusíte sahat a první kontrolu můžete pustit hned:

dresscode check src tests

Bez konfigurace platí preset dresscode/per, tedy PER Coding Style 3.1. Kdo dosud používal @PER-CS nebo PSR12, uvidí zhruba to, co čekal. Kdo měl doladěno nad rámec standardu, uvidí rozdíly, které vyřeší další krok.

2. Přeložte konfiguraci

Příkaz import přečte cizí konfiguraci a vypíše její ekvivalent pro DressCode:

dresscode import phpcs.xml > dresscode.php
dresscode import .php-cs-fixer.dist.php > dresscode.php

phpcs.xml je XML, takže se přečte bez čehokoli dalšího. Naproti tomu .php-cs-fixer.dist.php je PHP, které se musí spustit a které vrací objekt cizí knihovny; import na něm funguje jen v projektu, kde je ta knihovna ještě nainstalovaná. Proto konfiguraci překládejte dřív, než starý nástroj odeberete.

Na standardní výstup jde hotová konfigurace, na chybový výstup to, co se přenést nepodařilo:

<?php declare(strict_types=1);

use DressCode\Config;

return Config::create()
	->preset('dresscode/psr12')
	->enable('dresscode/line-length', ['limit' => 100])
	->enable('dresscode/unused-imports', ['searchAnnotations' => false]);

Read 4 rules, enabled 2 and 1 preset.
  No DressCode rule covers Squiz.Commenting.FunctionComment.

Druhý seznam je stejně cenný jako první: říká, kde se musíte rozhodnout. Pravidlo bez protějšku buď nepotřebujete, nebo si ho napíšete. Sady jako @PSR12 nebo PSR12 se překládají na presety; u sad, které protějšek nemají (třeba @PhpCsFixer), to import ohlásí a doporučí začít od dresscode/per.

Přeložené volby s sebou nesou i hodnoty (lineLimit se stane limit), ale ne každá cizí volba protějšek má; i to import vypíše. Výsledný soubor si projděte, je krátký.

3. Přepište komentáře

Komentáře v kódu fungují i se starými jmény, nové jsou ale kratší a čitelnější. Přepis udělá jeden příkaz:

dresscode migrate-suppressions src tests

Z phpcs:ignore SlevomatCodingStandard.Namespaces.UnusedUses se stane dresscode:ignore dresscode/unused-imports, z phpcs:disable a phpcs:enable se stanou dresscode:disable a dresscode:enable, z phpcs:ignoreFile pak dresscode:ignore-file. Jméno, které žádné pravidlo nepokrývá, zůstane, jak bylo, a příkaz ho vypíše. Z toho výpisu máte seznam potlačení, která už nic nepotlačují.

První oprava

Až konfigurace sedí, pusťte dresscode fix a výsledek commitněte samostatně, bez jiných změn. I u pravidla, které je „stejné“, může oprava vyjít o mezeru jinak než u starého nástroje, a procházet to řádek po řádku nemá smysl. Smysl má vědět, že v tom commitu není nic jiného. U velkého projektu, kde by byl takový commit neúnosný, použijte baseline: dnešní porušení se zapíšou a hlásit se budou jen nová.

Co bude jinak

Návod, který slibuje bezešvý přechod, ztratí důvěru u prvního rozdílu, tak raději rovnou:

  • Priority neexistují. Kdo si výsledek stavěl na pořadí fixerů, dostane u některých souborů jiný tvar kódu. Pravidla tu běží opakovaně, dokud se výsledek neustálí; proč.
  • Pravidla bez protějšku vypíše import i migrate-suppressions. Není jich málo, hlavně mezi sniffy o dokumentaci a mezi pravidly, kterými se nástroje navzájem překrývají.
  • Rizikové (risky) pravidlo tu rizikové být nemusí. Co PHP CS Fixer zapínal jen na výslovnou žádost, protože nad tokeny nerozeznal bezpečný případ od nebezpečného, rozhoduje tady strom, a pravidlo opraví jen ty bezpečné. Naopak pravidlo, které mění chování programu ze své podstaty (strict-comparison dělá z == ===), zůstává vaším rozhodnutím, ať ho zapnete kdekoli.
  • Exit kódy jsou jiné: 0 čisto, 1 porušení, 2 selhání nástroje. PHP_CodeSniffer i PHP CS Fixer mají vlastní stupnice, takže skript, který je vyhodnocuje, potřebuje jednu úpravu.
  • Jeden nástroj místo dvou. Kdo kombinoval CodeSniffer a Fixer, měl dvě konfigurace a dva kroky v CI. Teď je jedna a jeden.

Podrobnosti pro konkrétní nástroj: PHP CS Fixer, PHP_CodeSniffer a Slevomat, Nette Coding Standard.

verze: 1.0