Tovább a tartalomhoz

Kódintelligencia

A Control Center négy módot ad egy ügynöknek arra, hogy a kódot az elolvasásán túl is megértse. Ezek valóban különböző kérdésekre adnak választ, és azért van belőlük négy az egy helyett, mert egyetlen mechanizmus sem válaszolja meg mindet.

Mechanizmus Mire ad választ Mibe kerül
Kódgráf Mi van itt, és mi függ ettől Egy indexelési menet; a lekérdezés olcsó
Nyelvi szerver Ez tényleg lefordul-e, és mi ez a típus Egy szerverfolyamat projektenként
Strukturális keresés Hol jelenik meg ez az ALAK Egy parse fájlonként
Hibakereső Mi volt igaz ebben a pillanatban, ebben a keretben Egy megállított folyamat

A hiány, amelyet a nyelvi szerver kitölt

Szekció neve “A hiány, amelyet a nyelvi szerver kitölt”

A kódgráf tree-sitterből épül fel: szimbólumok, hívási élek, hatássugár. Gyors, olcsó, és semmit sem tud a típusokról. Nem mondja meg, hogy az imént írt hívás lefordul-e, hogy létezik-e az a mező az objektumon, vagy hogy az átnevezés kihagyott-e egy újraexportálást.

Nyelvi szerver nélkül egy ügynök a teszt futtatásakor szerez tudomást a hibáról – vagy soha. Ír valami hihetőt, továbblép, és a hiba három körrel később bukkan fel, egy másik módosításhoz kapcsolva.

Tehát a haszon valójában nem az lsp eszköz. Hanem az, hogy a write, az edit és az apply_patch be van csomagolva: minden írás után a fájl átmegy a nyelvi szerveren, és az újonnan bevezetett diagnosztikák bekerülnek az eszköz eredményébe. Az ügynök abban a pillanatban megtudja, hogy eltörte a buildet, amikor eltörte – akár gondolt rá, hogy megkérdezze, akár nem.

Hogy megismételjük, amit az ügynöknek már elmondtunk, rosszabb, mint a csend: megtölti az eredményt zajjal, amelyet az ügynök megtanul átfutni, és az az egyetlen új hiba is vele megy. Egy futásonkénti nyilvántartás követi, mi került már jelentésre, súlyosság, kód és üzenet szerint – nem pozíció szerint –, így az a diagnosztika, amely csak négy sorral lejjebb került, nem jelenik meg újként.

Induláskor egyetlen szerver sem indul el. Az első olyan kérésre indul el, amelynek szüksége van rá – ez szinte mindig az első szerkesztés egy olyan fájlban, amelyre igényt tart –, a tétleneket pedig elsöpri. Egy hoszt, amely soha nem nyúl a Dart-hoz, soha nem indít elemzőt.

A felderítés egy metszet: a checkoutban lennie kell egy gyökérjelölőnek, és a binárisnak fel kell oldódnia. A jelölő önmagában azt mondja, hogy „ez a projekt Python”, és semmit arról, hogy telepítve van-e a szerver; a feloldható bináris önmagában azt mondja, hogy a hoszton van eszközkészlet, és semmit erről a checkoutról. Csak a kettő együtt jelenti azt, hogy egy lekérdezés sikerülhet, és egy felkínált, de mindig elbukó eszköz rosszabb annál, amelyik nincs is meg.

Miért strukturális keresés, ha van grep

Szekció neve “Miért strukturális keresés, ha van grep”

A grep karaktereket illeszt. Ez a megfelelő eszköz egy névhez, és a rossz eszköz egy alakhoz.

Egy strukturális mintát a fájllal azonos nyelvtan dolgoz fel, így a dispose($X) megtalálja a hívást, akárhogyan van tagolva, tördelve vagy sortöréssel elvágva, és soha nem illeszti ugyanezeket a karaktereket egy sztringliterálon vagy megjegyzésen belül.

Az a tulajdonság, amely többé teszi, mint egy plusz lépésekkel felcicomázott regex, az, hogy egy mintában megismételt metaváltozónak ugyanazt a szöveget kell elkapnia:

if ($X != null) $X.dispose()

egy olyan őrfeltételre illeszkedik, amely azt szabadítja fel, amit vizsgált, és nem illeszkedik arra, amely valami mást szabadít fel. Ez olyan hibaosztály, amelyet szövegesen egyáltalán nem lehet kifejezni.

Nincs második motor. A cc_natives már betölti a tree-sittert és annak nyelvtanait a kódgráfhoz, egy lefordított lekérdezés-gyorsítótárral és egy nyelvtáblával. Az illesztő tiszta Dart, olyan fákon, amelyeket amúgy is feldolgoztunk volna. Egy második strukturális motor egy második parsert, egy második nyelvtanegyüttest jelentene, amelyet minden platformon fel kell építeni és elő kell készíteni, valamint két választ arra a kérdésre, hogy „mi számít híváskifejezésnek”.

