言語サーバー プロトコルの拡張機能の追加Add a Language Server Protocol extension

言語サーバープロトコル (LSP) は、JSON RPC v2.0 形式の共通プロトコルで、さまざまなコードエディターに言語サービス機能を提供するために使用されます。The Language Server Protocol (LSP) is a common protocol, in the form of JSON RPC v2.0, used to provide language service features to various code editors. 開発者は、このプロトコルを使用して、1つの言語サーバーを作成して、その LSP をサポートするさまざまなコードエディターに IntelliSense、エラー診断、すべての参照の検索などの言語サービス機能を提供できます。Using the protocol, developers can write a single language server to provide language service features like IntelliSense, error diagnostics, find all references, and so on, to various code editors that support the LSP. 従来、Visual Studio の言語サービスは、TextMate 文法ファイルを使用して、構文の強調表示などの基本的な機能を提供したり、Visual Studio 機能拡張 Api の完全なセットを使用するカスタム言語サービスを作成したりすることによって追加できます。豊富なデータ。Traditionally, language services in Visual Studio can be added by using TextMate grammar files to provide basic functionalities such as syntax highlighting or by writing custom language services that use the full set of Visual Studio extensibility APIs to provide richer data. Visual Studio で LSP をサポートしている場合は、3つ目のオプションがあります。With Visual Studio support for LSP, there's a third option.

Visual Studio の言語サーバープロトコルサービス

言語サーバー プロトコルLanguage Server Protocol

言語サーバープロトコルの実装

この記事では、LSP ベースの言語サーバーを使用する Visual Studio 拡張機能を作成する方法について説明します。This article describes how to create a Visual Studio extension that uses an LSP-based language server. LSP ベースの言語サーバーを既に開発しており、それを Visual Studio に統合するだけであることを前提としています。It assumes that you've already developed an LSP-based language server and just want to integrate it into Visual Studio.

Visual Studio 内でのサポートのために、言語サーバーは、次のようにストリームベースの転送機構を使用してクライアント (Visual Studio) と通信できます。For support within Visual Studio, language servers can communicate with the client (Visual Studio) via any stream-based transmission mechanism, for example:

  • 標準入力/出力ストリームStandard input/output streams
  • 名前付きパイプNamed pipes
  • ソケット (TCP のみ)Sockets (TCP only)

