VS Code でを試す!

プログラムによる言語機能

プログラムによる言語機能は、vscode.languages.* API を利用した一連のスマート編集機能です。Visual Studio Code で動的な言語機能を提供するには、主に2つの方法があります。例としてホバーを見てみましょう。

vscode.languages.registerHoverProvider('javascript', {
  provideHover(document, position, token) {
    return {
      contents: ['Hover Content']
    };
  }
});

上記のように、vscode.languages.registerHoverProvider API は、JavaScript ファイルにホバーコンテンツを提供する簡単な方法です。この拡張機能がアクティベートされると、JavaScript コードにホバーするたびに、VS Code は JavaScript 用のすべてのHoverProvider をクエリし、結果をホバーウィジェットに表示します。以下の言語機能リストと図示された GIF は、拡張機能に必要な VS Code API / LSP メソッドを見つける簡単な方法を提供します。

別の方法は、言語サーバープロトコルに対応した言語サーバーを実装することです。その仕組みは次のとおりです。

  • 拡張機能が JavaScript 用の言語クライアントと言語サーバーを提供します。
  • 言語クライアントは、他の VS Code 拡張機能と同様に、Node.js 拡張機能ホストコンテキストで実行されます。アクティベートされると、別のプロセスで言語サーバーを起動し、言語サーバープロトコルを通じてそれと通信します。
  • VS Code で JavaScript コードにホバーします
  • VS Code はホバーを言語クライアントに通知します
  • 言語クライアントは、ホバー結果を言語サーバーにクエリし、それを VS Code に送り返します
  • VS Code はホバー結果をホバーウィジェットに表示します

このプロセスはより複雑に見えますが、2つの大きな利点があります。

  • 言語サーバーは任意の言語で記述できます
  • 言語サーバーは、複数のエディターにスマート編集機能を提供するために再利用できます

より詳細なガイドについては、言語サーバー拡張機能ガイドを参照してください。


言語機能リスト

このリストには、各言語機能について次の項目が含まれています。

  • VS Code での言語機能の図
  • 関連する VS Code API
  • 関連する LSP メソッド
VS Code API LSP メソッド
createDiagnosticCollection PublishDiagnostics
registerCompletionItemProvider 補完 & 補完解決
registerHoverProvider ホバー
registerSignatureHelpProvider シグネチャヘルプ
registerDefinitionProvider 定義
registerTypeDefinitionProvider 型定義
registerImplementationProvider 実装
registerReferenceProvider 参照
registerDocumentHighlightProvider ドキュメントハイライト
registerDocumentSymbolProvider ドキュメントシンボル
registerCodeActionsProvider コードアクション
registerCodeLensProvider CodeLens & CodeLens解決
registerDocumentLinkProvider ドキュメントリンク & ドキュメントリンク解決
registerColorProvider ドキュメントカラー & カラープレゼンテーション
registerDocumentFormattingEditProvider フォーマット
registerDocumentRangeFormattingEditProvider 範囲フォーマット
registerOnTypeFormattingEditProvider 入力時フォーマット
registerRenameProvider 名前変更 & 名前変更の準備
registerFoldingRangeProvider 折りたたみ範囲

診断機能の提供

診断機能は、コードの問題を示す方法です。

Diagnostics indicating a misspelled method name

言語サーバープロトコル

言語サーバーは、textDocument/publishDiagnostics メッセージを言語クライアントに送信します。このメッセージには、リソース URI の診断項目配列が含まれています。

: クライアントはサーバーに診断を要求しません。サーバーが診断情報をクライアントにプッシュします。

直接実装

let diagnosticCollection: vscode.DiagnosticCollection;

export function activate(ctx: vscode.ExtensionContext): void {
  ...
  ctx.subscriptions.push(getDisposable());
  diagnosticCollection = vscode.languages.createDiagnosticCollection('go');
  ctx.subscriptions.push(diagnosticCollection);
  ...
}

