Aggiungere un'estensione del protocollo di server di linguaggio
Il protocollo LSP (Language Server Protocol) è un protocollo comune, sotto forma di RPC JSON v2.0, usato per fornire funzionalità del servizio di linguaggio a vari editor di codice. Usando il protocollo, gli sviluppatori possono scrivere un singolo server di linguaggio per fornire funzionalità del servizio di linguaggio come IntelliSense, diagnostica degli errori, trovare tutti i riferimenti e così via, a vari editor di codice che supportano il provider di servizi di configurazione locale. Tradizionalmente, i servizi di linguaggio in Visual Studio possono essere aggiunti usando i file di grammatica TextMate per fornire funzionalità di base, ad esempio l'evidenziazione della sintassi o scrivendo servizi di linguaggio personalizzati che usano il set completo di API di estendibilità di Visual Studio per fornire dati più completi. Con il supporto di Visual Studio per LSP, è disponibile una terza opzione.
Per garantire la migliore esperienza utente possibile, è consigliabile implementare anche La configurazione del linguaggio, che fornisce l'elaborazione locale di molte delle stesse operazioni e può quindi migliorare le prestazioni di molte delle operazioni dell'editor specifiche del linguaggio supportate dal provider di servizi di configurazione locale.
Protocollo di server di linguaggio
Questo articolo descrive come creare un'estensione di Visual Studio che usa un server di linguaggio basato su LSP. Si presuppone che sia già stato sviluppato un server di linguaggio basato su LSP e che si voglia semplicemente integrarlo in Visual Studio.
Per il supporto in Visual Studio, i server di linguaggio possono comunicare con il client (Visual Studio) tramite qualsiasi meccanismo di trasmissione basato su flusso, ad esempio:
- Flussi di input/output standard
- Named pipe
- Socket (solo TCP)
Lo scopo del provider di servizi di configurazione locale e del supporto in Visual Studio consiste nell'eseguire l'onboarding dei servizi di linguaggio che non fanno parte del prodotto Visual Studio. Non è progettato per estendere i servizi di linguaggio esistenti (ad esempio C#) in Visual Studio. Per estendere i linguaggi esistenti, vedere la guida all'estendibilità del servizio di linguaggio (ad esempio, la piattaforma del compilatore .NET Roslyn) o vedere Estendere l'editor e i servizi di linguaggio.
Per altre informazioni sul protocollo stesso, vedere la documentazione qui.
Per altre informazioni su come creare un server di linguaggio di esempio o su come integrare un server di linguaggio esistente in Visual Studio Code, vedere la documentazione qui.
Funzionalità supportate da Language Server Protocol
Le tabelle seguenti illustrano le funzionalità LSP supportate in Visual Studio:
Message | Supporto in Visual Studio |
---|---|
inizializzazione | yes |
inizializzato | yes |
shutdown | yes |
exit | yes |
$/cancelRequest | yes |
window/showMessage | yes |
window/showMessageRequest | yes |
window/logMessage | yes |
telemetria/evento | |
client/registerCapability | |
client/unregisterCapability | |
workspace/didChangeConfiguration | yes |
workspace/didChangeWatchedFiles | yes |
area di lavoro/simbolo | yes |
workspace/executeCommand | yes |
workspace/applyEdit | yes |
textDocument/publishDiagnostics | yes |
textDocument/didOpen | yes |
textDocument/didChange | yes |
textDocument/willSave | |
textDocument/willSaveWaitUntil | |
textDocument/didSave | yes |
textDocument/didClose | yes |
textDocument/completamento | yes |
completamento/risoluzione | yes |
textDocument/passaggio del mouse | yes |
textDocument/signatureHelp | yes |
textDocument/references | yes |
textDocument/documentHighlight | yes |
textDocument/documentSymbol | yes |
textDocument/formattazione | yes |
textDocument/rangeFormatting | yes |
textDocument/onTypeFormatting | |
textDocument/definition | yes |
textDocument/codeAction | yes |
textDocument/codeLens | |
codeLens/resolve | |
textDocument/documentLink | |
documentLink/resolve | |
textDocument/rename | yes |
Operazioni preliminari
Nota
A partire da Visual Studio 2017 versione 15.8, il supporto per Common Language Server Protocol è integrato in Visual Studio. Se sono state compilate estensioni LSP usando la versione VSIX del client di Language Server di anteprima, l'aggiornamento alla versione 15.8 o successiva smetterà di funzionare. Per ripristinare il funzionamento delle estensioni LSP, è necessario eseguire le operazioni seguenti:
Disinstallare microsoft Visual Studio Language Server Protocol Preview VSIX.
A partire dalla versione 15.8, ogni volta che si esegue un aggiornamento in Visual Studio l'anteprima VSIX viene rilevato e rimosso automaticamente.
Aggiornare il riferimento NuGet alla versione non di anteprima più recente per i pacchetti LSP.
Rimuovere la dipendenza da Microsoft Visual Studio Language Server Protocol Preview VSIX nel manifesto VSIX.
Assicurarsi che VSIX specifichi Visual Studio 2017 versione 15.8 Preview 3 come limite inferiore per la destinazione di installazione.
Ricompilare e ridistribuire.
Creare un progetto VSIX
Per creare un'estensione del servizio di linguaggio usando un server di linguaggio basato su LSP, verificare prima di tutto che sia installato il carico di lavoro sviluppo di estensioni di Visual Studio per l'istanza di Visual Studio.
Creare quindi un nuovo progetto VSIX passando a File>Nuovo progetto>Visual C#>Extensibility>VSIX Project:
Installazione del server di linguaggio e del runtime
Per impostazione predefinita, le estensioni create per supportare i server di linguaggio basati su LSP in Visual Studio non contengono i server di linguaggio stessi o i runtime necessari per eseguirli. Gli sviluppatori di estensioni sono responsabili della distribuzione dei server di linguaggio e dei runtime necessari. Esistono diversi modi per eseguire questa operazione:
- I server di linguaggio possono essere incorporati in VSIX come file di contenuto.
- Creare un'identità del servizio gestito per installare il server di linguaggio e/o i runtime necessari.
- Fornire istruzioni su Marketplace per informare gli utenti su come ottenere runtime e server di linguaggio.
File di grammatica TextMate
Il provider di servizi di configurazione locale non include specifiche su come fornire la colorazione del testo per le lingue. Per fornire colorazioni personalizzate per i linguaggi in Visual Studio, gli sviluppatori di estensioni possono usare un file di grammatica TextMate. Per aggiungere file di grammatica o tema TextMate personalizzati, seguire questa procedura:
Creare una cartella denominata "Grammars" all'interno dell'estensione (o può essere qualsiasi nome scelto).
All'interno della cartella Grammars includere qualsiasi file *.tmlanguage, *.plist, *.tmtheme o *.json che si desidera fornire la colorazione personalizzata.
Suggerimento
Un file con estensione tmtheme definisce il mapping degli ambiti alle classificazioni di Visual Studio (chiavi di colore denominate). Per indicazioni, è possibile fare riferimento al file tmtheme globale nella directory %ProgramFiles(x86)%\Microsoft Visual Studio\<version>\SKU>\<Common7\IDE\CommonExtensions\Microsoft\TextMate\Starterkit\Themesg.
Creare un file con estensione pkgdef e aggiungere una riga simile alla seguente:
[$RootKey$\TextMate\Repositories] "MyLang"="$PackageFolder$\Grammars"
Fare clic con il pulsante destro del mouse sui file e scegliere Proprietà. Modificare l'azione Di compilazione in Contenuto e modificare la proprietà Includi in VSIX impostandola su true.
Dopo aver completato i passaggi precedenti, una cartella Grammars viene aggiunta alla directory di installazione del pacchetto come origine del repository denominata "MyLang" ('MyLang' è solo un nome per la disambiguazione e può essere qualsiasi stringa univoca). Tutte le grammatiche (file con estensione tmlanguage ) e i file di tema (file con estensione tmtheme ) in questa directory vengono prelevati come potenziali e sostituiscono le grammatiche predefinite fornite con TextMate. Se le estensioni dichiarate del file grammaticale corrispondono all'estensione del file aperto, TextMate eseguirà il passaggio.
Creare un client di linguaggio semplice
Interfaccia principale - ILanguageClient
Dopo aver creato il progetto VSIX, aggiungere i pacchetti NuGet seguenti al progetto:
Nota
Quando si accetta una dipendenza dal pacchetto NuGet dopo aver completato i passaggi precedenti, anche i pacchetti Newtonsoft.Json e StreamJsonRpc vengono aggiunti al progetto. Non aggiornare questi pacchetti, a meno che non si sia certi che tali nuove versioni verranno installate nella versione di Visual Studio di destinazione dell'estensione. Gli assembly non verranno inclusi nel vsix; Verranno invece prelevati dalla directory di installazione di Visual Studio. Se si fa riferimento a una versione più recente degli assembly rispetto a quella installata nel computer di un utente, l'estensione non funzionerà.
È quindi possibile creare una nuova classe che implementa l'interfaccia ILanguageClient , ovvero l'interfaccia principale necessaria per i client di linguaggio che si connettono a un server di linguaggio basato su LSP.
Di seguito è riportato un esempio:
namespace MockLanguageExtension
{
[ContentType("bar")]
[Export(typeof(ILanguageClient))]
public class BarLanguageClient : ILanguageClient
{
public string Name => "Bar Language Extension";
public IEnumerable<string> ConfigurationSections => null;
public object InitializationOptions => null;
public IEnumerable<string> FilesToWatch => null;
public event AsyncEventHandler<EventArgs> StartAsync;
public event AsyncEventHandler<EventArgs> StopAsync;
public async Task<Connection> ActivateAsync(CancellationToken token)
{
await Task.Yield();
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Server", @"MockLanguageServer.exe");
info.Arguments = "bar";
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
info.CreateNoWindow = true;
Process process = new Process();
process.StartInfo = info;
if (process.Start())
{
return new Connection(process.StandardOutput.BaseStream, process.StandardInput.BaseStream);
}
return null;
}
public async Task OnLoadedAsync()
{
await StartAsync.InvokeAsync(this, EventArgs.Empty);
}
public Task OnServerInitializeFailedAsync(Exception e)
{
return Task.CompletedTask;
}
public Task OnServerInitializedAsync()
{
return Task.CompletedTask;
}
}
}
I metodi principali che devono essere implementati sono OnLoadedAsync e ActivateAsync. OnLoadedAsync viene chiamato quando Visual Studio ha caricato l'estensione e il server di linguaggio è pronto per l'avvio. In questo metodo è possibile richiamare immediatamente il delegato StartAsync per segnalare che il server di linguaggio deve essere avviato oppure è possibile eseguire logica aggiuntiva e richiamare StartAsync in un secondo momento. Per attivare il server di lingua, è necessario chiamare StartAsync a un certo punto.
ActivateAsync è il metodo richiamato chiamando il delegato StartAsync . Contiene la logica per avviare il server di lingua e stabilire la connessione. È necessario restituire un oggetto connessione che contiene flussi per la scrittura nel server e la lettura dal server. Tutte le eccezioni generate qui vengono rilevate e visualizzate all'utente tramite un messaggio InfoBar in Visual Studio.
Attivazione
Dopo aver implementato la classe client del linguaggio, è necessario definire due attributi per definirne la modalità di caricamento in Visual Studio e attivazione:
[Export(typeof(ILanguageClient))]
[ContentType("bar")]
MEF
Visual Studio usa MEF (Managed Extensibility Framework) per gestire i punti di estendibilità. L'attributo Export indica a Visual Studio che questa classe deve essere prelevata come punto di estensione e caricata al momento appropriato.
Per usare MEF, è anche necessario definire MEF come asset nel manifesto VSIX.
Aprire la finestra di progettazione del manifesto VSIX e passare alla scheda Asset :
Fare clic su Nuovo per creare un nuovo asset:
- Tipo: Microsoft.VisualStudio.MefComponent
- Origine: un progetto nella soluzione corrente
- Progetto: [Progetto]
Definizione del tipo di contenuto
Attualmente, l'unico modo per caricare l'estensione del server di linguaggio basata su LSP è per tipo di contenuto di file. In altre parole, quando si definisce la classe client del linguaggio (che implementa ILanguageClient), sarà necessario definire i tipi di file che, quando aperti, causeranno il caricamento dell'estensione. Se non vengono aperti file che corrispondono al tipo di contenuto definito, l'estensione non verrà caricata.
Questa operazione viene eseguita definendo una o più ContentTypeDefinition
classi:
namespace MockLanguageExtension
{
public class BarContentDefinition
{
[Export]
[Name("bar")]
[BaseDefinition(CodeRemoteContentDefinition.CodeRemoteContentTypeName)]
internal static ContentTypeDefinition BarContentTypeDefinition;
[Export]
[FileExtension(".bar")]
[ContentType("bar")]
internal static FileExtensionToContentTypeDefinition BarFileExtensionDefinition;
}
}
Nell'esempio precedente viene creata una definizione del tipo di contenuto per i file che terminano con estensione bar . Alla definizione del tipo di contenuto viene assegnato il nome "bar" e deve derivare da CodeRemoteContentTypeName.
Dopo aver aggiunto una definizione del tipo di contenuto, è possibile definire quando caricare l'estensione client del linguaggio nella classe client del linguaggio:
[ContentType("bar")]
[Export(typeof(ILanguageClient))]
public class BarLanguageClient : ILanguageClient
{
}
L'aggiunta del supporto per i server di linguaggio LSP non richiede l'implementazione del proprio sistema di progetto in Visual Studio. I clienti possono aprire un singolo file o una cartella in Visual Studio per iniziare a usare il servizio linguistico. In effetti, il supporto per i server di linguaggio LSP è progettato per funzionare solo in scenari di cartella/file aperti. Se viene implementato un sistema di progetto personalizzato, alcune funzionalità (ad esempio le impostazioni) non funzioneranno.
Funzionalità avanzate
Impostazione
È disponibile il supporto per impostazioni personalizzate specifiche del server del linguaggio, ma è ancora in fase di miglioramento. Impostazioni sono specifici di ciò che il server di linguaggio supporta e in genere controlla il modo in cui il server di linguaggio genera dati. Ad esempio, un server di lingua potrebbe avere un'impostazione per il numero massimo di errori segnalati. Gli autori di estensioni definiscono un valore predefinito, che può essere modificato dagli utenti per progetti specifici.
Seguire questa procedura per aggiungere il supporto per le impostazioni all'estensione del servizio di linguaggio LSP:
Aggiungere un file JSON(ad esempio MockLanguageExtension Impostazioni.json) al progetto che contiene le impostazioni e i relativi valori predefiniti. Ad esempio:
{ "foo.maxNumberOfProblems": -1 }
Fare clic con il pulsante destro del mouse sul file JSON e scegliere Proprietà. Impostare l'azione Di compilazione su "Contenuto" e la proprietà "Includi in VSIX" su true.
Implementare ConfigurationSections e restituire l'elenco di prefissi per le impostazioni definite nel file JSON (in Visual Studio Code, verrà eseguito il mapping al nome della sezione di configurazione in package.json):
public IEnumerable<string> ConfigurationSections { get { yield return "foo"; } }
Aggiungere un file con estensione pkgdef al progetto (aggiungere un nuovo file di testo e modificare l'estensione del file in pkgdef). Il file pkgdef deve contenere queste informazioni:
[$RootKey$\OpenFolder\Settings\VSWorkspaceSettings\[settings-name]] @="$PackageFolder$\[settings-file-name].json"
Esempio:
[$RootKey$\OpenFolder\Settings\VSWorkspaceSettings\MockLanguageExtension] @="$PackageFolder$\MockLanguageExtensionSettings.json"
Fare clic con il pulsante destro del mouse sul file con estensione pkgdef e scegliere Proprietà. Modificare l'azione Di compilazione in Contenuto e la proprietà Includi in VSIX impostandola su true.
Aprire il file source.extension.vsixmanifest e aggiungere un asset nella scheda Asset :
- Tipo: Microsoft.VisualStudio.VsPackage
- Origine: File nel file system
- Percorso: [Percorso del file con estensione pkgdef ]
Modifica delle impostazioni utente per un'area di lavoro
L'utente apre un'area di lavoro contenente file di proprietà del server.
L'utente aggiunge un file nella cartella vs denominata VSWorkspace Impostazioni.json.
L'utente aggiunge una riga al file VSWorkspace Impostazioni.json per un'impostazione fornita dal server. Ad esempio:
{ "foo.maxNumberOfProblems": 10 }
Abilitare la traccia diagnostica
La traccia diagnostica può essere abilitata per l'output di tutti i messaggi tra il client e il server, che possono essere utili durante il debug dei problemi. Per abilitare la traccia diagnostica, eseguire le operazioni seguenti:
- Aprire o creare il file di impostazioni dell'area di lavoro VSWorkspace Impostazioni.json (vedere "Modifica utente delle impostazioni per un'area di lavoro").
- Aggiungere la riga seguente nel file JSON delle impostazioni:
{
"foo.trace.server": "Off"
}
Esistono tre valori possibili per la verbosità della traccia:
- "Off": traccia disattivata completamente
- "Messages": la traccia è attivata, ma vengono tracciati solo il nome del metodo e l'ID risposta.
- "Dettagliato": traccia attivata; viene tracciato l'intero messaggio RPC.
Quando la traccia è attivata, il contenuto viene scritto in un file nella directory %temp%\VisualStudio\LSP . Il log segue il formato di denominazione [LanguageClientName]-[Datetime Stamp].log. Attualmente, la traccia può essere abilitata solo per scenari di cartelle aperte. L'apertura di un singolo file per attivare un server linguistico non dispone del supporto per la traccia diagnostica.
Messaggi personalizzati
Sono disponibili API per facilitare il passaggio di messaggi e la ricezione di messaggi dal server di lingua che non fanno parte del protocollo server di linguaggio standard. Per gestire i messaggi personalizzati, implementare l'interfaccia ILanguageClientCustomMessage2 nella classe client del linguaggio. La libreria VS-StreamJsonRpc viene usata per trasmettere messaggi personalizzati tra il client di lingua e il server linguistico. Poiché l'estensione client del linguaggio LSP è esattamente come qualsiasi altra estensione di Visual Studio, è possibile decidere di aggiungere funzionalità aggiuntive (non supportate dal provider di servizi di configurazione locale) a Visual Studio (usando altre API di Visual Studio) nell'estensione tramite messaggi personalizzati.
Ricevere messaggi personalizzati
Per ricevere messaggi personalizzati dal server di linguaggio, implementare la proprietà [CustomMessageTarget]((/dotnet/api/microsoft.visualstudio.languageserver.client.ilanguageclientcustommessage.custommessagetarget) in ILanguageClientCustomMessage2 e restituire un oggetto che sa gestire i messaggi personalizzati. Di seguito è riportato un esempio:
Proprietà (/dotnet/api/microsoft.visualstudio.languageserver.client.ilanguageclientcustommessage.custommessagetarget) in ILanguageClientCustomMessage2 e restituire un oggetto che sa come gestire i messaggi personalizzati. Di seguito è riportato un esempio:
internal class MockCustomLanguageClient : MockLanguageClient, ILanguageClientCustomMessage2
{
private JsonRpc customMessageRpc;
public MockCustomLanguageClient() : base()
{
CustomMessageTarget = new CustomTarget();
}
public object CustomMessageTarget
{
get;
set;
}
public class CustomTarget
{
public void OnCustomNotification(JToken arg)
{
// Provide logic on what happens OnCustomNotification is called from the language server
}
public string OnCustomRequest(string test)
{
// Provide logic on what happens OnCustomRequest is called from the language server
}
}
}
Inviare messaggi personalizzati
Per inviare messaggi personalizzati al server della lingua, implementare il metodo AttachForCustomMessageAsync in ILanguageClientCustomMessage2. Questo metodo viene richiamato all'avvio del server linguistico e pronto per la ricezione dei messaggi. Un oggetto JsonRpc viene passato come parametro, che è quindi possibile mantenere per inviare messaggi al server di linguaggio usando le API VS-StreamJsonRpc . Di seguito è riportato un esempio:
internal class MockCustomLanguageClient : MockLanguageClient, ILanguageClientCustomMessage2
{
private JsonRpc customMessageRpc;
public MockCustomLanguageClient() : base()
{
CustomMessageTarget = new CustomTarget();
}
public async Task AttachForCustomMessageAsync(JsonRpc rpc)
{
await Task.Yield();
this.customMessageRpc = rpc;
}
public async Task SendServerCustomNotification(object arg)
{
await this.customMessageRpc.NotifyWithParameterObjectAsync("OnCustomNotification", arg);
}
public async Task<string> SendServerCustomMessage(string test)
{
return await this.customMessageRpc.InvokeAsync<string>("OnCustomRequest", test);
}
}
Livello intermedio
A volte uno sviluppatore di estensioni potrebbe voler intercettare i messaggi LSP inviati e ricevuti dal server di lingua. Ad esempio, uno sviluppatore di estensioni può voler modificare il parametro del messaggio inviato per un determinato messaggio LSP o modificare i risultati restituiti dal server di linguaggio per una funzionalità LSP (ad esempio i completamenti). Quando necessario, gli sviluppatori di estensioni possono usare l'API MiddleLayer per intercettare i messaggi LSP.
Per intercettare un determinato messaggio, creare una classe che implementa l'interfaccia ILanguageClientMiddleLayer . Implementare quindi l'interfaccia ILanguageClientCustomMessage2 nella classe client del linguaggio e restituire un'istanza dell'oggetto nella proprietà MiddleLayer . Di seguito è riportato un esempio:
public class MockLanguageClient : ILanguageClient, ILanguageClientCustomMessage2
{
public object MiddleLayer => DiagnosticsFilterMiddleLayer.Instance;
private class DiagnosticsFilterMiddleLayer : ILanguageClientMiddleLayer
{
internal readonly static DiagnosticsFilterMiddleLayer Instance = new DiagnosticsFilterMiddleLayer();
private DiagnosticsFilterMiddleLayer() { }
public bool CanHandle(string methodName)
{
return methodName == "textDocument/publishDiagnostics";
}
public async Task HandleNotificationAsync(string methodName, JToken methodParam, Func<JToken, Task> sendNotification)
{
if (methodName == "textDocument/publishDiagnostics")
{
var diagnosticsToFilter = (JArray)methodParam["diagnostics"];
// ony show diagnostics of severity 1 (error)
methodParam["diagnostics"] = new JArray(diagnosticsToFilter.Where(diagnostic => diagnostic.Value<int?>("severity") == 1));
}
await sendNotification(methodParam);
}
public async Task<JToken> HandleRequestAsync(string methodName, JToken methodParam, Func<JToken, Task<JToken>> sendRequest)
{
return await sendRequest(methodParam);
}
}
}
La funzionalità del livello intermedio è ancora in fase di sviluppo e non è ancora completa.
Estensione del server del linguaggio LSP di esempio
Per visualizzare il codice sorgente di un'estensione di esempio usando l'API client LSP in Visual Studio, vedere l'esempio LSP VSSDK-Extensibility-Samples.
Domande frequenti
Si vuole creare un sistema di progetto personalizzato per integrare il server di linguaggio LSP per fornire un supporto più completo delle funzionalità in Visual Studio, come procedere?
Il supporto per i server di linguaggio basati su LSP in Visual Studio si basa sulla funzionalità apri cartella ed è progettato per non richiedere un sistema di progetto personalizzato. È possibile compilare un sistema di progetto personalizzato seguendo le istruzioni riportate qui, ma alcune funzionalità, ad esempio le impostazioni, potrebbero non funzionare. La logica di inizializzazione predefinita per i server di linguaggio LSP consiste nel passare il percorso della cartella radice della cartella attualmente aperta, pertanto se si usa un sistema di progetto personalizzato, potrebbe essere necessario fornire logica personalizzata durante l'inizializzazione per assicurarsi che il server di lingua possa essere avviato correttamente.
Ricerca per categorie aggiungere il supporto del debugger?
In una versione futura verrà fornito il supporto per il protocollo di debug comune.
Se è già installato un servizio di linguaggio supportato da Visual Studio (ad esempio, JavaScript), è comunque possibile installare un'estensione del server del linguaggio LSP che offre funzionalità aggiuntive(ad esempio linting)?
Sì, ma non tutte le funzionalità funzioneranno correttamente. L'obiettivo finale per le estensioni del server di linguaggio LSP è abilitare i servizi di linguaggio non supportati in modo nativo da Visual Studio. È possibile creare estensioni che offrono supporto aggiuntivo usando i server di linguaggio LSP, ma alcune funzionalità (ad esempio IntelliSense) non saranno un'esperienza ottimale. In generale, è consigliabile usare le estensioni del server di linguaggio LSP per fornire nuove esperienze linguistiche, non estendendone quelle esistenti.
Dove si pubblica il server di linguaggio LSP completato VSIX?
Vedere le istruzioni del Marketplace qui.