Visual Studio での LSP とそのサポートの目的は、Visual Studio 製品に含まれていない言語サービスをオンボードすることです。The intent of the LSP and support for it in Visual Studio is to onboard language services that are not part of Visual Studio product. これは、Visual Studio で既存の言語サービス ( C#など) を拡張するためのものではありません。It's not intended to extend existing language services (like C#) in Visual Studio. 既存の言語を拡張するには、言語サービスの拡張ガイド (たとえば"Roslyn" .NET Compiler Platform) を参照するか、「エディターと言語サービスの拡張」を参照してください。To extend existing languages, refer to the language service’s extensibility guide (for example, the "Roslyn" .NET Compiler Platform) or see Extend the editor and language services.

プロトコル自体の詳細については、こちらのドキュメントを参照してください。For more information on the protocol itself, see the documentation here.

サンプル言語サーバーを作成する方法、または既存の言語サーバーを Visual Studio Code に統合する方法の詳細については、こちらのドキュメントを参照してください。For more information on how to create a sample language server or how to integrate an existing language server into Visual Studio Code, see the documentation here.

言語サーバープロトコルでサポートされる機能Language Server Protocol supported features

次の表は、Visual Studio でサポートされている LSP 機能を示しています。The following tables shows which LSP features are supported in Visual Studio:

MessageMessage Visual Studio でのサポートがあるHas Support in Visual Studio
initialize yes
初期化済みinitialized yes
シャットダウンshutdown yes
終了exit yes
$/cancelRequest$/cancelRequest yes
window/showMessagewindow/showMessage yes
window/showMessageRequestwindow/showMessageRequest yes
window/logMessagewindow/logMessage yes
テレメトリ/イベントtelemetry/event
client/registerCapabilityclient/registerCapability
client/unregisterCapabilityclient/unregisterCapability
workspace/didChangeConfigurationworkspace/didChangeConfiguration yes
workspace/didChangeWatchedFilesworkspace/didChangeWatchedFiles yes
ワークスペース/シンボルworkspace/symbol yes
workspace/executeCommandworkspace/executeCommand yes
workspace/applyEditworkspace/applyEdit yes
textDocument/publishDiagnosticstextDocument/publishDiagnostics yes
textDocument/didOpentextDocument/didOpen yes
textDocument/didChangetextDocument/didChange yes
textDocument/willSavetextDocument/willSave
textDocument/willSaveWaitUntiltextDocument/willSaveWaitUntil
textDocument/didSavetextDocument/didSave yes
textDocument/didClosetextDocument/didClose yes
textDocument/補完機能textDocument/completion yes
完了/解決completion/resolve yes
textDocument/hovertextDocument/hover yes
textDocument/signatureHelptextDocument/signatureHelp yes
textDocument/referencestextDocument/references yes
textDocument/documentHighlighttextDocument/documentHighlight yes
textDocument/documentSymboltextDocument/documentSymbol yes
textDocument/書式設定textDocument/formatting yes
textDocument/rangeFormattingtextDocument/rangeFormatting yes
textDocument/onTypeFormatting 設定textDocument/onTypeFormatting
textDocument/definitiontextDocument/definition yes
textDocument/codeActiontextDocument/codeAction yes
textDocument/codeLenstextDocument/codeLens
codeLens/resolvecodeLens/resolve
textDocument/documentLinktextDocument/documentLink
documentLink/resolvedocumentLink/resolve
textDocument/renametextDocument/rename yes

作業開始Get started

Note

Visual Studio 2017 バージョン15.8 以降では、共通言語サーバープロトコルのサポートが Visual Studio に組み込まれています。Starting with Visual Studio 2017 version 15.8, support for the common Language Server Protocol is built into Visual Studio. プレビュー言語サーバークライアントの VSIXバージョンを使用して LSP 拡張機能をビルドした場合、バージョン15.8 以降にアップグレードすると、その拡張機能が動作しなくなります。If you've built LSP extensions using the preview Language Server Client VSIX version, they will stop working once you upgrade to version 15.8 or higher. LSP 拡張機能を再び動作させるには、次の手順を実行する必要があります。You will need to do the following to get your LSP extensions working again:

  1. Microsoft Visual Studio Language Server Protocol Preview VSIX をアンインストールします。Uninstall the Microsoft Visual Studio Language Server Protocol Preview VSIX.

    バージョン15.8 以降では、Visual Studio でアップグレードを実行するたびに、プレビュー VSIX が自動的に検出され、削除されます。Starting with version 15.8, each time you perform an upgrade in Visual Studio the preview VSIX is automatically detected and removed.

  2. Nuget の参照を、 LSP パッケージのプレビュー版以外の最新バージョンに更新します。Update your Nuget reference to the latest non-preview version for LSP packages.

  3. VSIX マニフェストの Microsoft Visual Studio Language Server Protocol Preview VSIX への依存関係を削除します。Remove the dependency to the Microsoft Visual Studio Language Server Protocol Preview VSIX in your VSIX manifest.

  4. VSIX で、インストールターゲットの下限として Visual Studio 2017 バージョン 15.8 Preview 3 が指定されていることを確認します。Make sure your VSIX specifies Visual Studio 2017 version 15.8 Preview 3 as the lower bound for install target.

  5. リビルドと再デプロイ。Rebuild and redeploy.

VSIX プロジェクトを作成するCreate a VSIX project

LSP ベースの言語サーバーを使用して言語サービス拡張機能を作成するには、まず、VS のインスタンス用にVisual Studio 拡張機能の開発ワークロードがインストールされていることを確認します。To create a language service extension using an LSP-based language server, first make sure you have the Visual Studio extension development Workload installed for your instance of VS.

次に、[ファイル > ] [新しいプロジェクト > > ] [ビジュアルC# 機能拡張 > ] [vsix プロジェクト] の順に移動して、新しい VSIX プロジェクトを作成します。Next, create a new VSIX project by navigating to File > New Project > Visual C# > Extensibility > VSIX Project:

vsix プロジェクトの作成

言語サーバーとランタイムのインストールLanguage server and runtime installation

既定では、Visual Studio で LSP ベースの言語サーバーをサポートするために作成される拡張機能には、言語サーバー自体や、それらを実行するために必要なランタイムは含まれていません。By default, the extensions created to support LSP-based language servers in Visual Studio don't contain the language servers themselves or the runtimes needed to execute them. 拡張機能の開発者は、必要な言語サーバーとランタイムの配布を担当します。Extension developers are responsible for distributing the language servers and the runtimes needed. これを行うには、いくつかの方法があります。There are several ways to do so:

  • 言語サーバーは、VSIX にコンテンツファイルとして埋め込むことができます。Language servers can be embedded in the VSIX as content files.
  • 言語サーバーや必要なランタイムをインストールするための MSI を作成します。Create an MSI to install the language server and/or needed runtimes.
  • ランタイムと言語サーバーを取得する方法をユーザーに通知する、Marketplace の手順を提供します。Provide instructions on Marketplace informing users how to obtain runtimes and language servers.

TextMate 文法ファイルTextMate grammar files

LSP には、言語のテキストの色付け方法に関する仕様は含まれていません。The LSP does not include specification on how to provide text colorization for languages. 拡張機能の開発者は、Visual Studio の言語に対してカスタムの色付けを提供するために、TextMate 文法ファイルを使用できます。To provide custom colorization for languages in Visual Studio, extension developers can use a TextMate grammar file. カスタムの TextMate 文法またはテーマファイルを追加するには、次の手順を実行します。To add custom TextMate grammar or theme files, follow these steps:

  1. 拡張機能内に "文法" という名前のフォルダーを作成します (または、任意の名前を選択します)。Create a folder named "Grammars" inside your extension (or it can be whatever name you choose).

  2. 文法フォルダー内に、カスタムの色付けを提供する、任意 *の tmlanguage*plist*tmlanguage、または *jsonファイルを含めます。Inside the Grammars folder, include any *.tmlanguage, *.plist, *.tmtheme, or *.json files you’d like that provide custom colorization.

    Tip

    Tmthemeファイルは、スコープが Visual Studio 分類 (名前付きの色キー) にどのようにマップされるかを定義します。A .tmtheme file defines how the scopes map to Visual Studio classifications (named color keys). ガイダンスについては、 % ProgramFiles (x86)% \ Microsoft Visual Studio\<バージョン >\<SKU > \Common7\IDE\CommonExtensions\Microsoft\ で、グローバルな tmtheme ファイルを参照できます。TextMate\Starterkit\Themesgディレクトリ。For guidance, you can reference the global .tmtheme file in the %ProgramFiles(x86)%\Microsoft Visual Studio\<version>\<SKU>\Common7\IDE\CommonExtensions\Microsoft\TextMate\Starterkit\Themesg directory.

  3. Pkgdefファイルを作成し、次のような行を追加します。Create a .pkgdef file and add a line similar to this:

    [$RootKey$\TextMate\Repositories]
    "MyLang"="$PackageFolder$\Grammars"
    
  4. ファイルを右クリックし、[プロパティ] を選択します。Right-click on the files and select Properties. [ビルド] アクションを [コンテンツ] に変更し、[ VSIX に含める] プロパティを [ true] に変更します。Change the Build action to Content and change the Include in VSIX property to true.

前の手順を完了すると、' MyLang ' という名前のリポジトリソースとして文法フォルダーがパッケージのインストールディレクトリに追加されます (' mylang ' はあいまいさを解消するための名前であり、任意の一意の文字列にすることができます)。After completing the previous steps, a Grammars folder is added to the package’s install directory as a repository source named 'MyLang' ('MyLang' is just a name for disambiguation and can be any unique string). このディレクトリ内のすべての文法 (tmlanguageファイル) とテーマファイル (tmlanguageファイル) は、チャンスとして取得され、textmate で提供される組み込みの文法を置き換えます。All of the grammars (.tmlanguage files) and theme files (.tmtheme files) in this directory are picked up as potentials and they supersede the built-in grammars provided with TextMate. 文法ファイルの宣言された拡張子が、開いているファイルの拡張子と一致する場合、TextMate がステップインします。If the grammar file's declared extensions match the extension of the file being opened, TextMate will step in.

単純な言語クライアントを作成するCreate a simple language client

Main インターフェイス- ILanguageClientMain interface - ILanguageClient

VSIX プロジェクトを作成したら、次の NuGet パッケージをプロジェクトに追加します。After creating your VSIX project, add the following NuGet package(s) to your project:

Note

前の手順を完了した後に NuGet パッケージに対する依存関係を取得すると、Newtonsoft. Json および StreamJsonRpc パッケージもプロジェクトに追加されます。When you take a dependency on the NuGet package after you complete the previous steps, the Newtonsoft.Json and StreamJsonRpc packages are added to your project as well. 拡張機能が対象とする Visual Studio のバージョンに新しいバージョンがインストールされることが確実である場合を除き、これらのパッケージは更新しないでください。Do not update these packages unless you are certain that those new versions will be installed on the version of Visual Studio that your extension targets. アセンブリは VSIX に含まれません。代わりに、Visual Studio のインストールディレクトリから選択されます。The assemblies will not be included in your VSIX; instead, they will be picked up from the Visual Studio installation directory. ユーザーのコンピューターにインストールされているものより新しいバージョンのアセンブリを参照している場合、拡張機能は機能しません。If you are referencing a newer version of the assemblies than what is installed on a user's machine, your extension will not work.

次に、 ILanguageClientインターフェイスを実装する新しいクラスを作成できます。これは、LSP ベースの言語サーバーに接続する言語クライアントに必要な主要なインターフェイスです。You can then create a new class that implements the ILanguageClient interface, which is the main interface needed for language clients connecting to an LSP-based language server.

次に例を示します。The following is a sample:

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

実装する必要のある主なメソッドは、 Onロード asyncアクティブ非同期です。The main methods that need to be implemented are OnLoadedAsync and ActivateAsync. Onloaded asyncは、Visual Studio によって拡張機能が読み込まれ、言語サーバーを開始する準備ができたときに呼び出されます。OnLoadedAsync is called when Visual Studio has loaded your extension and your language server is ready to be started. このメソッドでは、StartAsync をすぐに呼び出して、言語サーバーを開始する必要があることを通知することも、追加のロジックを実行して後で StartAsync を起動することもできます。In this method, you can invoke the StartAsync delegate immediately to signal that the language server should be started, or you can do additional logic and invoke StartAsync later. 言語サーバーをアクティブ化するには、ある時点で StartAsync 呼び出す必要があります。To activate your language server, you must call StartAsync at some point.

"アクティブな非同期" は、StartAsync デリゲートを呼び出すことによって、最終的に呼び出されるメソッドです。ActivateAsync is the method eventually invoked by calling the StartAsync delegate. 言語サーバーを起動して接続を確立するロジックが含まれています。It contains the logic to start the language server and establish connection to it. サーバーへの書き込みとサーバーからの読み取りのためのストリームを含む接続オブジェクトを返す必要があります。A connection object that contains streams for writing to the server and reading from the server must be returned. ここでスローされた例外は、Visual Studio の情報バーメッセージを使用してキャッチされ、ユーザーに表示されます。Any exceptions thrown here are caught and displayed to user via an InfoBar message in Visual Studio.

アクティベーションActivation

言語クライアントクラスが実装されたら、それに対して2つの属性を定義して、Visual Studio への読み込み方法とアクティブ化方法を定義する必要があります。Once your language client class is implemented, you'll need to define two attributes for it to define how it will be loaded into Visual Studio and activated:

  [Export(typeof(ILanguageClient))]
  [ContentType("bar")]

MEFMEF

Visual Studio はMEF (Managed Extensibility Framework) を使用して、その機能拡張ポイントを管理します。Visual Studio uses MEF (Managed Extensibility Framework) to manage its extensibility points. Export属性は、このクラスが拡張ポイントとして取得され、適切なタイミングで読み込まれる必要があることを Visual Studio に示します。The Export attribute indicates to Visual Studio that this class should be picked up as an extension point and loaded at the appropriate time.

MEF を使用するには、VSIX マニフェストで、MEF を資産として定義する必要もあります。To use MEF, you must also define MEF as an Asset in the VSIX manifest.

VSIX マニフェストデザイナーを開き、[アセット] タブに移動します。Open up your VSIX manifest designer and navigate to the Assets tab:

MEF アセットの追加

新しい資産を作成するには、[新規] をクリックします。Click New to create a new asset:

MEF 資産の定義

  • 種類:Microsoft.VisualStudio.MefComponentType: Microsoft.VisualStudio.MefComponent
  • ソース:現在のソリューション内のプロジェクトSource: A project in the current solution
  • プロジェクト: [プロジェクト]Project: [Your project]

コンテンツタイプの定義Content type definition

現在、LSP ベースの言語サーバー拡張機能を読み込む唯一の方法は、ファイルのコンテンツタイプです。Currently, the only way to load your LSP-based language server extension is by file content type. つまり、言語クライアントクラス ( ILanguageClientを実装) を定義する場合は、ファイルの種類を定義する必要があります。このクラスを開くと、拡張機能が読み込まれます。That is, when defining your language client class (which implements ILanguageClient), you will need to define the types of files that, when opened, will cause your extension to load. 定義されているコンテンツの種類に一致するファイルが開かれていない場合、拡張機能は読み込まれません。If no files that match your defined content type are opened, then your extension will not be loaded.

これを行うには、1つContentTypeDefinitionまたは複数のクラスを定義します。This is done through defining one or more ContentTypeDefinition classes:

namespace MockLanguageExtension
{
    public class BarContentDefinition
    {
        [Export]
        [Name("bar")]
        [BaseDefinition(CodeRemoteContentDefinition.CodeRemoteContentTypeName)]
        internal static ContentTypeDefinition BarContentTypeDefinition;

        [Export]
        [FileExtension(".bar")]
        [ContentType("bar")]
        internal static FileExtensionToContentTypeDefinition BarFileExtensionDefinition;
    }
}

前の例では、 . barファイル拡張子で終わるファイルに対して、コンテンツの種類の定義が作成されています。In the previous example, a content type definition is created for files that end in .bar file extension. コンテンツの種類の定義には "bar" という名前が付けられ、 CodeRemoteContentTypeNameから派生する必要があります。The content type definition is given the name "bar" and must derive from CodeRemoteContentTypeName.

コンテンツタイプの定義を追加した後、言語クライアントの拡張機能をどのような場合に言語クライアントクラスに読み込むかを定義できます。After adding a content type definition, you can then define when to load your language client extension in the language client class:

    [ContentType("bar")]
    [Export(typeof(ILanguageClient))]
    public class BarLanguageClient : ILanguageClient
    {
    }

LSP 言語サーバーのサポートを追加する場合、Visual Studio で独自のプロジェクトシステムを実装する必要はありません。Adding support for LSP language servers does not require you to implement your own project system in Visual Studio. お客様は、Visual Studio で1つのファイルまたはフォルダーを開いて、言語サービスの使用を開始できます。Customers can open a single file or a folder in Visual Studio to start using your language service. 実際、LSP 言語サーバーのサポートは、開いているフォルダーやファイルのシナリオでのみ機能するように設計されています。In fact, support for LSP language servers is designed to work only in open folder/file scenarios. カスタムプロジェクトシステムが実装されている場合、一部の機能 (設定など) は機能しません。If a custom project system is implemented, some features (such as settings) will not work.

高度な機能Advanced features

設定Settings

カスタム言語サーバー固有の設定はサポートされていますが、引き続き改善されています。Support for custom language-server-specific settings is available, but it is still in the process of being improved. 設定は言語サーバーがサポートする内容に固有であり、通常は言語サーバーがデータを出力する方法を制御します。Settings are specific to what the language server supports and usually control how the language server emits data. たとえば、言語サーバーには、報告されるエラーの最大数の設定が含まれている場合があります。For example, a language server might have a setting for the maximum number of errors reported. 拡張機能の作成者は、特定のプロジェクトのユーザーが変更できる既定値を定義します。Extension authors would define a default value, which can be changed by users for specific projects.

次の手順に従って、LSP 言語サービス拡張機能に設定のサポートを追加します。Follow these steps below to add support for settings to your LSP language service extension:

  1. 設定とその既定値を含む JSON ファイル (たとえば、 MockLanguageExtensionSettings) をプロジェクトに追加します。Add a JSON file (for example, MockLanguageExtensionSettings.json) to your project that contains the settings and their default values. 例えば:For example:

    {
        "foo.maxNumberOfProblems": -1
    }
    
  2. JSON ファイルを右クリックし、[プロパティ] を選択します。Right-click on the JSON file and select Properties. ビルドアクションを "Content" に、"VSIX に含める" プロパティをtrueに変更します。Change the Build action to "Content" and the "Include in VSIX' property to true.

  3. ConfigurationSections を実装し、JSON ファイルで定義されている設定のプレフィックスの一覧を返します (Visual Studio Code では、これは、パッケージの構成セクション名にマップされます)。Implement ConfigurationSections and return the list of prefixes for the settings defined in the JSON file (In Visual Studio Code, this would map to the configuration section name in package.json):

    public IEnumerable<string> ConfigurationSections
    {
        get
        {
            yield return "foo";
        }
    }
    
  4. Pkgdef ファイルをプロジェクトに追加し (新しいテキストファイルを追加し、ファイル拡張子を pkgdef に変更します)。Add a .pkgdef file to the project (add new text file and change the file extension to .pkgdef). .Pkgdef ファイルには、次の情報が含まれている必要があります。The pkgdef file should contain this info:

    [$RootKey$\OpenFolder\Settings\VSWorkspaceSettings\[settings-name]]
    @="$PackageFolder$\[settings-file-name].json"
    

    サンプル:Sample:

    [$RootKey$\OpenFolder\Settings\VSWorkspaceSettings\MockLanguageExtension]
    @="$PackageFolder$\MockLanguageExtensionSettings.json"
    
  5. Pkgdef ファイルを右クリックし、[プロパティ] を選択します。Right click on the .pkgdef file and select Properties. [ビルドアクション] を [コンテンツ] に、[ VSIX に含める] プロパティを [ true] に変更します。Change the Build action to Content and the Include in VSIX property to true.

  6. Source.extension.vsixmanifestファイルを開き、[資産] タブに資産を追加します。Open up the source.extension.vsixmanifest file and add an asset in the Asset tab:

    vspackage asset の編集

    • 種類:VisualStudio. VsPackageType: Microsoft.VisualStudio.VsPackage
    • ソース:ファイルシステム上のファイルSource: File on filesystem
    • パス: [ Pkgdefファイルのパス]Path: [Path to your .pkgdef file]

ワークスペースの設定をユーザーが編集するUser editing of settings for a workspace

  1. ユーザーは、サーバーが所有しているファイルが含まれているワークスペースを開きます。User opens a workspace containing files your server owns.

  2. ユーザーは、 vsworkspacesettings.jsonという名前のvsフォルダーにファイルを追加します。User adds a file in the .vs folder called VSWorkspaceSettings.json.

  3. ユーザーは、サーバーが提供する設定のvsworkspacesettings.jsonファイルに行を追加します。User adds a line to the VSWorkspaceSettings.json file for a setting the server provides. 例えば:For example:

    {
        "foo.maxNumberOfProblems": 10
    }
    

診断トレースを有効にするEnable diagnostics tracing

診断トレースを有効にすると、クライアントとサーバー間のすべてのメッセージを出力できます。これは、問題をデバッグするときに役立ちます。Diagnostics tracing can be enabled to output all messages between the client and server, which can be useful when debugging issues. 診断トレースを有効にするには、次の手順を実行します。To enable diagnostic tracing, do the following:

  1. ワークスペース設定ファイルvsworkspacesettings.jsonを開くか作成します (「ワークスペースの設定をユーザーが編集する」を参照してください)。Open or create the workspace settings file VSWorkspaceSettings.json (see "User editing of settings for a workspace").
  2. 設定の json ファイルに次の行を追加します。Add the following line in the settings json file:
{
    "foo.trace.server": "Off"
}

トレースの詳細には、次の3つの値を指定できます。There are three possible values for trace verbosity:

  • オフ: トレースは完全にオフ"Off": tracing turned off completely
  • "Messages": トレースが有効になっていますが、メソッド名と応答 ID のみがトレースされています。"Messages": tracing turned on but only method name and response ID are traced.
  • "Verbose": トレースが有効になります。rpc メッセージ全体がトレースされます。"Verbose": tracing turned on; the entire rpc message is traced.

トレースが有効になっている場合、コンテンツは %temp%\VisualStudio\LSPディレクトリ内のファイルに書き込まれます。When tracing is turned on the content is written to a file in the %temp%\VisualStudio\LSP directory. このログは、 [LanguageClientName]-[Datetime スタンプ] .logという名前の形式に従います。The log follows the naming format [LanguageClientName]-[Datetime Stamp].log. 現時点では、トレースは、開いているフォルダーのシナリオに対してのみ有効にすることができます。Currently, tracing can only be enabled for open folder scenarios. 1つのファイルを開いて言語サーバーをアクティブ化する場合、診断トレースはサポートされません。Opening a single file to activate a language server does not have diagnostics tracing support.

カスタムメッセージCustom messages

標準言語サーバープロトコルに含まれていない言語サーバーとのメッセージの送受信を容易にする Api が用意されています。There are APIs in place to facilitate passing messages to and receiving messages from the language server that are not part of the standard Language Server Protocol. カスタムメッセージを処理するには、言語クライアントクラスでILanguageClientCustomMessageインターフェイスを実装します。To handle custom messages, implement ILanguageClientCustomMessage interface in your language client class. VS-StreamJsonRpcライブラリは、言語クライアントと言語サーバーの間でカスタムメッセージを転送するために使用されます。VS-StreamJsonRpc library is used to transmit custom messages between your language client and language server. LSP 言語のクライアント拡張機能は他の Visual Studio 拡張機能と同じであるため、拡張機能のカスタムメッセージを使用して、(他の Visual Studio Api を使用して) Visual Studio に追加機能を追加することもできます。Since your LSP language client extension is just like any other Visual Studio extension, you can decide to add additional features (that are not supported by the LSP) to Visual Studio (using other Visual Studio APIs) in your extension through custom messages.

カスタムメッセージを受信するReceive custom messages

言語サーバーからカスタムメッセージを受信するには、 ILanguageClientCustomMessagecustommessagetargetプロパティを実装し、カスタムメッセージの処理方法を認識するオブジェクトを返します。To receive custom messages from the language server, implement the CustomMessageTarget property on ILanguageClientCustomMessage and return an object that knows how to handle your custom messages. 次に例を示します。Example below:

internal class MockCustomLanguageClient : MockLanguageClient, ILanguageClientCustomMessage
{
    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
        }
    }
}