function onChange() {
  let uri = document.uri;
  check(uri.fsPath, goConfig).then(errors => {
    diagnosticCollection.clear();
    let diagnosticMap: Map<string, vscode.Diagnostic[]> = new Map();
    errors.forEach(error => {
      let canonicalFile = vscode.Uri.file(error.file).toString();
      let range = new vscode.Range(error.line-1, error.startColumn, error.line-1, error.endColumn);
      let diagnostics = diagnosticMap.get(canonicalFile);
      if (!diagnostics) { diagnostics = []; }
      diagnostics.push(new vscode.Diagnostic(range, error.msg, error.severity));
      diagnosticMap.set(canonicalFile, diagnostics);
    });
    diagnosticMap.forEach((diags, file) => {
      diagnosticCollection.set(vscode.Uri.parse(file), diags);
    });
  })
}

基本

開いているエディターの診断を報告します。最低限、これはすべての保存時に行う必要があります。より良いのは、エディターの未保存の内容に基づいて診断が計算されることです。

高度

開いているエディターだけでなく、開いているフォルダー内のすべてのリソースについて診断を報告します。それらがエディターで開かれたことがあるかどうかは関係ありません。

コード補完候補の表示

コード補完は、ユーザーにコンテキストに応じた提案を提供します。

Code Completion prompting variable, method, and parameter names while writing code

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーは補完機能を提供すること、および計算された補完項目に追加情報を提供するために completionItem\resolve メソッドをサポートするかどうかを通知する必要があります。

{
    ...
    "capabilities" : {
        "completionProvider" : {
            "resolveProvider": "true",
            "triggerCharacters": [ '.' ]
        }
        ...
    }
}

直接実装

class GoCompletionItemProvider implements vscode.CompletionItemProvider {
    public provideCompletionItems(
        document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken):
        Thenable<vscode.CompletionItem[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(getDisposable());
    ctx.subscriptions.push(
        vscode.languages.registerCompletionItemProvider(
            GO_MODE, new GoCompletionItemProvider(), '.', '\"'));
    ...
}

基本

解決プロバイダーはサポートしていません。

高度

ユーザーが選択した補完候補の追加情報を計算する解決プロバイダーをサポートしています。この情報は選択された項目の横に表示されます。

ホバーの表示

ホバーは、マウスカーソルの下にあるシンボル/オブジェクトに関する情報を表示します。これは通常、シンボルの型と説明です。

Showing details about a workspace and a method when hovering over them

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーはホバー機能を提供することを通知する必要があります。

{
    ...
    "capabilities" : {
        "hoverProvider" : "true",
        ...
    }
}

さらに、言語サーバーは textDocument/hover リクエストに応答する必要があります。

直接実装

class GoHoverProvider implements HoverProvider {
    public provideHover(
        document: TextDocument, position: Position, token: CancellationToken):
        Thenable<Hover> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerHoverProvider(
            GO_MODE, new GoHoverProvider()));
    ...
}

基本

型情報を表示し、利用可能な場合はドキュメントを含めます。

高度

コードを色付けするのと同じスタイルでメソッドシグネチャを色付けします。

関数とメソッドのシグネチャのヘルプ

ユーザーが関数やメソッドを入力するときに、呼び出されている関数/メソッドに関する情報を表示します。

Showing information about the getPackageInfo method including the necessary parameters

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーはシグネチャヘルプ機能を提供することを通知する必要があります。

{
    ...
    "capabilities" : {
        "signatureHelpProvider" : {
            "triggerCharacters": [ '(' ]
        }
        ...
    }
}

さらに、言語サーバーは textDocument/signatureHelp リクエストに応答する必要があります。

直接実装

class GoSignatureHelpProvider implements SignatureHelpProvider {
    public provideSignatureHelp(
        document: TextDocument, position: Position, token: CancellationToken):
        Promise<SignatureHelp> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerSignatureHelpProvider(
            GO_MODE, new GoSignatureHelpProvider(), '(', ','));
    ...
}

基本

シグネチャヘルプが関数またはメソッドのパラメーターのドキュメントを含むことを確認します。

高度

追加機能なし。

シンボルの定義の表示

ユーザーが変数/関数/メソッドが使用されている場所で、その定義を直接確認できるようにします。

Right click a variable, function, or method and select "Go to Definition" to jump to the definition

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーは定義へのジャンプ機能を提供することを通知する必要があります。

{
    ...
    "capabilities" : {
        "definitionProvider" : "true"
        ...
    }
}

