Kód strukturális refaktorálása
Ez az útmutató megmutatja, hogyan vegyen rá egy ügynököt egy széles körű, mechanikus változtatásra — egy codemod, egy tömeges API-migráció vagy egy minta, amelyet el akar tüntetni — strukturális kereséssel és átírással, úgy, hogy a változás a kiírás előtt átnézésre előkészítve várjon.
Az ast_grep alak szerint illeszti a kódot. Az ast_edit átírja. A resolve véglegesíti vagy elveti.
Mielőtt elkezdi
Szekció neve “Mielőtt elkezdi”A strukturális eszközök azokat a nyelveket fedik le, amelyeket a kódgráf feldolgoz: Dart, JavaScript, TypeScript, TSX, PHP, Python, Rust, Zig, C, C++, Go, Java, Ruby, C#, Swift, Kotlin, R, Assembly, MATLAB és Ada. Szükségük van az előkészített tree-sitter nyelvtanokra, amelyek egy kiszállított buildben mindig rendelkezésre állnak — egy hiányzó nyelvtan leállítja a szervert, nem pedig lerontja a keresést.
Először keresse meg az alakot
Szekció neve “Először keresse meg az alakot”Soha ne írjon át olyasmit, amit nem nézett meg. Kérje meg az ügynököt a keresésre:
Keresse meg az összes helyet, ahol egy nullable értéken
dispose()-t hívunk, amelyet épp most ellenőriztünk nullára.
ast_grep(pattern: "if ($X != null) $X.dispose()", language: "dart")A kimenet file:line, valamint minden helyhez az illeszkedő forrás.
Mit nyújt a mintaszintaxis
Szekció neve “Mit nyújt a mintaszintaxis”| Token | Illeszkedés |
|---|---|
$NAME |
Bármely egyetlen csomópont, elkapva |
$$$NAME |
Testvérek bármely sorozata — argumentumok, utasítások |
$_ |
Bármi, név nélkül elkapva |
Amelyik igazán számít: egy ismételt $NAME-nek ugyanazt a szöveget kell elkapnia.
if ($X != null) $X.dispose()olyan őrfeltételre illeszkedik, amely azt szabadítja fel, amit vizsgált. Nem illeszkedik viszont az if (a != null) b.dispose() esetre — ami általában pont az a hiba, amelyet keresett. Ezt egyetlen szöveges keresés sem tudja kifejezni.
Amikor a minta nem talál semmit
Szekció neve “Amikor a minta nem talál semmit”Két dolgot érdemes kipróbálni, ebben a sorrendben:
- Kisebbítse.
foo($X)azif (a) { foo($X); }előtt. Egy minta, amely önmagában nem érvényes kód, gyakran nem az a szerkezet, amelyet valójában keresett. - Nevezze meg a nyelvet. A
language:csak akkor következtethető ki, ha apathegyetlen fájlra mutat.
Az olyan mintát, amelyet egyetlen feldolgozási környezet sem fogad el, feldolgozhatatlanként jelentenek — az eszköz ezt mondja ahelyett, hogy „nincs találat”-ot jelentene valamire, amit soha nem úgy olvastak, ahogy kinéz.
Írjon át, és nézze meg, mielőtt bekerül
Szekció neve “Írjon át, és nézze meg, mielőtt bekerül”ast_edit( pattern: "if ($X != null) $X.dispose()", rewrite: "$X?.dispose()", language: "dart",)Az eredmény egy javaslat:
(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.Még semmi sincs a lemezen. Olvassa el a listát, ellenőrizzen néhány helyet, amelyet a keresés jelentett, majd:
resolve(edit_id: "edit_1", action: "accept")vagy
resolve(edit_id: "edit_1", action: "discard")Ellenőrizze a munkáját a fordítóval
Szekció neve “Ellenőrizze a munkáját a fordítóval”Azért érdemes strukturálisan eljárni, mert a változás széles hatókörű. Pont a széles körű változások azok, ahol egy hihetőnek tűnő átírás eltöri a típust. A véglegesítés után kérjen diagnosztikát:
lsp(action: "diagnostics", file: "*")A file: "*" a projekt saját ellenőrzőjét futtatja (dart analyze, tsc --noEmit, cargo check, go build) fájlonkénti lekérdezés helyett — ez a helyes kérdésforma egy negyven fájlt érintő változás után.
Kidolgozott példa: hívás migrálása
Szekció neve “Kidolgozott példa: hívás migrálása”Tegyük fel, hogy a log(msg, level) helyébe a log(level: level, message: msg) lép.
ast_grep(pattern: "log($MSG, $LEVEL)", language: "dart")Nézze meg a találatokat. Ha közülük néhány egy másik kétargumentumos log, szűkítse a mintát úgy, hogy a path értékét arra a könyvtárra korlátozza, amelyik a keresett példányt tartalmazza, ahelyett hogy a különbséget magában a mintában próbálná kifejezni.
ast_edit( pattern: "log($MSG, $LEVEL)", rewrite: "log(level: $LEVEL, message: $MSG)", path: "lib/features/telemetry", language: "dart",)Ezután resolve, majd lsp(action: "diagnostics", file: "*").
Mikor használjon mást
Szekció neve “Mikor használjon mást”| Helyzet | Jobb eszköz |
|---|---|
| Szimbólum átnevezése | lsp_rename — a hivatkozásokat követi, nem az alakokat |
| Sztring, megjegyzés vagy fájlnév megkeresése | search (tartalom) / search_files (nevek) |
| „Mi törik el, ha ezt megváltoztatom?” | A kódgráf |
| Olyan nyelv, amelyet a nyelvtanok nem fednek le | search plusz edit |
Kapcsolódó
Szekció neve “Kapcsolódó”- Kódintelligencia — miért nem egy plusz lépésekkel felcicomázott regex a strukturális illesztés
- Beépített ügynökeszközök — a teljes argumentumlista
- Kód keresése a kódgráffal — a szimbólumok és a hatás oldala