カスタムメッセージを送信するSend custom messages

言語サーバーにカスタムメッセージを送信するには、 ILanguageClientCustomMessageAttachForCustomMessageAsyncメソッドを実装します。To send custom messages to the language server, implement the AttachForCustomMessageAsync method on ILanguageClientCustomMessage. このメソッドは、言語サーバーが開始され、メッセージを受信する準備ができたときに呼び出されます。This method is invoked when your language server is started and ready to receive messages. Jsonrpcオブジェクトはパラメーターとして渡されます。これにより、 VS streamjsonrpc api を使用して、メッセージを言語サーバーに送信することができます。A JsonRpc object is passed as a parameter, which you can then keep to send messages to the language server using VS-StreamJsonRpc APIs. 次に例を示します。Example below:

internal class MockCustomLanguageClient : MockLanguageClient, ILanguageClientCustomMessage
{
    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);
    }
}

中間層Middle layer

拡張機能の開発者が、言語サーバーとの間で送受信された LSP メッセージを傍受する場合があります。Sometimes an extension developer may want to intercept LSP messages sent to and received from the language server. たとえば、拡張機能の開発者は、特定の LSP メッセージに送信されるメッセージパラメーターを変更したり、LSP 機能の言語サーバーから返された結果を変更したりすることができます (入力候補など)。For example, an extension developer may want to alter the message parameter sent for a particular LSP message, or modify the results returned from the language server for an LSP feature (for example completions). これが必要な場合、拡張機能の開発者は MiddleLayer API を使用して LSP メッセージをインターセプトできます。When this is necessary, extension developers can use the MiddleLayer API to intercept LSP messages.