さらに、言語サーバーは textDocument/definition リクエストに応答する必要があります。

直接実装

class GoDefinitionProvider implements vscode.DefinitionProvider {
    public provideDefinition(
        document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken):
        Thenable<vscode.Location> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerDefinitionProvider(
            GO_MODE, new GoDefinitionProvider()));
    ...
}

基本

シンボルがあいまいな場合は、複数の定義を表示できます。

高度

追加機能なし。

シンボルへのすべての参照の検索

ユーザーが特定の変数/関数/メソッド/シンボルが使用されているすべてのソースコードの場所を確認できるようにします。

Right clicking and selecting "Find All References" to highlight all the locations where that symbol is used

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーはシンボル参照場所を提供することを通知する必要があります。

{
    ...
    "capabilities" : {
        "referencesProvider" : "true"
        ...
    }
}

さらに、言語サーバーは textDocument/references リクエストに応答する必要があります。

直接実装

class GoReferenceProvider implements vscode.ReferenceProvider {
    public provideReferences(
        document: vscode.TextDocument, position: vscode.Position,
        options: { includeDeclaration: boolean }, token: vscode.CancellationToken):
        Thenable<vscode.Location[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerReferenceProvider(
            GO_MODE, new GoReferenceProvider()));
    ...
}

基本

すべての参照の場所 (リソース URI と範囲) を返します。

高度

追加機能なし。

ドキュメント内のシンボルのすべての出現箇所をハイライト表示

ユーザーが開いているエディターでシンボルのすべての出現箇所を確認できるようにします。

Select a symbol to highlight all occurrences

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーはシンボルドキュメントの場所を提供することを通知する必要があります。

{
    ...
    "capabilities" : {
        "documentHighlightProvider" : "true"
        ...
    }
}

さらに、言語サーバーは textDocument/documentHighlight リクエストに応答する必要があります。

直接実装

class GoDocumentHighlightProvider implements vscode.DocumentHighlightProvider {
    public provideDocumentHighlights(
        document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken):
        vscode.DocumentHighlight[] | Thenable<vscode.DocumentHighlight[]>;
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerDocumentHighlightProvider(
            GO_MODE, new GoDocumentHighlightProvider()));
    ...
}

基本

参照が見つかるエディターのドキュメント内の範囲を返します。

高度

追加機能なし。

ドキュメント内のすべてのシンボル定義の表示

ユーザーが開いているエディターで任意のシンボル定義に素早く移動できるようにします。

Navigate to a symbol definition in the open editor using @

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーはシンボルドキュメントの場所を提供することを通知する必要があります。

{
    ...
    "capabilities" : {
        "documentSymbolProvider" : "true"
        ...
    }
}

さらに、言語サーバーは textDocument/documentSymbol リクエストに応答する必要があります。

直接実装

class GoDocumentSymbolProvider implements vscode.DocumentSymbolProvider {
    public provideDocumentSymbols(
        document: vscode.TextDocument, token: vscode.CancellationToken):
        Thenable<vscode.SymbolInformation[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerDocumentSymbolProvider(
            GO_MODE, new GoDocumentSymbolProvider()));
    ...
}

基本

ドキュメント内のすべてのシンボルを返します。変数、関数、クラス、メソッドなどのシンボルの種類を定義します。

高度

追加機能なし。

フォルダー内のすべてのシンボル定義の表示

ユーザーが VS Code で開いているフォルダー(ワークスペース)内の任意の場所でシンボル定義に素早く移動できるようにします。

Navigate to symbol definitions in the workspace using #

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーはグローバルシンボル場所を提供することを通知する必要があります。

{
    ...
    "capabilities" : {
        "workspaceSymbolProvider" : "true"
        ...
    }
}

さらに、言語サーバーは workspace/symbol リクエストに応答する必要があります。

直接実装

class GoWorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvider {
    public provideWorkspaceSymbols(
        query: string, token: vscode.CancellationToken):
        Thenable<vscode.SymbolInformation[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerWorkspaceSymbolProvider(
            new GoWorkspaceSymbolProvider()));
    ...
}

基本

