プログラムによる言語機能
プログラムによる言語機能は、vscode.languages.*
API によって強化されたスマート編集機能のセットです。Visual Studio Code で動的な言語機能を提供するには、2 つの一般的な方法があります。例として Hover を見てみましょう。
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 メソッドを簡単に見つける方法を提供します。
別の方法として、Language Server Protocol を使用する Language Server を実装する方法があります。仕組みは次のとおりです。
- 拡張機能は、JavaScript 用の Language Client と Language Server を提供します。
- Language Client は、Node.js Extension Host コンテキストで実行される他の VS Code 拡張機能と同様です。アクティブ化されると、別のプロセスで Language Server を起動し、Language Server Protocol を介して通信します。
- VS Code で JavaScript コードの上にカーソルを合わせます
- VS Code は Language Client にホバーを通知します
- Language Client は Language Server にホバー結果をクエリし、VS Code に送り返します
- VS Code はホバーウィジェットにホバー結果を表示します
プロセスはより複雑に見えますが、2 つの大きな利点があります
- Language Server は任意の言語で記述できます
- Language Server は、複数のエディターにスマート編集機能を提供するために再利用できます
より詳細なガイドについては、Language Server 拡張機能ガイドを参照してください。
言語機能一覧
このリストには、各言語機能について次の項目が含まれています
- VS Code での言語機能の図
- 関連する VS Code API
- 関連する LSP メソッド
診断を提供する
診断は、コードの問題を示す方法です。
Language Server Protocol
言語サーバーは、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);
});
})
}
基本
開いているエディターの診断を報告します。最低限、これは保存のたびに発生する必要があります。より良いのは、診断がエディターの未保存のコンテンツに基づいて計算されるべきです。
高度
開いているエディターだけでなく、開いているフォルダー内のすべてのリソース(エディターで開かれたことがあるかどうかに関係なく)の診断を報告します。
コード補完候補を表示する
コード補完は、ユーザーにコンテキストに応じた提案を提供します。
Language Server Protocol
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(), '.', '\"'));
...
}
基本
リゾルブプロバイダーをサポートしていません。
高度
ユーザーが選択した補完候補の追加情報を計算するリゾルブプロバイダーをサポートしています。この情報は、選択された項目と一緒に表示されます。
ホバーを表示する
ホバーは、マウスカーソルの下にあるシンボル/オブジェクトに関する情報を表示します。これは通常、シンボルの型と説明です。
Language Server Protocol
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()));
...
}
基本
型情報を表示し、利用可能な場合はドキュメントを含めます。
高度
コードを色付けするのと同じスタイルでメソッドシグネチャを色付けします。
関数とメソッドのシグネチャに関するヘルプ
ユーザーが関数またはメソッドを入力すると、呼び出されている関数/メソッドに関する情報を表示します。
Language Server Protocol
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(), '(', ','));
...
}
基本
シグネチャヘルプに関数またはメソッドのパラメーターのドキュメントが含まれていることを確認してください。
高度
追加はありません。
シンボルの定義を表示する
ユーザーが変数/関数/メソッドが使用されている場所で変数/関数/メソッドの定義を確認できるようにします。
Language Server Protocol
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()));
...
}
基本
シンボルが曖昧な場合は、複数の定義を表示できます。
高度
追加はありません。
シンボルのすべての参照を検索する
ユーザーが特定の変数/関数/メソッド/シンボルが使用されているすべてのソースコードの場所を確認できるようにします。
Language Server Protocol
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 と範囲)を返します。
高度
追加はありません。
ドキュメント内のシンボルのすべての出現箇所を強調表示する
ユーザーが開いているエディターでシンボルのすべての出現箇所を確認できるようにします。
Language Server Protocol
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()));
...
}
基本
参照が見つかっているエディターのドキュメント内の範囲を返します。
高度
追加はありません。
ドキュメント内のすべてのシンボル定義を表示する
ユーザーが開いているエディター内の任意のシンボル定義にすばやく移動できるようにします。
Language Server Protocol
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 で開いているフォルダー (ワークスペース) 内の任意の場所にあるシンボル定義にすばやく移動できるようにします。
Language Server Protocol
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()));
...
}
基本
開いているフォルダー内のソースコードによって定義されたすべてのシンボルを返します。変数、関数、クラス、メソッドなどのシンボルの種類を定義します。
高度
追加はありません。
エラーまたは警告に対する可能なアクション
エラーまたは警告のすぐ隣に、可能な修正アクションをユーザーに提供します。アクションが利用可能な場合、エラーまたは警告の横に電球が表示されます。ユーザーが電球をクリックすると、利用可能なコードアクションのリストが表示されます。
Language Server Protocol
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 - ソースコード内のアクション可能なコンテキスト情報を表示する
ソースコードに点在して表示される、アクション可能なコンテキスト情報をユーザーに提供します。
Language Server Protocol
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 の結果をコマンドにバインドします。
カラーデコレーターを表示する
ユーザーがドキュメントの色をプレビューおよび変更できるようにします。
Language Server Protocol
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(...)) の色のプレゼンテーションを提供します。
高度
追加はありません。
エディターでソースコードをフォーマットする
ユーザーにドキュメント全体のフォーマットのサポートを提供します。
Language Server Protocol
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()));
...
}
基本
フォーマットサポートを提供しないでください。
高度
ソースコードがフォーマットされる最小限のテキスト編集を常に返す必要があります。これは、診断結果などのマーカーが正しく調整され、失われないようにするために重要です。
エディターで選択された行をフォーマットする
ユーザーにドキュメント内の選択された行範囲をフォーマットするサポートを提供します。
Language Server Protocol
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
は、ユーザーが入力するときにソースコードがフォーマットされるかどうかを制御します。
Language Server Protocol
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()));
...
}
基本
フォーマットサポートを提供しないでください。
高度
ソースコードがフォーマットされる最小限のテキスト編集を常に返す必要があります。これは、診断結果などのマーカーが正しく調整され、失われないようにするために重要です。
シンボルをリネームする
ユーザーがシンボルをリネームし、シンボルへのすべての参照を更新できるようにします。
Language Server Protocol
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()));
...
}
基本
リネームサポートを提供しないでください。
高度
実行する必要があるすべてのワークスペース編集のリストを返します。たとえば、シンボルへの参照を含むすべてのファイルにわたるすべての編集などです。