各 LSP メッセージには、傍受のための独自の中間層インターフェイスがあります。Each LSP message has its own middle layer interface for interception. 特定のメッセージをインターセプトするには、そのメッセージの中間層インターフェイスを実装するクラスを作成します。To intercept a particular message, create a class that implements the middle layer interface for that message. 次に、言語クライアントクラスにILanguageClientCustomMessageインターフェイスを実装し、 MiddleLayerプロパティにオブジェクトのインスタンスを返します。Then, implement the ILanguageClientCustomMessage interface in your language client class and return an instance of your object in the MiddleLayer property. 次に例を示します。Example below:

public class MockLanguageClient: ILanguageClient, ILanguageClientCustomMessage
{
    public object MiddleLayer => MiddleLayerProvider.Instance;

    private class MiddleLayerProvider : ILanguageClientWorkspaceSymbolProvider
    {
        internal readonly static MiddleLayerProvider Instance = new MiddleLayerProvider();

        private MiddleLayerProvider()
        {
        }

        public async Task<SymbolInformation[]> RequestWorkspaceSymbols(WorkspaceSymbolParams param, Func<WorkspaceSymbolParams, Task<SymbolInformation[]>> sendRequest)
        {
            // Send along the request as given
            SymbolInformation[] symbols = await sendRequest(param);

            // Only return symbols that are "files"
            return symbols.Where(sym => string.Equals(new Uri(sym.Location.Uri).Scheme, "file", StringComparison.OrdinalIgnoreCase)).ToArray();
        }
    }
}