開いているフォルダー内のソースコードによって定義されているすべてのシンボルを返します。変数、関数、クラス、メソッドなどのシンボルの種類を定義します。

高度

追加機能なし。

エラーまたは警告に対する可能なアクション

エラーや警告のすぐ横で、ユーザーに可能な修正アクションを提供します。アクションが利用可能な場合、電球アイコンがエラーまたは警告の横に表示されます。ユーザーが電球アイコンをクリックすると、利用可能なコードアクションのリストが表示されます。

Selecting a light bulb to view a list of available Code Actions

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーはコードアクション機能を提供することを通知する必要があります。

{
    ...
    "capabilities" : {
        "codeActionProvider" : "true"
        ...
    }
}

さらに、言語サーバーは textDocument/codeAction リクエストに応答する必要があります。

直接実装

class GoCodeActionProvider implements vscode.CodeActionProvider<vscode.CodeAction> {
    public provideCodeActions(
        document: vscode.TextDocument, range: vscode.Range | vscode.Selection,
        context: vscode.CodeActionContext, token: vscode.CancellationToken):
        Thenable<vscode.CodeAction[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerCodeActionsProvider(
            GO_MODE, new GoCodeActionProvider()));
    ...
}

基本

エラー/警告の修正アクションに対するコードアクションを提供します。

高度

さらに、リファクタリングなどのソースコード操作アクションも提供します。例えば、メソッドの抽出などです。

CodeLens - ソースコード内の操作可能なコンテキスト情報の表示

ソースコードに散りばめられた、操作可能なコンテキスト情報をユーザーに提供します。

CodeLens providing context

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーは CodeLens 結果を提供すること、および CodeLens をそのコマンドにバインドするための codeLens\resolve メソッドをサポートするかどうかを通知する必要があります。

{
    ...
    "capabilities" : {
        "codeLensProvider" : {
            "resolveProvider": "true"
        }
        ...
    }
}

さらに、言語サーバーは textDocument/codeLens リクエストに応答する必要があります。

直接実装

class GoCodeLensProvider implements vscode.CodeLensProvider {
    public provideCodeLenses(document: TextDocument, token: CancellationToken):
        CodeLens[] | Thenable<CodeLens[]> {
    ...
    }

    public resolveCodeLens?(codeLens: CodeLens, token: CancellationToken):
         CodeLens | Thenable<CodeLens> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerCodeLensProvider(
            GO_MODE, new GoCodeLensProvider()));
    ...
}

基本

ドキュメントで利用可能な CodeLens 結果を定義します。

高度

codeLens/resolve に応答することで、CodeLens 結果をコマンドにバインドします。

カラーデコレーターの表示

ユーザーがドキュメント内の色をプレビューおよび変更できるようにします。

Showing the color picker

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーは色情報を提供することを通知する必要があります。

{
    ...
    "capabilities" : {
        "colorProvider" : "true"
        ...
    }
}

さらに、言語サーバーは textDocument/documentColor および textDocument/colorPresentation リクエストに応答する必要があります。

直接実装

class GoColorProvider implements vscode.DocumentColorProvider {
    public provideDocumentColors(
        document: vscode.TextDocument, token: vscode.CancellationToken):
        Thenable<vscode.ColorInformation[]> {
    ...
    }
    public provideColorPresentations(
        color: Color, context: { document: TextDocument, range: Range }, token: vscode.CancellationToken):
        Thenable<vscode.ColorPresentation[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerColorProvider(
            GO_MODE, new GoColorProvider()));
    ...
}

基本

ドキュメント内のすべての色参照を返します。サポートされている色フォーマット(例: rgb(...), hsl(...))の色表示を提供します。

高度

追加機能なし。

エディターでのソースコードのフォーマット

ユーザーにドキュメント全体のフォーマットをサポートします。

Right click and select format code

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーはドキュメントフォーマット機能を提供することを通知する必要があります。

{
    ...
    "capabilities" : {
        "documentFormattingProvider" : "true"
        ...
    }
}

さらに、言語サーバーは textDocument/formatting リクエストに応答する必要があります。

直接実装

