Příkazová řádka
Příkazy check a fix, výpis toho, co konfigurace znamená, vysvětlení pravidel
s příkladem na terminál i jako dokument, převod cizí konfigurace, všechny přepínače, formáty výstupu pro terminál
i pro CI, exit kódy, cache a paralelní běh.
Příkazy
dresscode check [cesty...]
dresscode fix [cesty...]
dresscode config
dresscode explain [pravidlo]
dresscode rules
dresscode init
dresscode import <soubor>
dresscode migrate-suppressions [cesty...]
dresscode lsp
checkohlásí porušení a nic nezapíše.fixopraví, co pravidla umějí, a zbytek ohlásí. Soubor se zapíše jen tehdy, když se změnil a výsledek se znovu naparsuje na totéž; soubor se syntaktickou chybou nebo s pravidlem, které selhalo, zůstane nedotčený, a stejně tak soubor, který mezitím uložil editor nebo jiný nástroj.configvypíše, k čemu konfigurace vede: která pravidla běží, s jakými volbami, kdo je nastavil a co přebil, a proč ostatní neběží. Viz níže.explainřekne o pravidle, k čemu je, jaké má v tomhle projektu volby a ukáže příklad před opravou a po ní; bez jména pravidla totéž o všech pravidlech, která běží. Viz níže.rulesvypíše všechna známá pravidla: hvězdičkou označí ta, která v aktuální konfiguraci platí, a u každého uvede fázi, popis a jména pravidel jiných nástrojů, která pokrývá. Hodí se, když hledáte, jak se co jmenuje.initnapíšedresscode.neonpodle toho, jak je projekt psaný: odsazení, uvozovky a tvar podmínek změří na vzorku souborů. Viz níže.importpřevede konfiguraci PHP CS Fixeru nebo PHP_CodeSniffer, viz Přechod na DressCode.migrate-suppressionspřepíše komentářephpcs:*nadresscode:*, viz tamtéž.lspspustí jazykový server pro editory.
Cesty jsou soubory nebo adresáře relativně k aktuálnímu adresáři a mají přednost před klíčem paths
z konfigurace. Adresář, ve kterém leží některé cesty z paths, se ale zúží jen na ně, takže
dresscode fix . v kořeni projektu nesáhne mimo paths a check i fix to hned
na začátku výpisu ohlásí slovy narrowed to the configured paths. Adresář nebo soubor mimo paths
se vezme tak, jak jste ho zadali. Bez cest i bez konfiguračního souboru příkaz skončí chybou, protože nechce hádat, co
má kontrolovat.
Přepínače
| přepínač | význam |
|---|---|
-c, --config <soubor> |
konfigurační soubor místo nejbližšího dresscode.neon nebo dresscode.php |
-f, --format <název> |
formát výstupu, viz níže |
--diff |
u check ukáže, co by fix změnil; u fix to, co změnil |
--preset <název> |
přidá preset; lze uvést vícekrát |
--group <název> |
přidá skupinu pravidel, třeba
cleanup nebo modernization; lze uvést vícekrát |
--rule <název>=on nebo =off |
zapne nebo vypne pravidlo pro tenhle běh; lze uvést vícekrát |
--only <název> |
zúží běh na jmenovaná pravidla; jméno presetu nebo skupiny znamená všechna jejich pravidla. Lze uvést vícekrát, viz níže |
--fix-risky |
udělá rizikové opravy všech pravidel,
nejen těch, která konfigurace jmenuje v klíči fixRisky; ohlásí se tak jako tak |
--max-warnings <n> |
víc než n varování
znamená exit kód 1; bez něj varování exit kód nemění |
--stdin <cesta> |
čte kód ze standardního vstupu, jako by to byl soubor na dané cestě; fix pak opravený kód vypíše na
standardní výstup |
--generate-baseline |
zapíše porušení, která oprava nechá, do baseline místo
hlášení; jen u check a nad kódem, na kterém fix nemá co opravit |
--file <cesta> |
u config: co platí pro tenhle jeden soubor, včetně přepisů v overrides |
--json |
u config: totéž jako data |
--output <soubor> |
u explain: zapíše vysvětlení do souboru jako Markdown |
--no-cache |
zpracuje každý soubor, i ten, o kterém se ví, že je čistý |
--jobs <n> |
počet pracovních procesů; 1 znamená běh v jediném procesu |
--strict-rules |
pravidlo, které poruší svůj kontrakt, je chyba, ne varování; pro vývoj vlastních pravidel |
--no-color |
výstup bez barev |
--version, --help |
verze, nápověda |
U --preset, --rule a explain můžete jméno vestavěného presetu nebo pravidla
zkrátit o předponu dresscode/: --preset nette je totéž co --preset dresscode/nette.
Jména skupin vendora nemají a píšou se vždycky sama: --group cleanup.
Co konfigurace znamená: config
Konfigurace je pár řádků, ale to, co z nich vzejde, je sto sedmdesát pravidel s volbami z několika vrstev.
dresscode config to vypíše tak, jak to vidí běh: čte totéž vyřešení, kterým se řídí pravidla i cache,
takže nemůže tvrdit něco jiného, než co se opravdu stane.
DRESS|CODE 1.0
Config /var/www/shop/dresscode.neon
Target PHP 8.2 from composer.json
Presets dresscode/psr12, dresscode/per, dresscode/nette-style, dresscode/nette
Groups cleanup, modernization, types, deprecations, correctness
Style a tab, the line ending each file mostly has, lines of up to 140 characters
Rules 172 of 199 run
dresscode/name-casing dresscode/nette
classes PascalCase dresscode/nette
constants PascalCase dresscode/nette (over dresscode/psr12 UPPER_CASE, dresscode/per UPPER_CASE)
dresscode/braces-position dresscode/nette-style
emptyBodies ownLine dresscode/nette-style (over dresscode/per sameLine)
dresscode/line-length the configuration
dresscode/strict-call group correctness, risky fixes only reported
...
Not running
dresscode/useless-else turned off by dresscode/nette
dresscode/octal-notation it needs PHP 8.1 and the target is 8.0
dresscode/no-deprecated-members it needs the types of the code and the configuration sets no types
6 more that no preset or rule of the configuration mentions
Řádek Groups říká, ke kterým skupinám
pravidel se konfigurace doresolvovala, a pravidlo, které zapnula skupina, má jako vrstvu group <jméno>.
U každého pravidla stojí vrstva, která ho zapnula, u každé volby, kterou některá vrstva jmenovala, výsledná hodnota,
kdo ji nastavil a co tím přebil. Pravidlo s rizikovými opravami navíc říká, jestli jste
je přijali (risky fixes accepted), nebo jestli se jen ohlásí (risky fixes only reported). Pravidlo,
které neběží, říká proč: vypnul ho preset nebo konfigurace, chybí mu verze PHP, typy nebo knihovna, kterou hlídá,
zapíná ho jen přepis, nebo o něm nikdo nemluvil. --file cesta ukáže totéž pro jeden soubor, tedy
i s přepisy, které pro něj platí, a --json dá výstup jako data pro nástroje.
Vysvětlení pravidel: explain
Jméno pravidla ve výpisu je odkaz, ne vysvětlení. dresscode explain <pravidlo> k němu dá popis,
fázi, volby s hodnotou a vrstvou, která ji v tomhle projektu nastavila, a příklad kódu před opravou a po ní:
dresscode/string-quotes
Decides which quotes a string that needs neither kind is written with.
stage Structure
It runs in this project, set by dresscode/nette.
Options
quotes single (default)
The quotes a plain string is written with
Example
<?php
$name = "Kafka";
$greeting = "Hello, $name";
becomes
<?php
$name = 'Kafka';
$greeting = "Hello, $name";
Příklad je fixtura pravidla, kterou jeho autor vybral jako ukázku, takže ho testovací sada pouští proti pravidlu a
ukázka nemůže zastarat. Pravidlo, které jen hlásí, má příklad bez „becomes“. Diff toho, co by fix
udělal s vaším kódem, ukáže check --diff.
Bez jména pravidla dresscode explain vysvětlí všechna pravidla, která v projektu běží. S
--output je zapíše do souboru jako Markdown: z čeho se konfigurace skládá a u každého pravidla popis, volby,
jak je má tenhle projekt, a příklad, seskupeno podle oblastí kódu.
dresscode explain --output docs/rules.md
Dokument vzniká z téže konfigurace, kterou se kontroluje kód. Zvyklosti z code review a všechno, na co žádné pravidlo není, v něm nejsou.
Konfigurace naměřená z kódu: init
První konfiguraci nemusíte psát: dresscode init v kořeni projektu ji změří z kódu, který už máte, a
napíše dresscode.neon. Nic nehádá. Pro každou hodnotu rozhodnutí pustí to pravidlo, které by ji potom
opravovalo, a co pravidlo nahlásí, s tou hodnotou nesouhlasí. Měří se tedy týmž nástrojem, který bude kód kontrolovat,
a měřítko se s ním nemůže rozejít.
dresscode init
DRESS|CODE 1.0
Sample 35 of 35 files in src, tests
Standard nette, as given
Indent tab 100% of 32 files
Quotes single 100% of 591 strings
Conditions no conditions
Namespaced none declared in 35 files
Dry run 2 of 35 sampled files would change
dresscode.neon written.
Vzorek je každý k-tý soubor setříděného seznamu, nejvýš 300, aby měření trvalo vteřiny i ve velkém projektu;
kromě výchozích vyloučených cest jdou stranou adresáře fixtures, Fixtures a
expected, protože jejich obsah nikdo nepíše rukou. Poslední řádek je nasucho spuštěný fix:
říká, kolik souborů vzorku by navržená konfigurace změnila, tedy co vás čeká při prvním opravdovém
fix.
Měří se tři rozhodnutí, a každé jinou jednotkou, podle toho, jak často se v kódu vyskytuje:
- odsazení po souborech, protože je to vlastnost souboru:
tab,4nebo2; - uvozovky po řetězcích, protože se rozhodují u každého znovu. Pravidlo je obousměrné, takže jedno spuštění spočítá řetězce psané dvojitě a druhé ty jednoduché a jmenovatel je jejich součet;
- tvar víceřádkové podmínky po podmínkách; třetí běh, který povolí oba tvary, spočítá podmínky, které nejsou ani v jednom.
Zapíše se jen to, co kód říká dost jasně. Hodnota, se kterou souhlasí aspoň 70 % míst, se napíše jako hodnota
i s procenty. Kde hranice nedosáhne žádná, ale obě dohromady ano, napíše se u tvaru podmínky tolerance
[perLine, compact], tedy „oba tvary projdou“; u uvozovek, kde tolerance nedává smysl, se napíše
keep. A kde ani to ne, nenapíše se nic a rozhoduje standard. Klíč fixRisky nenapíše
init nikdy: souhlas s opravami, které mohou změnit chování kódu, se z kódu změřit nedá.
# Written by dresscode init from 35 of the 35 files. A number is the share of the places a decision
# appears in that already agree with its value; what the file does not name, the standard decides.
presets:
- nette
indent: tab # tab 100% of 32 files
# the namespaces of the scope declare no function and no constant, so an unqualified name in a namespace
# is resolved for certain; one declared later is reported until it is listed
nameResolution: certain
rules:
string-quotes: single # single 100% of 591 strings
paths:
- src
- tests
fileExtensions:
- php
- phpt
Vedle tří rozhodnutí zapíše init i to, co deklarují jmenné prostory. Tady nejde o většinu, ale
o úplnost, a tak vzorek nestačí: init projde všechny soubory v cestách, najde funkce a konstanty deklarované
ve jmenných prostorech, zapíše jejich seznamy do klíče namespaces a k nim nameResolution: certain.
Soubor, který nejde naparsovat, může deklarovat cokoli, a proto init jistotu v takovém případě nezapíše a
v komentáři jmenuje první takový soubor a řekne, kolik je dalších. Když mezi nainstalovanými balíčky najde
symfony/dependency-injection, navrhne i preset symfony-configurator, který zná funkce, jimiž Symfony
konfiguruje služby. Co ty klíče znamenají, popisuje stránka Funkce a konstanty
ve jmenných prostorech.
Standard init neměří: vezme ten, který mu dáte přepínačem --preset, a bez něj napíše
per s komentářem, že ostatní tři jsou psr12, nette a symfony. Cesty bere
z adresářů src, tests, app a lib, které v kořeni opravdu jsou.
Než se soubor zapíše, init si ho sám přečte a nechá vyřešit, jestli z něj vyjdou tytéž hodnoty,
které naměřil. Konfiguraci, která už existuje, nikdy nepřepíše: návrh vypíše na výstup a skončí s kódem
2, takže si ho můžete prohlédnout nebo přesměrovat do souboru.
Jedno pravidlo najednou: –only
--only zúží běh na vyjmenovaná pravidla. Jméno presetu znamená všechna pravidla, která skládá, jméno
skupiny všechna pravidla té skupiny, a přepínač se
dá uvést vícekrát:
dresscode fix --only dresscode/string-quotes
dresscode fix --only cleanup --only modernization
Hodí se při přechodu na DressCode a u velkých úklidů: jedno pravidlo, jeden commit, jedno review. Filtruje až to,
k čemu konfigurace dojde, takže pravidlo nezapíná ani nepřenastavuje: na to je --rule, a ten se uplatní
dřív. Jméno, které v téhle konfiguraci nic nespouští, je chyba, ne tiše prázdný běh. Klíč konfiguračního souboru
to není: je to rozhodnutí jednoho běhu, ne projektu.
fix --only opraví jen to jedno pravidlo a zbytku se nedotkne, takže příští úplný fix klidně
změní víc; to je záměr, ne nedokončená práce. Ostatní pravidla mezitím ve výpisu dresscode config
říkají the run is narrowed to other rules. Baseline se zúženým během generovat nedá, protože by zapomněla,
co našla ostatní pravidla.
Formáty výstupu
Přepínač --format volí celý tvar výstupu, ne jeho detail; formáty se nekombinují.
console je výchozí volba pro terminál: hlavička s konfigurací, cílovou verzí PHP a rozsahem kontroly, pak
jednotlivé soubory s porušeními (řádek, sloupec, zpráva, pravidlo) a nakonec shrnutí. Porušení pravidla z klíče
warnings má značku warning místo error a shrnutí ho počítá zvlášť. U
check shrnutí řekne i to, kolik porušení by po fix zbylo a kolik z nich jsou rizikové opravy,
které čekají na svolení, a u kterých pravidel:
FOUND 36 violations, 2 warnings, a fix leaves 5, 3 of them risky (strict-call, strict-comparison), fixed with --fix-risky or once their rules are named in fixRisky in 12 of 214 files
Porušení, které v souboru vzniklo až opravou jiného porušení z téhož běhu, vypíše konzole jako poznámku pod
tím, z něhož plyne, typicky prázdný řádek nebo odsazení u zalomení, které oprava vložila. Shrnutí pak řekne, kolik
porušení plyne z ostatních. V ostatních formátech je to porušení jako každé jiné s údajem
derivedFrom.
src/Cart.php
error 1:7 A line break after the opening tag blank-lines
followed by blank-lines on line 1
fix vypíše každý soubor, který přepsal, s poznámkou rewritten a pod ním to, co opravený
text pořád porušuje, s řádky a sloupci v opraveném souboru. Které porušení oprava odstranila, se z výsledného textu
poznat nedá, a tak shrnutí počítá nalezená a zbylá porušení; co přesně se změnilo, ukáže --diff:
src/Cart.php rewritten src/Order.php rewritten error 12:1 The line is 133 characters long, the limit is 120 line-length FIXED 36 violations found, 1 remaining in 12 of 214 files
Barvy se vypnou samy, jakmile výstup nejde do terminálu.
github se zvolí sám, když běh probíhá jako krok GitHub Actions. Každé porušení je anotace, která se
ukáže přímo v diffu pull requestu; u fix jsou to porušení, která oprava nechala.
bare je pro Git hooky a nástroje, které výstup čtou: bez hlavičky a bez shrnutí, jen porušení, která
zůstala na uživateli, ve stejném rozvržení jako console, a u každého přepsaného souboru řádek
rewritten. Čistý běh nevypíše vůbec nic.
src/Cart.php rewritten src/Order.php error 12:1 The line is 133 characters long, the limit is 120 line-length
json je strojově čitelný a jeho tvar se v minoritních verzích nemění. Pole files má
u každého souboru nalezená porušení violations (pravidlo, zpráva, řádek, sloupec, závažnost, zda je oprava
riziková, otisk) a porušení remaining, která zbudou po opravě, s pozicemi v opraveném textu. Dál následuje
summary s počty, mezi nimi remaining, rizikové opravy, které čekají, soubory se syntaktickou
chybou (syntaxErrors) a porušení v baseline, a nakonec warnings.
checkstyle je XML, kterému rozumí Jenkins, nástroj cs2pr a další nástroje pro CI; u
fix v něm stejně jako u github jsou porušení, která oprava nechala.
Exit kódy
| kód | význam |
|---|---|
0 |
čisto; u fix také tehdy, když opravený text už nic neporušuje; varování bez prahu
--max-warnings exit kód nemění |
1 |
zůstala porušení, soubor nejde parsovat, nebo je varování víc, než --max-warnings dovolí |
2 |
selhání: špatná konfigurace, neznámé pravidlo, pravidlo, které vyhodilo výjimku nebo se s jiným zacyklilo, soubor změněný během opravy |
Selhání jednoho souboru běh nezastaví: soubor se ohlásí jako selhavší, nic se do něj nezapíše a ostatní se
zpracují dál. Riziková oprava, která čeká na svolení, je porušení jako každé jiné a drží exit kód na
1, dokud ji někdo neudělá nebo nezapíše do baseline.
Cache a paralelní běh
DressCode si pamatuje každý soubor, který prošel čistě: jeho cestu a otisk obsahu, a spolu s nimi otisk konfigurace,
která pro něj platí (včetně přepisů pro jeho cestu), cílové verze PHP, baseline a verzí nainstalovaných balíčků.
Cesta v klíči je proto, že tentýž obsah může ve dvou souborech dostat dva verdikty, třeba kvůli přepisu nebo pravidlu,
které se na cestu dívá. Soubor se stejnou cestou, obsahem a konfigurací příště přeskočí; jakmile se kterákoli z těch
věcí změní, zpracuje ho znovu. Počty ve shrnutí i varování o zastaralých položkách baseline vyjdou s cache stejně
jako bez ní. Obsah, který zapsal fix, si DressCode zapamatuje jen v projektu bez baseline. Cache leží
v systémovém dočasném adresáři, nebo tam, kam ukazuje cacheDir v konfiguraci; --no-cache ji pro
jeden běh obejde.
Soubory, které cache nepokryje, se rozdělí mezi pracovní procesy. Výchozí počet odpovídá počtu procesorů, nejvýš
však jeden proces na čtyři soubory, protože spuštění procesu něco stojí. --jobs 1 běží bez nich, což se
hodí při ladění vlastního pravidla, a --jobs 8 se vyplatí na stroji s mnoha jádry, kde by výchozí odhad byl
zbytečně nízký. S procesy běží i --generate-baseline, takže generování netrvá déle než kontrola.
Standardní vstup
--stdin je rozhraní pro editory a hooky: obsah přijde na standardním vstupu, cesta říká, která pravidla pro
něj platí (podle ní se vyhodnotí přepisy pro cesty), a fix vrátí opravený kód na standardní výstup místo
toho, aby zapisoval do souboru:
git show :src/Cart.php | dresscode check --stdin src/Cart.php
Cache se u standardního vstupu nepoužívá.