Provider del server del linguaggio di estendibilità
Un provider del server di linguaggio prevede un processo ospitato all'esterno di Visual Studio e che fornisce funzionalità del linguaggio non presenti in Visual Studio.
Questi server devono rispettare il protocollo del server di linguaggio, creato da un progetto di estensione e implementare LanguageServerProvider
.
Usare i provider del server di linguaggio
Questa panoramica illustra questi scenari principali per l'uso dei provider di server di linguaggio:
- Creare un provider di server di linguaggio
- Inviare dati aggiuntivi all'avvio di un server linguistico
- Definire tipi di documento personalizzati
- Abilitare o disabilitare un server di linguaggio
- Usare le risorse localizzate
Creare un provider di server di linguaggio
La creazione di un provider di server di linguaggio comporta l'aggiunta di una nuova classe che estende Microsoft.VisualStudio.Extensibility.LanguageServer.LanguageServerProvider
e applica l'attributo VisualStudioContribution
.
[VisualStudioContribution]
public class MyLanguageServerProvider : LanguageServerProvider
{
public MyLanguageServerProvider(ExtensionCore container, VisualStudioExtensibility extensibilityObject, TraceSource traceSource)
: base(container, extensibilityObject)
{
}
}
Dopo aver definito il provider, è necessario:
Configurare il provider eseguendo l'override della
LanguageServerProviderConfiguration
proprietà . Questa proprietà di configurazione definisce il nome visualizzato del server e i tipi di documento applicabili.LanguageServerBaseDocumentType
è disponibile per tutti i server e i trigger in tutti i tipi di documento. Vedere Definire un tipo di documento personalizzato.public override LanguageServerProviderConfiguration LanguageServerProviderConfiguration => new("My Language Server", new[] { DocumentFilter.FromDocumentType(LanguageServerBaseDocumentType), });
Eseguire l'override del
CreateServerConnectionAsync
metodo , chiamato da Visual Studio per notificare all'estensione che il server LSP deve essere avviato.// Activate the language server and return a duplex pipe that communicates with the server. public override Task<IDuplexPipe?> CreateServerConnectionAsync(CancellationToken cancellationToken) { (Stream PipeToServer, Stream PipeToVS) = FullDuplexStream.CreatePair(); // Connect "PipeToServer" to the language server return Task.FromResult<IDuplexPipe?>(new DuplexPipe(PipeToVS.UsePipeReader(), PipeToVS.UsePipeWriter())); }
Eseguire l'override del
OnServerInitializationResultAsync
metodo , chiamato da Visual Studio dopo che il server LSP ha completato i passaggi di avvio e configurazione.ServerInitializationResult
fornisce lo stato risultante del server eLanguageServerInitializationFailureInfo
fornisce un'eccezione, se presente.public override Task OnServerInitializationResultAsync(ServerInitializationResult startState,LanguageServerInitializationFailureInfo? initializationFailureInfo, CancellationToken cancellationToken) { // Method called when server activation was completed successfully or failed, denoted by "startState". return Task.CompletedTask; }
Di seguito è riportato l'aspetto del provider di server di linguaggio di esempio dopo aver completato tutti i passaggi:
[VisualStudioContribution]
public class MyLanguageServerProvider : LanguageServerProvider
{
public MyLanguageServerProvider(ExtensionCore container, VisualStudioExtensibility extensibilityObject, TraceSource traceSource)
: base(container, extensibilityObject)
{
}
public override LanguageServerProviderConfiguration LanguageServerProviderConfiguration =>
new("My Language Server",
new[]
{
DocumentFilter.FromDocumentType(LanguageServerBaseDocumentType),
});
// Activate the language server and return a duplex pipe that communicates with the server.
public override Task<IDuplexPipe?> CreateServerConnectionAsync(CancellationToken cancellationToken)
{
(Stream PipeToServer, Stream PipeToVS) = FullDuplexStream.CreatePair();
// Connect "PipeToServer" to the language server
return Task.FromResult<IDuplexPipe?>(new DuplexPipe(PipeToVS.UsePipeReader(), PipeToVS.UsePipeWriter()));
}
public override Task OnServerInitializationResultAsync(ServerInitializationResult startState, LanguageServerInitializationFailureInfo? initializationFailureInfo, CancellationToken cancellationToken)
{
// Method called when server activation was completed successfully or failed, denoted by "startState".
return Task.CompletedTask;
}
}
Inviare dati aggiuntivi all'avvio di un server linguistico
LanguageServerOptions.InitializationOptions
può essere impostato nel costruttore per LanguageServerProvider
inviare dati aggiuntivi al server con il messaggio di protocollo "inizializza".
public MyLanguageServerProvider(ExtensionCore container, VisualStudioExtensibility extensibilityObject, TraceSource traceSource)
: base(container, extensibilityObject)
{
this.LanguageServerOptions.InitializationOptions = JToken.Parse(@"[{""server"":""initialize""}]");
}
Definire tipi di documento personalizzati
Quando un'estensione supporta i tipi di file non supportati in modo nativo da Visual Studio, gli autori di estensioni possono implementare tipi di documento personalizzati. Questi tipi possono essere usati quando si definiscono LanguageServerProviderConfiguration
per specificare i tipi di documento supportati.
[VisualStudioContribution]
internal static DocumentTypeConfiguration RustDocumentType => new("rust")
{
FileExtensions = new[] { ".rs", ".rust" },
BaseDocumentType = LanguageServerBaseDocumentType,
};
[VisualStudioContribution]
internal static DocumentTypeConfiguration MarkdownDocumentType => new("markdown")
{
FileExtensions = new[] { ".md" },
BaseDocumentType = LanguageServerBaseDocumentType,
};
Questo frammento di codice definisce due nuovi tipi di documento: rust
e markdown
. Questi tipi contengono un elenco di estensioni di file e un tipo di base, che può essere LanguageServerBaseDocumentType
per coprire tutti i tipi.
Usare questi tipi in LanguageServerProviderConfiguration
per attivare il server quando questi tipi di documento vengono aperti:
public override LanguageServerProviderConfiguration LanguageServerProviderConfiguration =>
new("My Language Server",
new[]
{
DocumentFilter.FromDocumentType(RustDocumentType),
DocumentFilter.FromDocumentType(MarkdownDocumentType),
});
Abilitare o disabilitare un server di linguaggio
Un server di lingua abilitato può "attivare" una volta aperto un tipo di documento applicabile. Se disabilitato, un messaggio di arresto viene inviato a qualsiasi server di lingua attivo applicabile e impedisce ulteriori attivazioni.
[VisualStudioContribution]
public class MyLanguageServerProvider : LanguageServerProvider
{
...
public override Task OnServerInitializationResultAsync(ServerInitializationResult startState, LanguageServerInitializationException? initializationFailureInfo, CancellationToken cancellationToken)
{
if (startState == ServerInitializationResult.Failed)
{
Telemetry.LogEvent(initializationFailureInfo.StatusMessage, initializationFailureInfo.Exception)
// Disable the language server.
this.Enabled = false;
}
}
}
Questo frammento di codice disabilita il server di linguaggio impostando this.Enabled
su false
se ServerInitializationResult
viene impostato su Failed
dopo che non è stato possibile inizializzare.
Nota
Questo flag è pubblico e, se impostato su false, tutti i server in esecuzione vengono arrestati.
Usare le risorse localizzate
È supportato l'uso della localizzazione definendo un string-resources.json
file e usando %tokens%
per specificare il contenuto localizzato.
string-resources.json
{
{ "LocalizedResource": "LangaugeServerLocalized" }
}
Accedere a una risorsa localizzata
[VisualStudioContribution]
public class MyLanguageServer : LanguageServerProvider
{
...
/// <inheritdoc/>
public override LanguageServerProviderConfiguration LanguageServerProviderConfiguration =>
new("%LocalizedResource%",
new[]
{
DocumentFilter.FromDocumentType(LanguageServerBaseDocumentType)
});
}
Passaggi successivi
- Seguire l'esercitazione creare la prima estensione per iniziare a creare un'estensione.
- Per un esempio completo di creazione di un'estensione con un provider di server di linguaggio, vedere l'esempio del provider del server di linguaggio Rust.