class GoDocumentFormatter implements vscode.DocumentFormattingEditProvider {
    provideDocumentFormattingEdits(
        document: vscode.TextDocument, options: vscode.FormattingOptions, token: vscode.CancellationToken)
        : vscode.ProviderResult<vscode.TextEdit[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerDocumentFormattingEditProvider(
            GO_MODE, new GoDocumentFormatter()));
    ...
}

基本

フォーマット機能は提供しません。

高度

ソースコードがフォーマットされる最小限のテキスト編集を常に返す必要があります。これは、診断結果などのマーカーが正しく調整され、失われないようにするために不可欠です。

エディターで選択した行のフォーマット

ユーザーにドキュメント内の選択された行の範囲のフォーマットをサポートします。

Select lines, right click, and select format code

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーは行範囲のフォーマットをサポートすることを通知する必要があります。

{
    ...
    "capabilities" : {
        "documentRangeFormattingProvider" : "true"
        ...
    }
}

さらに、言語サーバーは textDocument/rangeFormatting リクエストに応答する必要があります。

直接実装

class GoDocumentRangeFormatter implements vscode.DocumentRangeFormattingEditProvider{
    public provideDocumentRangeFormattingEdits(
        document: vscode.TextDocument, range: vscode.Range,
        options: vscode.FormattingOptions, token: vscode.CancellationToken):
        vscode.ProviderResult<vscode.TextEdit[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerDocumentRangeFormattingEditProvider(
            GO_MODE, new GoDocumentRangeFormatter()));
    ...
}

基本

フォーマット機能は提供しません。

高度

ソースコードがフォーマットされる最小限のテキスト編集を常に返す必要があります。これは、診断結果などのマーカーが正しく調整され、失われないようにするために不可欠です。

ユーザーが入力する際のコードの増分フォーマット

ユーザーが入力する際にテキストをフォーマットする機能をサポートします。

: ユーザーが入力する際にソースコードがフォーマットされるかどうかは、ユーザーの設定 editor.formatOnType によって制御されます。

Visual indicators for formatting as code is typed

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーはユーザーが入力する際にフォーマット機能を提供することを通知する必要があります。また、どの文字でフォーマットがトリガーされるべきかをクライアントに伝える必要があります。moreTriggerCharacters はオプションです。

{
    ...
    "capabilities" : {
        "documentOnTypeFormattingProvider" : {
            "firstTriggerCharacter": "}",
            "moreTriggerCharacter": [";", ","]
        }
        ...
    }
}

さらに、言語サーバーは textDocument/onTypeFormatting リクエストに応答する必要があります。

直接実装

class GoOnTypingFormatter implements vscode.OnTypeFormattingEditProvider{
    public provideOnTypeFormattingEdits(
        document: vscode.TextDocument, position: vscode.Position,
        ch: string, options: vscode.FormattingOptions, token: vscode.CancellationToken):
        vscode.ProviderResult<vscode.TextEdit[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerOnTypeFormattingEditProvider(
            GO_MODE, new GoOnTypingFormatter()));
    ...
}

基本

フォーマット機能は提供しません。

高度

ソースコードがフォーマットされる最小限のテキスト編集を常に返す必要があります。これは、診断結果などのマーカーが正しく調整され、失われないようにするために不可欠です。

シンボルの名前変更

ユーザーがシンボルの名前を変更し、そのシンボルへのすべての参照を更新できるようにします。

Rename a symbol and update all references to the new name

言語サーバープロトコル

initialize メソッドへの応答で、言語サーバーは名前変更機能を提供することを通知する必要があります。

{
    ...
    "capabilities" : {
        "renameProvider" : "true"
        ...
    }
}

さらに、言語サーバーは textDocument/rename リクエストに応答する必要があります。

直接実装

class GoRenameProvider implements vscode.RenameProvider {
    public provideRenameEdits(
        document: vscode.TextDocument, position: vscode.Position,
        newName: string, token: vscode.CancellationToken):
        Thenable<vscode.WorkspaceEdit> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerRenameProvider(
            GO_MODE, new GoRenameProvider()));
    ...
}

基本

名前変更機能は提供しません。

高度

実行する必要のあるすべてのワークスペース編集のリストを返します。例えば、シンボルへの参照を含むすべてのファイルにわたるすべての編集です。