Zprostředkovatel rozšiřitelnosti jazykového serveru

Poskytovatel jazykového serveru zahrnuje proces hostovaný mimo Visual Studio a poskytuje funkce jazyka, které nejsou v sadě Visual Studio.

Tyto servery musí dodržovat protokol jazykového serveru, vytvořený projektem rozšíření a implementovat LanguageServerProvider.

Práce se zprostředkovateli jazykových serverů

Tento přehled popisuje tyto hlavní scénáře práce s poskytovateli jazykových serverů:

Vytvoření poskytovatele jazykového serveru

Vytvoření poskytovatele jazykového serveru zahrnuje přidání nové třídy, která rozšiřuje Microsoft.VisualStudio.Extensibility.LanguageServer.LanguageServerProvider a aplikuje na VisualStudioContribution něj atribut.

[VisualStudioContribution]
public class MyLanguageServerProvider : LanguageServerProvider
{
    public MyLanguageServerProvider(ExtensionCore container, VisualStudioExtensibility extensibilityObject, TraceSource traceSource)
        : base(container, extensibilityObject)
    {
    }
}

Po definování poskytovatele potřebujete:

  1. Nakonfigurujte zprostředkovatele přepsáním LanguageServerProviderConfiguration vlastnosti. Tato vlastnost konfigurace definuje zobrazovaný název serveru a příslušné typy dokumentů. LanguageServerBaseDocumentType je k dispozici pro všechny servery a triggery pro všechny typy dokumentů. Viz Definice vlastního typu dokumentu.

    public override LanguageServerProviderConfiguration LanguageServerProviderConfiguration => new("My Language Server",
        new[]
        {
           DocumentFilter.FromDocumentType(LanguageServerBaseDocumentType),
        });
    
  2. Přepište metodu CreateServerConnectionAsync , která je volána sadou Visual Studio, aby oznámila rozšíření, že má být spuštěn server LSP.

    // 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()));
    }
    
  3. Přepište metodu OnServerInitializationResultAsync , která je volána sadou Visual Studio po dokončení spouštěcího a konfiguračního postupu serveru LSP. ServerInitializationResult poskytuje výsledný stav serveru a LanguageServerInitializationFailureInfo poskytuje výjimku, pokud existuje.

    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;
    }
    

Po dokončení všechkrokůch

[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;
    }
}

Odeslání dalších dat při spuštění jazykového serveru

LanguageServerOptions.InitializationOptions lze nastavit v konstruktoru pro LanguageServerProvider odesílání dalších dat na server se zprávou "initialize" protokolu.

public MyLanguageServerProvider(ExtensionCore container, VisualStudioExtensibility extensibilityObject, TraceSource traceSource)
    : base(container, extensibilityObject)
{
    this.LanguageServerOptions.InitializationOptions = JToken.Parse(@"[{""server"":""initialize""}]");
}

Definování vlastních typů dokumentů

Pokud přípona podporuje typy souborů, které nejsou nativně podporovány sadou Visual Studio, můžou autoři rozšíření implementovat vlastní typy dokumentů. Tyto typy lze použít při definování LanguageServerProviderConfiguration k určení podporovaných typů dokumentů.

[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,
};

Tento fragment kódu definuje dva nové typy dokumentů: rust a markdown. Tyto typy obsahují seznam přípon souborů a základní typ, který může zahrnovat LanguageServerBaseDocumentType všechny typy.

Tyto typy slouží LanguageServerProviderConfiguration k aktivaci serveru při otevření těchto typů dokumentů:

public override LanguageServerProviderConfiguration LanguageServerProviderConfiguration =>
    new("My Language Server",
        new[]
        {
            DocumentFilter.FromDocumentType(RustDocumentType),
            DocumentFilter.FromDocumentType(MarkdownDocumentType),
        });

Povolení nebo zakázání jazykového serveru

Po otevření příslušného typu dokumentu je povolený server jazyka aktivovat. Pokud je tato možnost zakázaná, odešle se zpráva stop na jakýkoli použitelný aktivní jazykový server a zabrání dalším aktivací.

[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;
        }
    }
}

Tento fragment kódu zakáže server jazyka nastavením this.Enabledfalse , pokud ServerInitializationResult se nastaví na Failed po selhání inicializace.

Poznámka:

Tento příznak je veřejný a pokud je nastavený na false, zastaví se všechny spuštěné servery.

Použití lokalizovaných prostředků

Lokalizaci podporujeme definováním string-resources.json souboru a určením %tokens% lokalizovaného obsahu.

string-resources.json

{
  { "LocalizedResource": "LangaugeServerLocalized" }
}

Přístup k lokalizovaným prostředkům

[VisualStudioContribution]
public class MyLanguageServer : LanguageServerProvider
{
    ...

    /// <inheritdoc/>
    public override LanguageServerProviderConfiguration LanguageServerProviderConfiguration =>
        new("%LocalizedResource%",
            new[]
            {
                DocumentFilter.FromDocumentType(LanguageServerBaseDocumentType)
            });
}

Další kroky