Langkau ke kandungan

Kepintaran kod

Control Center memberikan ejen empat cara untuk memahami kod selain membacanya. Setiap satu menjawab soalan yang benar-benar berbeza, dan sebabnya ada empat dan bukan satu ialah tiada satu mekanisme pun yang menjawab kesemuanya.

Mekanisme Menjawab Kos
Graf kod Apa yang ada di sini, dan apa yang bergantung padanya Satu laluan pengindeksan; murah untuk ditanya
Pelayan bahasa Adakah ini benar-benar dikompil, dan apakah jenis ini Satu proses pelayan bagi setiap projek
Carian struktur Di manakah BENTUK ini muncul Satu penghuraian bagi setiap fail
Nyahpepijat Apa yang benar pada saat ini, dalam bingkai ini Proses yang dihentikan

Graf kod dibina daripada tree-sitter: simbol, tepi panggilan, jejari kesan. Ia pantas, ia murah, dan ia tidak tahu apa-apa tentang jenis. Ia tidak dapat memberitahu anda sama ada panggilan yang baru anda tulis dapat dikompil, sama ada medan itu wujud pada objek, atau sama ada penamaan semula anda terlepas satu eksport semula.

Tanpa pelayan bahasa, ejen hanya mengetahuinya pada masa ujian — atau tidak pernah. Ia menulis sesuatu yang kelihatan munasabah, terus bergerak, dan kegagalan itu muncul tiga pusingan kemudian, terlekat pada perubahan yang berbeza.

Jadi hasilnya bukanlah alat lsp itu sendiri. Yang penting ialah write, edit dan apply_patch dibalut: selepas setiap tulisan, fail itu melalui pelayan bahasa dan diagnostik yang baru diperkenalkan dilipat masuk ke dalam hasil alat. Ejen tahu ia telah memecahkan binaan pada saat ia memecahkannya, sama ada ia terfikir untuk bertanya atau tidak.

Mengulang apa yang telah diberitahu kepada ejen lebih buruk daripada berdiam diri: ia memenuhi hasil dengan hingar yang dipelajari oleh ejen untuk dilangkau, dan satu ralat baharu itu turut terlepas bersama. Satu lejar setiap larian menjejaki apa yang telah dilaporkan, berkunci pada keterukan, kod dan mesej — bukan kedudukan, jadi diagnostik yang hanya berpindah turun empat baris tidak dilaporkan semula sebagai baharu.

Tiada pelayan dimulakan semasa but. Satu pelayan dimulakan pada permintaan pertama yang memerlukannya, yang hampir selalu merupakan suntingan pertama pada fail yang dituntutnya, dan pelayan yang menganggur akan disapu keluar. Hos yang tidak pernah menyentuh Dart tidak pernah memulakan penganalisis.

Pengesanan ialah satu persilangan: penanda akar mesti wujud dalam checkout dan binari mesti dapat diselesaikan. Penanda sahaja berkata “projek ini ialah Python” dan tidak berkata apa-apa tentang sama ada pelayan dipasang; binari yang dapat diselesaikan sahaja berkata hos ini mempunyai rantaian alat dan tidak berkata apa-apa tentang checkout ini. Hanya kedua-duanya bersama-sama bermakna satu pertanyaan boleh berjaya, dan alat yang ditawarkan tetapi selalu gagal lebih buruk daripada alat yang tidak hadir.

grep memadankan aksara. Itu alat yang betul untuk satu nama dan alat yang salah untuk satu bentuk.

Corak struktur dihuraikan oleh tatabahasa yang sama seperti fail itu, jadi dispose($X) menemui panggilan itu tidak kira bagaimana ia dijarakkan, dibalut atau dipecahkan baris, dan tidak pernah memadankan aksara yang sama di dalam literal rentetan atau komen.

Sifat yang menjadikannya lebih daripada satu regex dengan beberapa langkah tambahan ialah metapembolehubah yang berulang dalam satu corak mesti menangkap teks yang sama:

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

memadankan satu pengawal yang membuang apa yang diujinya, dan tidak memadankan pengawal yang membuang benda lain. Itu kelas pepijat yang tidak boleh anda ungkapkan secara tekstual sama sekali.

Ia berjalan atas tree-sitter yang sudah dipautkan

Bahagian bertajuk “Ia berjalan atas tree-sitter yang sudah dipautkan”

Tiada enjin kedua. cc_natives sudah memuatkan tree-sitter dan tatabahasanya untuk graf kod, dengan cache pertanyaan terkompil dan jadual bahasa. Pemadan itu Dart tulen atas pokok yang memang sedang dihuraikan. Enjin struktur kedua akan bermakna penghurai kedua, set tatabahasa kedua untuk dibina dan disediakan pada setiap platform, serta dua jawapan kepada “apakah itu ungkapan panggilan”.