Egy nyelvtan csak azt határozza meg, mi egy teljes fájl. A Dart felső szintjén csupaszon feldolgozva a dispose(x) egy teljesen érvényes függvényszignatúra – egy dispose nevű deklaráció, amely egy x paramétert vesz fel –, és sehol nincs hiba, amely elárulná. Az erre a feldolgozásra épülő illesztő deklarációkat keres, nem talál hívásokat, és azt jelenti: „nincs találat” egy olyan mintára, amelyet soha nem úgy olvastak, ahogy kinéz.

Ezért a minta egy vázakból álló létrán próbálódik ki – utasítás, kifejezés, osztálytag, felső szint –, és az első, amely elfogadja, nyer. Egy töredéket, amelyet egyetlen környezet sem fogad el, feldolgozhatatlanként jelentenek, ahelyett hogy keresnénk, és csendben nem találnánk meg.

Miért készít elő az átírás a kiírás helyett

Szekció neve “Miért készít elő az átírás a kiírás helyett”

Egy strukturális átírás a legszélesebb szerkesztés, amelyet egy ügynök végezhet: egy minta, negyven fájl, és senki sem olvassa végig soronként az eredményt – sem a modell, sem az, aki kérte. Ha kiírjuk, és azt jelentjük: „kész”, az azt jelenti, hogy a változásra az első őszinte pillantás egy utólagos git diff lesz.

Ezért az ast_edit azt jelenti, amit tenne – a darabszámot, a fájlokat, az illeszkedő helyeket –, és a változás csak akkor kerül a helyére, amikor a resolve véglegesíti. Ez az is, ami lehetővé teszi, hogy egy diff és egy Elfogadás/Elvetés az ember elé kerüljön, mielőtt bármi eljut a lemezre.

A véglegesítés mindent-vagy-semmit, és minden fájlt az előkészítéskor rögzített tartalomhoz ellenőriznek. Az előkészítés és a véglegesítés között előfordulhat, hogy az ügynök kézzel szerkesztette az egyik ilyen fájlt, egy diagnosztikai menet átírta, vagy egy formázó hozzányúlt – ha mégis véglegesítenénk, az elvetné ezt a munkát, és a diff szándékosnak látszana. Bármilyen eltérés visszautasítja a teljes változást, mert a részben alkalmazott strukturális átírás olyan fát hagy maga után, amely egyik alak szerint sem fordul le.

Mit válaszol meg egy hibakereső, amit egy print utasítás nem tud

Szekció neve “Mit válaszol meg egy hibakereső, amit egy print utasítás nem tud”

A print utasításos ciklus: hozzáadunk egy printet, újrafuttatjuk az egészet, elolvassuk a kimenetet, töröljük a printet. Minden kérdésért egy teljes tesztfutás az ára, és csak arra a kérdésre válaszol, amelyet futtatás előtt gondoltunk feltenni.

Egy megállított veremkeret egyszerre megválaszol minden kérdést arról a pillanatról – minden lokális változót, minden hívót, és egy kifejezést a keret saját hatókörében kiértékelve. Egy beragadt folyamat vagy egy tíz futásból egyszer előforduló hiba esetén ez egy délután és egy perc közötti különbség.

Elkerítve, akár egy karám, és ugyanazért az okért

Szekció neve “Elkerítve, akár egy karám, és ugyanazért az okért”

Egy hibakereső adapter birtokol egy megállított folyamatot, amely mindent fog, amit az a folyamat fog – egy portot, egy zárat, egy adatbázis-kapcsolatot. Az a munkamenet, amelyet senki sem vezet, szivárgás, amely túléli az őt indító kört. Ezért van egy kemény TTL, beszélgetésenként pontosan egy munkamenet, és egy második launch visszautasításra kerül ahelyett, hogy csendben lecserélné az elsőt: az az ügynök, amely úgy indít másodikat, hogy nem fejezte be az elsőt, szinte biztosan elveszítette az elsőt.

A Debug Adapter Protocol a Language Server Protocol Content-Length keretezését használja, és semmit sem felette – más korrelációs kulcsok, más hibaalak, és egy harmadik üzenettípus (események), amelynek nincs LSP-megfelelője. A keretezés egy helyen él; a protokollok külön ülnek rajta.

A keretezés kétszeri megírása két választ jelentene arra, hogy „egy üzenet két darabon ível át”, „egy darab három üzenetet tartalmaz” és „a szerver egy bannert írt a stdoutra az első kerete előtt” – és csak az egyik kapná meg a javítást.