Työn pääteos on todennäköisesti pelkkää tekstiä sisältävät tiedostot. Joten miksi et käytä Muistioa niiden luomiseen?
Syntaksin korostus ja automaattinen muotoilu ovat vain jäävuoren huippu. Entä nukkaus, koodin viimeistely ja puoliautomaattinen korjaus? Nämä ovat kaikki erittäin hyviä syitä käyttää “oikeaa” koodieditoria. Nämä ovat elintärkeitä päivittäisillemme, mutta ymmärrämmekö niiden toiminnan?
Tässä kielipalvelimen protokollan opetusohjelmassa tutkimme näitä kysymyksiä vähän ja selvitämme, mikä saa tekstieditorimme valitsemaan. Loppujen lopuksi toteutamme yhdessä peruskielipalvelimen sekä esimerkkiasiakkaat VSCodelle, Sublime Text 3: lle ja Vimille.
Ohitamme toistaiseksi syntaksin korostamisen ja muotoilun, joka hoidetaan staattisella analyysillä - mielenkiintoinen aihe itsessään - ja keskitymme tärkeimpään palautteeseen, jonka saamme näistä työkaluista. On olemassa kaksi pääluokkaa: kääntäjät ja kielipalvelut.
Kääntäjät ottavat lähdekoodisi ja sylkivät toisen muodon. Jos koodi ei noudata kielen sääntöjä, kääntäjä palauttaa virheet. Nämä ovat melko tuttuja. Ongelmana on, että se on yleensä melko hidas ja rajoitettu. Entä avun tarjoaminen koodia luodessasi?
Tätä kielipalvelut tarjoavat. Ne voivat antaa sinulle tietoa koodikannastasi, kun se on vielä kesken, ja todennäköisesti paljon nopeammin kuin koko projektin kokoaminen.
Näiden palvelujen laajuus vaihtelee. Se voi olla jotain yhtä yksinkertaista kuin palauttaa luettelo kaikista projektin symboleista, tai jotain monimutkaista, kuten palauttaa vaiheet refaktorikoodiin. Nämä palvelut ovat ensisijainen syy, miksi käytämme koodieditorit. Jos haluaisimme vain kääntää ja nähdä virheitä, voimme tehdä sen muutamalla näppäimen painalluksella. Kielipalvelut antavat meille lisää oivalluksia ja hyvin nopeasti.
Huomaa, että emme ole vielä kutsuneet tiettyjä tekstieditoreja. Selitetään miksi esimerkillä.
Oletetaan, että olet kehittänyt uuden ohjelmointikielen nimeltä Lapine. Se on kaunis kieli ja kääntäjä antaa loistavan Jalava -tyyppisiä virheilmoituksia. Lisäksi voit tarjota koodin täydennyksen, viitteet, korjausohjeet ja diagnostiikan.
Mitä koodi- / tekstieditoria tuet ensin? Entä sen jälkeen? Sinulla on ylämäkeen taistelu taistellaksesi ihmisten omaksumiseksi, joten haluat tehdä siitä mahdollisimman helpon. Et halua valita väärää editoria ja menettää käyttäjiä. Entä jos pidät etäisyyttä koodieditorista ja keskityt erikoisuuteesi - kieleen ja sen ominaisuuksiin?
Tulla sisään kielipalvelimet . Nämä ovat työkaluja, joiden kanssa puhutaan kieliasiakkaat ja antaa mainitsemamme oivallukset. Ne ovat riippumattomia tekstieditorista syistä, jotka juuri kuvasimme hypoteettisessa tilanteessamme.
Kuten tavallista, tarvitsemme toisen kerroksen abstraktiota. Nämä lupaavat rikkoa kielityökalujen ja koodieditorien tiukan yhdistämisen. Kielen luojat voivat kääri ominaisuutensa palvelimeen kerran, ja koodi- / tekstieditorit voivat lisätä pieniä laajennuksia muuttaakseen itsensä asiakkaiksi. Se on voitto kaikille. Tämän helpottamiseksi meidän on kuitenkin sovittava siitä, miten nämä asiakkaat ja palvelimet kommunikoivat.
Onneksi meille, tämä ei ole hypoteettista. Microsoft on jo alkanut määrittelemällä kielipalvelimen protokollaa .
Kuten useimpien upeiden ideoiden kohdalla, se kasvoi välttämättömyydestä eikä ennakoinnista. Monet koodieditorit olivat jo alkaneet lisätä tukea erilaisille kieliominaisuuksille; jotkut ominaisuudet ulkoistetaan kolmansien osapuolten työkaluille, jotkut tehdään päällekkäin editorissa. Skaalautuvuusongelmat tulivat esiin, ja Microsoft otti johtoaseman asioiden jakamisessa. Kyllä, Microsoft raivasi tien siirtää nämä ominaisuudet pois koodieditorista sen sijaan, että keräisi niitä VSCodeen. He olisivat voineet jatkaa rakennustyökalunsa lukitsemista käyttäjiin - mutta he vapauttivat heidät.
Kielipalvelinprotokolla (LSP) määriteltiin vuonna 2016 helpottamaan kielityökalujen ja muokkaajien erottamista. Siellä on vielä monia VSCode-sormenjälkiä, mutta se on merkittävä askel toimittajan agnostismin suuntaan. Tutkitaan protokollaa vähän.
Asiakkaat ja palvelimet - ajatuskoodieditorit ja kielityökalut - kommunikoivat yksinkertaisilla tekstiviesteillä. Näillä viesteillä on HTTP-tyyppiset otsikot, JSON-RPC-sisältö, ja ne voivat olla peräisin joko asiakkaalta tai palvelimelta. JSON-RPC-protokolla määrittelee pyynnöt, vastaukset ja ilmoitukset sekä muutaman niiden ympärillä olevan perussäännön. Keskeinen piirre on, että se on suunniteltu toimimaan asynkronisesti, joten asiakkaat / palvelimet voivat käsitellä viestejä järjestyksessä ja jonkin verran rinnakkain.
Lyhyesti sanottuna JSON-RPC antaa asiakkaan pyytää toista ohjelmaa suorittamaan menetelmän parametreillä ja palauttamaan tuloksen tai virheen. LSP perustuu tähän ja määrittelee käytettävissä olevat menetelmät, odotetut tietorakenteet ja muutaman muun säännön tapahtumien ympärille. Esimerkiksi kättelyprosessi tapahtuu, kun asiakas käynnistää palvelimen.
Palvelin on tilallinen ja tarkoitettu vain yhden asiakkaan käsittelemiseen kerrallaan. Viestinnässä ei kuitenkaan ole nimenomaisia rajoituksia, joten kielipalvelin voisi ajaa eri koneella kuin asiakas. Käytännössä se olisi kuitenkin melko hidasta reaaliaikaiselle palautteelle. Kielipalvelimet ja asiakkaat työskentelevät samojen tiedostojen kanssa ja ovat melko puhuttelevia.
LSP on kunnollinen määrä dokumentointi kun tiedät mitä etsiä. Kuten mainittiin, suuri osa tästä kirjoitetaan VSCode-kontekstissa, vaikka ideoilla onkin paljon laajempi soveltamisala. Esimerkiksi protokollamääritykset kirjoitetaan kaikki TypeScript-muodossa. Tässä on perusteet auttamaan tutkijoita, jotka eivät tunne VSCode- ja TypeScript-tiedostoja.
Kielipalvelimen protokollassa on määritelty useita viestiryhmiä. Ne voidaan jakaa karkeasti 'järjestelmänvalvojaan' ja 'kieliominaisuuksiin'. Järjestelmänvalvojan viestit sisältävät ne, joita käytetään asiakas / palvelin kättelyssä, tiedostojen avaamisessa / muuttamisessa jne. Tärkeää on, että tässä asiakas ja palvelimet jakavat käsittelemiään ominaisuuksia. Eri kielet ja työkalut tarjoavat varmasti erilaisia ominaisuuksia. Tämä mahdollistaa myös asteittaisen hyväksymisen. Langserver.org nimeää puoli tusinaa avainominaisuutta, joita asiakkaiden ja palvelinten tulisi tukea, joista vähintään yhden vaaditaan luettelon tekemiseen.
Kielitoiminnot ovat niistä, joista olemme enimmäkseen kiinnostuneita. Näistä yksi on syytä kutsua erityisesti: diagnostiikkaviesti. Diagnostiikka on yksi tärkeimmistä ominaisuuksista. Kun avaat tiedoston, lähinnä oletetaan, että tämä toimii. Toimittajan tulisi kertoa, onko tiedostossa jotain vikaa. Näin tapahtuu LSP: n kanssa:
textDocument/didOpen
palvelimelle.textDocument/publishDiagnostics
ilmoituksen.Tämä on passiivinen tapa saada tietoa kielipalveluistasi. Aktiivisempi esimerkki olisi löytää kaikki viitteet symbolille kohdistimen alapuolelta. Tämä menisi noin:
textDocument/references
palvelimelle määrittämällä sijainti tiedostossa.Voisimme varmasti syventyä kielipalvelimen protokollan yksityiskohtiin, mutta jätetään se asiakkaan toteuttajille. Edistääkseen muokkausohjelman ja kielityökalujen erottamisen idean me näytämme työkalun luojaa.
Pidämme sen yksinkertaisena ja pidämme diagnostiikkaa uuden kielen ja ominaisuuksien luomisen sijaan. Diagnostiikka sopii hyvin: ne ovat vain varoituksia tiedoston sisällöstä. Linter palauttaa diagnostiikan. Teemme jotain samanlaista.
Teemme työkalun ilmoittamaan meille sanoista, joita haluaisimme välttää. Sitten tarjoamme tämän toiminnon muutamalle erilaiselle tekstieditorille.
Ensinnäkin työkalu. Leivotaan tämä suoraan kielipalvelimeksi. Yksinkertaisuuden vuoksi tämä on a Node.js sovelluksen, vaikka voimme tehdä sen minkä tahansa tekniikan kanssa, joka pystyy käyttämään virtoja lukemiseen ja kirjoittamiseen.
Tässä on logiikka. Annettuaan jonkin verran tekstiä, tämä menetelmä palauttaa joukon vastaavia mustalla listalla olevia sanoja ja indeksejä, joista ne löytyivät.
const getBlacklisted = (text) => { const blacklist = [ 'foo', 'bar', 'baz', ] const regex = new RegExp(`\b($'))\b`, 'gi') const results = [] while ((matches = regex.exec(text)) && results.length <100) { results.push({ value: matches[0], index: matches.index, }) } return results }
Tehdään nyt siitä palvelin.
const { TextDocuments, createConnection, } = require('vscode-languageserver') const {TextDocument} = require('vscode-languageserver-textdocument') const connection = createConnection() const documents = new TextDocuments(TextDocument) connection.onInitialize(() => ({ capabilities: { textDocumentSync: documents.syncKind, }, })) documents.listen(connection) connection.listen()
Tässä käytämme vscode-languageserver
. Nimi on harhaanjohtava, koska se voi varmasti toimia VSCoden ulkopuolella. Tämä on yksi monista 'sormenjäljistä', jotka näet LSP: n alkuperästä. vscode-languageserver
huolehtii alemman tason protokollasta ja antaa sinun keskittyä käyttötapauksiin. Tämä katkelma muodostaa yhteyden ja sitoo sen asiakirjahallintaan. Kun asiakas muodostaa yhteyden palvelimeen, palvelin kertoo haluavansa ilmoituksen tekstidokumenttien avaamisesta.
Voisimme pysähtyä täällä. Tämä on täysin toimiva, vaikkakin turha LSP-palvelin. Sen sijaan vastaamme asiakirjan muutoksiin diagnostiikkatiedoilla.
documents.onDidChangeContent(change => { connection.sendDiagnostics({ uri: change.document.uri, diagnostics: getDiagnostics(change.document), }) })
Lopuksi yhdistämme pisteet muuttuneen asiakirjan, logiikkamme ja diagnostiikkavasteen välillä.
const getDiagnostics = (textDocument) => getBlacklisted(textDocument.getText()) .map(blacklistToDiagnostic(textDocument)) const { DiagnosticSeverity, } = require('vscode-languageserver') const blacklistToDiagnostic = (textDocument) => ({ index, value }) => ({ severity: DiagnosticSeverity.Warning, range: { start: textDocument.positionAt(index), end: textDocument.positionAt(index + value.length), }, message: `${value} is blacklisted.`, source: 'Blacklister', })
Diagnostiikan hyötykuormamme on seurausta asiakirjan tekstin suorittamisesta toiminnon kautta, joka on sitten sovitettu asiakkaan odottamaan muotoon.
Tämä komentosarja luo kaiken tämän sinulle.
curl -o- https://raw.githubusercontent.com/reergymerej/lsp-article-resources/revision-for-6.0.0/blacklist-server-install.sh | bash
Huomaa: Jos tuntemattomien ihmisten on lisättävä suoritettavia tiedostoja koneellesi, ole hyvä tarkista lähde . Se luo projektin, lataa index.js
ja npm link
s sen sinulle.
Lopullinen blacklist-server
lähde on:
#!/usr/bin/env node const { DiagnosticSeverity, TextDocuments, createConnection, } = require('vscode-languageserver') const {TextDocument} = require('vscode-languageserver-textdocument') const getBlacklisted = (text) => { const blacklist = [ 'foo', 'bar', 'baz', ] const regex = new RegExp(`\b($'))\b`, 'gi') const results = [] while ((matches = regex.exec(text)) && results.length ({ index, value }) => ({ severity: DiagnosticSeverity.Warning, range: { start: textDocument.positionAt(index), end: textDocument.positionAt(index + value.length), }, message: `${value} is blacklisted.`, source: 'Blacklister', }) const getDiagnostics = (textDocument) => getBlacklisted(textDocument.getText()) .map(blacklistToDiagnostic(textDocument)) const connection = createConnection() const documents = new TextDocuments(TextDocument) connection.onInitialize(() => ({ capabilities: { textDocumentSync: documents.syncKind, }, })) documents.onDidChangeContent(change => { connection.sendDiagnostics({ uri: change.document.uri, diagnostics: getDiagnostics(change.document), }) }) documents.listen(connection) connection.listen()
Kun projekti on link
muokattu, yritä suorittaa palvelin määrittelemällä stdio
kuljetusmekanismina:
blacklist-server --stdio
Se kuuntelee stdio
nyt LSP-viesteistä, joista puhuimme aiemmin. Voisimme tarjota ne manuaalisesti, mutta luodaan sen sijaan asiakas.
Koska tämä tekniikka on peräisin VSCodesta, vaikuttaa tarkoituksenmukaiselta aloittaa siitä. Luomme laajennuksen, joka luo LSP-asiakkaan ja yhdistää sen juuri tekemäämme palvelimeen.
On useilla tavoilla luoda VSCode-laajennus, mukaan lukien Yeomanin ja sopivan generaattorin käyttö, generator-code
Tehkäämme yksinkertaisuuden vuoksi esimerkiksi barebones-esimerkki.
Kloonataan kattilalevy ja asennetaan sen riippuvuudet:
git clone [email protected] :reergymerej/standalone-vscode-ext.git blacklist-vscode cd blacklist-vscode npm i # or yarn
Avaa blacklist-vscode
hakemiston VSCode.
Paina F5 aloittaaksesi toisen VSCode-ilmentymän, virheenkorjaamalla laajennuksen.
Ensimmäisen VSCode-esiintymän 'virheenkorjauskonsolissa' näet tekstin 'Katso, ma. Laajennus!'
Olemme nyt saaneet perustason VSCode-laajennuksen toimimaan ilman kaikkia kelloja ja pillejä. Tehdään siitä LSP-asiakas. Sulje molemmat VSCode-esiintymät ja blacklist-vscode
hakemisto, suorita:
npm i vscode-languageclient
Korvata extension.js kanssa:
const { LanguageClient } = require('vscode-languageclient') module.exports = { activate(context) { const executable = { command: 'blacklist-server', args: ['--stdio'], } const serverOptions = { run: executable, debug: executable, } const clientOptions = { documentSelector: [{ scheme: 'file', language: 'plaintext', }], } const client = new LanguageClient( 'blacklist-extension-id', 'Blacklister', serverOptions, clientOptions ) context.subscriptions.push(client.start()) }, }
Tässä käytetään vscode-languageclient
paketti LSP-asiakkaan luomiseen VSCodeen. Toisin kuin vscode-languageserver
, tämä on tiukasti kytketty VSCodeen. Lyhyesti sanottuna, mitä teemme tässä laajennuksessa, on luoda asiakas ja käskeä sitä käyttämään edellisissä vaiheissa luomaa palvelinta. Kiihdyttämällä VSCode-laajennuksen yksityiskohtia voimme nähdä, että käskemme sitä käyttämään tätä LSP-asiakasta tavallisten tekstitiedostojen varten.
Testaa sitä avaamalla blacklist-vscode
hakemiston VSCode. Aloita toinen ilmentymä painamalla F5 aloittaaksesi virheenkorjaus.
Luo uudessa VSCode-ilmentymässä tekstitiedosto ja tallenna se. Kirjoita 'foo' tai 'bar' ja odota hetki. Näet varoituksia siitä, että nämä ovat mustalla listalla.
Se siitä! Meidän ei tarvinnut luoda mitään logiikkaamme, vain koordinoida asiakasta ja palvelinta.
Tehdään se uudelle muokkaajalle, tällä kertaa Sublime Text 3. Prosessi on melko samanlainen ja hieman helpompaa.
Avaa ensin ST3 ja avaa komentopaletti. Tarvitsemme kehyksen, jotta editorista voidaan tehdä LSP-asiakas. Kirjoita “Package Control: Install Package” ja paina Enter. Etsi paketti “LSP” ja asenna se. Kun olet valmis, meillä on kyky määrittää LSP-asiakkaat. Presettejä on monia, mutta emme aio käyttää niitä. Olemme luoneet oman.
Avaa komentopaletti uudelleen. Etsi ”Preferences: LSP Settings” ja paina Enter. Tämä avaa LSP-paketin määritystiedoston LSP.sublime-settings
Lisää mukautettu asiakas käyttämällä alla olevaa määritystä.
{ 'clients': { 'blacklister': { 'command': [ 'blacklist-server', '--stdio' ], 'enabled': true, 'languages': [ { 'syntaxes': [ 'Plain text' ] } ] } }, 'log_debug': true }
Tämä saattaa näyttää tutulta VSCode-laajennuksesta. Määritimme asiakkaan, käskimme sen työskentelemään pelkkien tekstitiedostojen kanssa ja määritimme kielipalvelimen.
Tallenna asetukset, luo ja tallenna sitten tekstitiedosto. Kirjoita 'foo' tai 'bar' ja odota. Jälleen näet varoituksia siitä, että nämä ovat mustalla listalla. Käsittely - miten viestit näkyvät editorissa - on erilainen. Toiminnollisuutemme on kuitenkin sama. Olemme tuskin edes tehneet mitään tällä kertaa lisätäksesi tukea editorille.
Jos et ole vieläkään vakuuttunut siitä, että tämä huolenaiheiden jakaminen helpottaa ominaisuuksien jakamista tekstieditorien välillä, tässä on vaiheet saman toiminnon lisäämiseksi Vimiin Coc .
Avaa Vim ja kirjoita :CocConfig
ja lisää sitten:
'languageserver': { 'blacklister': { 'command': 'blacklist-server', 'args': ['--stdio'], 'filetypes': ['text'] } }
Tehty.
Kielipalveluiden vastuun erottaminen tekstieditorista, joissa niitä käytetään, on selvästi voitto. Se antaa kieliominaisuuksien luojille mahdollisuuden keskittyä erikoisaloihinsa ja editorin luojien tehdä samoin. Se on melko uusi idea, mutta hyväksyminen on leviämässä.
Nyt kun sinulla on perusta työskennellä, voit ehkä löytää projektin ja auttaa siirtämään tätä ideaa eteenpäin. Toimittajan liekkisota ei koskaan lopu, mutta se on OK. Niin kauan kuin kielitaitoja voi esiintyä tiettyjen toimittajien ulkopuolella, voit vapaasti käyttää haluamaasi editoria.
Kuten a Microsoft Gold -kumppani , ApeeScape on Microsoft-asiantuntijoidesi eliittiverkosto. Rakenna korkean suorituskyvyn omaavia tiimejä tarvitsemiesi asiantuntijoiden kanssa - missä tahansa ja juuri silloin, kun tarvitset niitä!
Kielipalvelinprotokolla on joukko sääntöjä, jotka kuvaavat, miten kieliasiakkaiden ja kielipalvelimien tulisi kommunikoida. Se määriteltiin vuonna 2016 auttamaan erottamaan toimittajat kielikohtaisista työkaluista, kuten tsserver.
C ++, Java, Erlang, Go ja Common Lisp ovat kaikki käännettyjä kieliä, mikä tarkoittaa, että niiden lähde muunnetaan toiseen muotoon, kuten konekoodiksi, ennen suoritusta. Tulkittujen kielten, kuten Pythonin tai JavaScriptin, lähdekoodi ajetaan tulkin kautta ohjelmien suorituksen aikana.
Kääntäjän tehtävänä on muuntaa lähdekoodi toiseen muotoon suoritettavaksi, tyypillisesti konekoodiksi. Tämä eroaa transpileristä, joka muuntaa lähdekoodin toisen tyyppiseksi lähdekoodiksi, kuten TypeScript JavaScriptiksi. Kääntäjä ilmoittaa lähdekoodivirheistä.
Kääntäjän päätehtävä on muuntaa lähdekoodi konekoodiksi. Tähän sisältyy lexing ja jäsentäminen ohjelman mallin rakentamiseksi, optimointien toteuttaminen ja kohdekoodin luominen. Käyttöliittymän analyysi antaa palautetta, joka voi auttaa kehittäjiä tunnistamaan virheet syntaksissa.
Tekstieditorit ovat ohjelmia, joita käytetään tekstitiedostojen muokkaamiseen, esimerkiksi Notepad, Word, Notepad ++, Sublime Text, Vim ja Emacs. Tyypillisesti kehittäjät välttävät yksinkertaisten tekstieditorien käyttämistä ohjelmoinnissa, ellei niitä voida laajentaa ymmärtämään tekstiä ohjelmointikielen yhteydessä ja muuttamaan ne tosiasiallisesti IDEiksi.
VSCode tehdään Node.js: llä, Electronin kautta. Lähde on saatavilla Githubissa Microsoftin arkistoluettelossa.