中間層機能はまだ開発中であり、まだ包括的ではありません。The middle layer feature is still under development and not yet comprehensive.

サンプル LSP 言語サーバー拡張機能Sample LSP language server extension

Visual Studio で LSP クライアント API を使用してサンプル拡張機能のソースコードを表示するには、「VSSDK-拡張性-サンプルLSP サンプル」を参照してください。To see the source code of a sample extension using the LSP client API in Visual Studio, see VSSDK-Extensibility-Samples LSP sample.

FAQFAQ

Visual Studio の豊富な機能がサポートする LSP 言語サーバーを補足するカスタム プロジェクト システムを構築したいのですが、どうしたらよいでしょうか。I would like to build a custom project system to supplement my LSP language server to provide richer feature support in Visual Studio, how do I go about doing that?

Visual Studio での LSP ベースの言語サーバーのサポートは、フォルダーを開く機能に依存しており、カスタムプロジェクトシステムを必要としないように設計されています。Support for LSP-based language servers in Visual Studio relies on the open folder feature and is designed to not require a custom project system. ここで説明する手順に従って独自のカスタムプロジェクトシステムを構築できますが、設定などの一部の機能が動作しない場合があります。You can build your own custom project system following instructions here, but some features, such as settings, may not work. LSP 言語サーバーの既定の初期化ロジックは、現在開かれているフォルダーのルートフォルダーの場所を渡すことです。したがって、カスタムプロジェクトシステムを使用する場合は、初期化時にカスタムロジックを提供して、言語サーバーが正常に起動します。The default initialization logic for LSP language servers is to pass in the root folder location of the folder currently being opened, so if you use a custom project system, you may need to provide custom logic during initialization to ensure your language server can start properly.

