Refaktorujte kód strukturálně
Tenhle návod ukáže, jak od agenta dostat širokou mechanickou změnu — codemod, hromadnou migraci API, vzor, který má zmizet — strukturálním hledáním a přepisem, přičemž se změna nejdřív připraví k revizi a teprve potom se cokoli zapíše.
ast_grep hledá kód podle tvaru. ast_edit ho přepisuje. resolve zápis potvrdí, nebo ho zahodí.
Než začneš
Sekce “Než začneš”Strukturální nástroje pokrývají jazyky, které parsuje graf kódu: Dart, JavaScript, TypeScript, TSX, PHP, Python, Rust, Zig, C, C++, Go, Java, Ruby, C#, Swift, Kotlin, R, Assembly, MATLAB a Ada. Potřebují připravené gramatiky tree-sitter a v dodávaném sestavení je mají vždy — chybějící gramatika zastaví server, místo aby se hledání potichu zhoršilo.
Nejdřív najdi tvar
Sekce “Nejdřív najdi tvar”Nepřepisuj nic, na co ses nepodíval. Požádej agenta, ať hledá:
Najdi každé místo, kde voláme
dispose()na nullable, který jsme právě zkontrolovali na null.
ast_grep(pattern: "if ($X != null) $X.dispose()", language: "dart")Výstup je file:line a ke každému místu shodný zdroj.
K čemu je syntaxe vzoru
Sekce “K čemu je syntaxe vzoru”| Token | Shoda |
|---|---|
$NAME |
Libovolný jeden uzel, zachycený |
$$$NAME |
Libovolná řada sourozenců — argumenty, příkazy |
$_ |
Cokoli, zachycené bez jména |
Podstatné je tohle: zopakované $NAME musí zachytit tentýž text.
if ($X != null) $X.dispose()najde guard, který zavolá dispose na to, co právě otestoval. Nenajde if (a != null) b.dispose() — a to bývá právě ta chyba, kterou hledáš. Textem se taková věc vyjádřit nedá.
Když vzor nic nenajde
Sekce “Když vzor nic nenajde”Zkus dvě věci, v tomhle pořadí:
- Zmenši ho. Nejdřív
foo($X), až potomif (a) { foo($X); }. Vzor, který sám o sobě není platný kód, často není ten konstrukt, který jsi myslel. - Pojmenuj jazyk.
language:se odvodí jen tehdy, kdyžpathuvádí jeden soubor.
Vzor, který nepřijme žádný kontext rozboru, se nahlásí jako nerozparsovatelný — nástroj to řekne, místo aby u něčeho, co se nikdy nečetlo tak, jak vypadá, ohlásil „žádné shody“.
Přepiš a podívej se, než to dopadne
Sekce “Přepiš a podívej se, než to dopadne”ast_edit( pattern: "if ($X != null) $X.dispose()", rewrite: "$X?.dispose()", language: "dart",)Výsledek je návrh:
(proposed) ast_edit: if ($X != null) $X.dispose() → $X?.dispose()12 replacements in 4 files: lib/features/a/x.dart (3) lib/features/b/y.dart (5) …Nothing has been written. Call resolve with edit_id "edit_1" and action"accept" to apply it, or "discard" to drop it.Na disku ještě nic není. Přečti seznam, zkontroluj pár míst, která hledání nahlásilo, a pak:
resolve(edit_id: "edit_1", action: "accept")nebo
resolve(edit_id: "edit_1", action: "discard")Ověř to překladačem
Sekce “Ověř to překladačem”Strukturálně se to dělá proto, že je to široké. Právě u širokých změn věrohodný přepis rozbije typ. Po potvrzení si vyžádej diagnostiky:
lsp(action: "diagnostics", file: "*")file: "*" spustí vlastní kontrolu projektu (dart analyze, tsc --noEmit, cargo check, go build), ne dotaz na každý soubor zvlášť — správný tvar otázky po změně, která sahá do čtyřiceti souborů.
Řešený příklad: migrace volání
Sekce “Řešený příklad: migrace volání”Dejme tomu, že log(msg, level) přechází na log(level: level, message: msg).
ast_grep(pattern: "log($MSG, $LEVEL)", language: "dart")Podívej se na shody. Když je část z nich jiný dvouargumentový log, zúž vzor omezením path na adresář, kterému patří ten, o který jde, místo abys ten rozdíl vyjadřoval ve vzoru.
ast_edit( pattern: "log($MSG, $LEVEL)", rewrite: "log(level: $LEVEL, message: $MSG)", path: "lib/features/telemetry", language: "dart",)Pak resolve, pak lsp(action: "diagnostics", file: "*").
Kdy sáhnout po něčem jiném
Sekce “Kdy sáhnout po něčem jiném”| Situace | Lepší nástroj |
|---|---|
| Přejmenování symbolu | lsp_rename — sleduje reference, ne tvary |
| Řetězec, komentář nebo název souboru | search (obsah) / search_files (názvy) |
| „Co se rozbije, když tohle změním?“ | Graf kódu |
| Jazyk, který gramatiky nepokrývají | search a edit |
Související
Sekce “Související”- Inteligence kódu — proč strukturální hledání není regulární výraz s pár kroky navíc
- Vestavěné nástroje agentů — úplný seznam argumentů
- Hledejte kód v grafu kódu — symboly a dopad