Tatabahasa hanya mentakrifkan apa itu satu fail penuh. Apabila dihuraikan secara mentah pada aras atas Dart, dispose(x) ialah tandatangan fungsi yang sah sepenuhnya — satu pengisytiharan bernama dispose yang mengambil parameter x — tanpa sebarang ralat yang mendedahkannya. Pemadan yang dibina atas huraian itu mencari pengisytiharan, tidak menemui panggilan, dan melaporkan “tiada padanan” untuk corak yang memang tidak pernah dibaca seperti rupanya.

Jadi sesuatu corak dicuba dalam satu tangga perancah — pernyataan, ungkapan, ahli kelas, aras atas — dan yang pertama menerimanya menang. Serpihan yang tidak diterima oleh mana-mana konteks dilaporkan sebagai tidak boleh dihuraikan, dan bukan dicari lalu secara senyap tidak ditemui.

Mengapa penulisan semula melalui peringkat, bukan terus menulis

Bahagian bertajuk “Mengapa penulisan semula melalui peringkat, bukan terus menulis”

Penulisan semula struktur ialah suntingan paling luas yang boleh dilakukan oleh ejen: satu corak, empat puluh fail, dan tiada siapa membaca hasilnya baris demi baris — bukan model, dan bukan orang yang memintanya. Menulisnya dan melaporkan “selesai” bermakna pandangan jujur pertama terhadap perubahan itu ialah git diff selepasnya.

Jadi ast_edit melaporkan apa yang akan dilakukannya — kiraan, fail, tapak yang dipadankan — dan perubahan itu hanya mendarat apabila resolve mengkomitnya. Itulah juga yang membolehkan satu diff dan pilihan Terima/Buang terletak di hadapan manusia sebelum apa-apa pun sampai ke cakera.

Komit itu bersifat semua-atau-tiada dan setiap fail disemak terhadap kandungan yang ditangkap pada masa peringkat. Antara peringkat dan komit, ejen mungkin telah menyunting salah satu fail itu secara manual, satu laluan diagnostik mungkin telah menulis semulanya, atau pemformat mungkin telah menyentuhnya — mengkomit juga akan membuang kerja itu dan diff tersebut akan kelihatan disengajakan. Sebarang ketakpadanan menolak keseluruhan perubahan, kerana penulisan semula struktur yang hanya sebahagian diterapkan meninggalkan pokok yang tidak dapat dikompil dalam mana-mana bentuk.

Apa yang nyahpepijat jawab yang tidak dapat dijawab oleh pernyataan cetak

Bahagian bertajuk “Apa yang nyahpepijat jawab yang tidak dapat dijawab oleh pernyataan cetak”

Gelung pernyataan cetak ialah: tambah satu cetakan, jalankan semuanya semula, baca output, padam cetakan itu. Ia memakan satu larian ujian penuh bagi setiap soalan, dan ia hanya menjawab soalan yang anda terfikir untuk tanyakan sebelum menjalankannya.

Bingkai yang dihentikan menjawab setiap soalan tentang saat itu sekali gus — setiap pembolehubah setempat, setiap pemanggil, dan satu ungkapan yang dinilai dalam skop bingkai itu sendiri. Untuk proses yang tersekat atau kegagalan yang hanya berulang sekali dalam sepuluh larian, itulah bezanya antara satu petang dengan satu minit.

Terbatas seperti kepungan, dan atas sebab yang sama

Bahagian bertajuk “Terbatas seperti kepungan, dan atas sebab yang sama”

Penyesuai nyahpepijat memiliki satu proses yang dihentikan yang memegang apa sahaja yang dipegang oleh proses itu — satu port, satu kunci, satu sambungan pangkalan data. Sesi yang tidak dipandu oleh sesiapa ialah kebocoran yang hidup lebih lama daripada pusingan yang memulakannya. Jadi terdapat TTL keras, tepat satu sesi bagi setiap perbualan, dan launch kedua ditolak dan bukan secara senyap menggantikan yang pertama: ejen yang memulakan sesi kedua tanpa menamatkan yang pertama hampir pasti telah hilang jejak yang pertama.

Debug Adapter Protocol berkongsi rangka Content-Length Language Server Protocol dan tiada apa-apa di atasnya — kunci korelasi yang berbeza, bentuk kegagalan yang berbeza, dan jenis mesej ketiga (peristiwa) yang tiada padanan dalam LSP. Rangka itu tinggal di satu tempat; protokol-protokol itu duduk di atasnya secara berasingan.

Menulis rangka itu dua kali akan bermakna dua jawapan kepada “satu mesej merentangi dua ketulan”, “satu ketulan memegang tiga mesej” dan “pelayan menulis sepanduk ke stdout sebelum rangka pertamanya”, dan hanya satu daripadanya akan menerima pembaikan.