デバッガーサポートを追加操作方法にはHow do I add debugger support?

共通デバッグプロトコルのサポートは、今後のリリースで提供される予定です。We will be providing support for the common debugging protocol in a future release.

VS でサポートされている言語サービス (たとえば、JavaScript など) が既にインストールされている場合、LSP 言語サーバー拡張機能のインストール (lint 処理) などをインストールすることはできますか?If there is already a VS supported language service installed (for example, JavaScript), can I still install an LSP language server extension that offers additional features (such as linting)?

はい、できますが、すべての機能が正しく動作するわけではありません。Yes, but not all features will work properly. LSP 言語サーバー拡張機能の最終的な目標は、Visual Studio でネイティブにサポートされていない言語サービスを有効にすることです。The ultimate goal for LSP language server extensions is to enable language services not natively supported by Visual Studio. LSP 言語サーバーを使用して追加のサポートを提供する拡張機能を作成することができますが、一部の機能 (IntelliSense) などはスムーズな体験にはなりません。You can create extensions that offer additional support using LSP language servers, but some features (such as IntelliSense) will not be a smooth experience. 一般に、LSP 言語サーバー拡張機能は、既存のものを拡張するのではなく、新しい言語のエクスペリエンスを提供するために使用することをお勧めします。In general, it is advised that LSP language server extensions be used for providing new language experiences, not extending existing ones.

完成した LSP 言語サーバー VSIX を発行するにはどうすればよいですか。Where do I publish my completed LSP language server VSIX?

Marketplace の手順については、こちらを参照してください。See the Marketplace instructions here.

関連項目See also