セマンティックハイライトガイド
セマンティックハイライトは、構文ハイライトガイドで説明されている構文ハイライトの追加機能です。Visual Studio Code は、TextMate 文法を主要なトークン化エンジンとして使用します。TextMate 文法は、単一のファイルを入力として受け取り、正規表現で表現された字句規則に基づいて分解します。
セマンティックトークン化により、言語サーバーは、プロジェクトのコンテキストでシンボルを解決する方法に関する言語サーバーの知識に基づいて、追加のトークン情報を提供できます。テーマは、セマンティックトークンを使用して、文法からの構文ハイライトを改善および洗練することを選択できます。エディターは、文法からのハイライトの上にセマンティックトークンからのハイライトを適用します。
セマンティックハイライトが追加できる例を次に示します
セマンティックハイライトなし
セマンティックハイライトあり
言語サービスシンボルの理解に基づいた色の違いに注目してください
- 10行目:
languageModes
はパラメータとして色付けされています - 11行目:
Range
とPosition
はクラスとして、document
はパラメータとして色付けされています。 - 13行目:
getFoldingRanges
は関数として色付けされています。
セマンティックトークンプロバイダー
セマンティックハイライトを実装するには、言語拡張機能は、ドキュメント言語および/またはファイル名によってセマンティックトークンプロバイダー
を登録できます。エディターは、セマンティックトークンが必要なときにプロバイダーにリクエストを送信します。
const tokenTypes = ['class', 'interface', 'enum', 'function', 'variable'];
const tokenModifiers = ['declaration', 'documentation'];
const legend = new vscode.SemanticTokensLegend(tokenTypes, tokenModifiers);
const provider: vscode.DocumentSemanticTokensProvider = {
provideDocumentSemanticTokens(
document: vscode.TextDocument
): vscode.ProviderResult<vscode.SemanticTokens> {
// analyze the document and return semantic tokens
const tokensBuilder = new vscode.SemanticTokensBuilder(legend);
// on line 1, characters 1-5 are a class declaration
tokensBuilder.push(
new vscode.Range(new vscode.Position(1, 1), new vscode.Position(1, 5)),
'class',
['declaration']
);
return tokensBuilder.build();
}
};
const selector = { language: 'java', scheme: 'file' }; // register for all Java documents from the local file system
vscode.languages.registerDocumentSemanticTokensProvider(selector, provider, legend);
セマンティックトークンプロバイダー API には、言語サーバーの機能を収容するために2つの種類があります
-
DocumentSemanticTokensProvider
- 常に完全なドキュメントを入力として受け取ります。provideDocumentSemanticTokens
- ドキュメントのすべてのトークンを提供します。provideDocumentSemanticTokensEdits
- ドキュメントのすべてのトークンを以前の応答に対するデルタとして提供します。
-
DocumentRangeSemanticTokensProvider
- 範囲でのみ機能します。provideDocumentRangeSemanticTokens
- ドキュメント範囲のすべてのトークンを提供します。
プロバイダーによって返される各トークンには、トークンタイプ、任意の数のトークン修飾子、およびトークン言語で構成される分類が付属しています。
上記の例のように、プロバイダーは、SemanticTokensLegend
で使用するタイプと修飾子の名前を付けます。これにより、provide
API は、凡例へのインデックスとしてトークンタイプと修飾子を返すことができます。
セマンティックトークン分類
セマンティックトークンプロバイダーの出力はトークンで構成されます。各トークンには、トークンがどのような構文要素を表すかを記述する範囲とトークン分類があります。オプションで、トークンが埋め込み言語の一部である場合、分類は言語の名前も付けることができます。
構文要素の種類を記述するために、セマンティックトークンタイプと修飾子が使用されます。この情報は、構文ハイライトガイドで説明されているTextMateスコープに似ていますが、専用のよりクリーンな分類システムを考案したかったのです。
VS Codeには、すべてのセマンティックトークンプロバイダーが使用する標準のセマンティックトークンタイプと修飾子のセットが付属しています。それでも、セマンティックトークンプロバイダーは、新しいタイプと修飾子を定義し、標準タイプのサブタイプを作成することができます。
標準トークンタイプと修飾子
標準のタイプと修飾子は、多くの言語で使用される一般的な概念をカバーしています。各言語は一部のタイプと修飾子に異なる用語を使用するかもしれませんが、標準の分類に準拠することで、テーマ作成者は言語間で機能するテーマルールを定義できます。
これらは、VS Codeによって事前に定義された標準のセマンティックトークンタイプとセマンティックトークン修飾子です
標準トークンタイプ
ID | 説明 |
---|---|
namespace |
名前空間、モジュール、またはパッケージを宣言または参照する識別子の場合。 |
class |
クラスタイプを宣言または参照する識別子の場合。 |
enum |
列挙型を宣言または参照する識別子の場合。 |
interface |
インターフェースタイプを宣言または参照する識別子の場合。 |
struct |
構造体タイプを宣言または参照する識別子の場合。 |
typeParameter |
型パラメータを宣言または参照する識別子の場合。 |
type |
上記でカバーされていない型を宣言または参照する識別子の場合。 |
parameter |
関数またはメソッドのパラメータを宣言または参照する識別子の場合。 |
variable |
ローカル変数またはグローバル変数を宣言または参照する識別子の場合。 |
property |
メンバープロパティ、メンバーフィールド、またはメンバー変数を宣言または参照する識別子の場合。 |
enumMember |
列挙プロパティ、定数、またはメンバーを宣言または参照する識別子の場合。 |
decorator |
デコレーターとアノテーションを宣言または参照する識別子の場合。 |
event |
イベントプロパティを宣言する識別子の場合。 |
function |
関数を宣言する識別子の場合。 |
method |
メンバー関数またはメソッドを宣言する識別子の場合。 |
macro |
マクロを宣言する識別子の場合。 |
label |
ラベルを宣言する識別子の場合。 |
comment |
コメントを表すトークンの場合。 |
string |
文字列リテラルを表すトークンの場合。 |
keyword |
言語キーワードを表すトークンの場合。 |
number |
数値リテラルを表すトークンの場合。 |
regexp |
正規表現リテラルを表すトークンの場合。 |
operator |
演算子を表すトークンの場合。 |
標準トークン修飾子
ID | 説明 |
---|---|
declaration |
シンボルの宣言の場合。 |
definition |
シンボルの定義の場合、例えばヘッダーファイル内。 |
readonly |
読み取り専用変数およびメンバーフィールド(定数)の場合。 |
static |
クラスメンバー(静的メンバー)の場合。 |
deprecated |
使用すべきではないシンボル。Deprecated とは、非推奨、旧式、推奨されない、という意味です。 |
abstract |
抽象的な型やメンバー関数の場合。 |
async |
非同期としてマークされた関数の場合。 |
modification |
変数が代入される変数参照の場合。 |
documentation |
ドキュメント内のシンボルの出現の場合。 |
defaultLibrary |
標準ライブラリの一部であるシンボル。 |
標準の型と修飾子に加えて、VS Code は型と修飾子を類似の TextMate スコープにマッピングすることを定義しています。これは、セマンティックトークンスコープマップのセクションで説明されています。
カスタムトークンタイプと修飾子
必要に応じて、拡張機能は、拡張機能の package.json
の semanticTokenTypes
および semanticTokenModifiers
貢献ポイントを介して、新しいタイプと修飾子を宣言したり、既存のタイプのサブタイプを作成したりできます
{
"contributes": {
"semanticTokenTypes": [
{
"id": "templateType",
"superType": "type",
"description": "A template type."
}
],
"semanticTokenModifiers": [
{
"id": "native",
"description": "Annotates a symbol that is implemented natively"
}
]
}
}
上記の例では、拡張機能は新しい型 templateType
と新しい修飾子 native
を宣言しています。type
をスーパータイプとして指定することで、type
のテーマスタイルルールが templateType
にも適用されます
{
"name": "Red Theme",
"semanticTokenColors": {
"type": "#ff0011"
}
}
上記の semanticTokenColors
の値 "#ff0011"
は、type
とそのすべてのサブタイプ(templateType
を含む)の両方に適用されます。
カスタムトークンタイプに加えて、拡張機能は、これらがTextMateスコープにどのようにマッピングされるかを定義できます。これは、カスタムマッピングセクションで説明されています。カスタムマッピングルールはスーパータイプから自動的に継承されないことに注意してください。代わりに、サブタイプはマッピングを再定義する必要があり、できればより具体的なスコープにしてください。
セマンティックハイライトの有効化
セマンティックトークンが計算され、ハイライトされるかどうかは、設定 editor.semanticHighlighting.enabled
によって決定されます。値は true
、false
、および configuredByTheme
です。
true
とfalse
は、すべてのテーマでセマンティックハイライトをオンまたはオフにします。configuredByTheme
はデフォルトで、各テーマがセマンティックハイライトを有効にするかどうかを制御します。VS Code に付属するすべてのテーマ(例えば、「Dark+」デフォルト)は、デフォルトでセマンティックハイライトが有効になっています。
セマンティックトークンに依存する言語拡張機能は、package.json
でその言語のデフォルトをオーバーライドできます
{
"configurationDefaults": {
"[languageId]": {
"editor.semanticHighlighting.enabled": true
}
}
}
テーマ設定
テーマ設定とは、トークンに色とスタイルを割り当てることです。テーマ設定ルールは、カラーテーマファイル (JSON 形式) で指定されます。ユーザーはユーザー設定でテーマ設定ルールをカスタマイズすることもできます。
カラーテーマでのセマンティックカラーリング
セマンティックトークンに基づくハイライトをサポートするために、カラーテーマファイル形式に2つの新しいプロパティが追加されました。
プロパティ semanticHighlighting
は、テーマがセマンティックトークンを使用したハイライトに対応しているかどうかを定義します。デフォルトでは false ですが、すべてのテーマでこれを有効にすることをお勧めします。このプロパティは、設定 editor.semanticHighlighting.enabled
が configuredByTheme
に設定されている場合に使用されます。
プロパティ semanticTokenColors
により、テーマは、セマンティックトークンプロバイダーによって発行されるセマンティックトークンタイプと修飾子に一致する新しいカラーリングルールを定義できます。
{
"name": "Red Theme",
"tokenColors": [
{
"scope": "comment",
"settings": {
"foreground": "#dd0000",
"fontStyle": "italic"
}
}
],
"semanticHighlighting": true,
"semanticTokenColors": {
"variable.readonly:java": "#ff0011"
}
}
variable.readonly:java
はセレクターと呼ばれ、(*|tokenType)(.tokenModifier)*(:tokenLanguage)?
の形式です。
値は、ルールが一致する場合のスタイルを記述します。これは、前景を表す文字列、または { foreground: string, bold: boolean, italic: boolean, underline: boolean }
の形式のオブジェクト、または tokenColors
で TextMate テーマルールに使用される { foreground: string, fontStyle: string }
の形式のオブジェクトのいずれかです。
前景は、色の形式で説明されている色の形式に従う必要があります。透明性はサポートされていません。
セレクターとスタイルの他の例を次に示します
"*.declaration": { "bold": true } // すべての宣言は太字になります
"class:java": { "foreground": "#0f0", "italic": true } // Java のクラス
ルールが一致しない場合、またはテーマに semanticTokenColors
セクションがない場合 (ただし semanticHighlighting
が有効になっている場合)、VS Code は セマンティックトークンスコープマップ を使用して、指定されたセマンティックトークンの TextMate スコープを評価します。そのスコープは、テーマの tokenColors
内の TextMate テーマルールと照合されます。
セマンティックトークンスコープマップ
特定のセマンティックルールを定義していないテーマでセマンティックハイライトを機能させ、カスタムトークンタイプと修飾子のフォールバックとして機能させるために、VS Code はセマンティックトークンセレクターから TextMate スコープへのマップを維持しています。
テーマでセマンティックハイライトが有効になっているが、指定されたセマンティックトークンのルールが含まれていない場合、これらの TextMate スコープが代わりに TextMate テーマルールを見つけるために使用されます。
事前定義されたTextMateスコープマッピング
次の表に、現在事前定義されているマッピングを示します。
セマンティックトークンセレクター | フォールバック TextMate スコープ |
---|---|
namespace |
entity.name.namespace |
type |
entity.name.type |
type.defaultLibrary |
support.type |
struct |
storage.type.struct |
class |
entity.name.type.class |
class.defaultLibrary |
support.class |
interface |
entity.name.type.interface |
enum |
entity.name.type.enum |
function |
entity.name.function |
function.defaultLibrary |
support.function |
method |
entity.name.function.member |
macro |
entity.name.function.preprocessor |
variable |
variable.other.readwrite 、entity.name.variable |
variable.readonly |
variable.other.constant |
variable.readonly.defaultLibrary |
support.constant |
parameter |
variable.parameter |
property |
variable.other.property |
property.readonly |
variable.other.constant.property |
enumMember |
variable.other.enummember |
event |
variable.other.event |
カスタム TextMate スコープマッピング
このマップは、拡張機能の package.json
にある semanticTokenScopes
貢献ポイントを通じて拡張できます。
拡張機能がこれを行うための2つのユースケースがあります
-
カスタムトークンタイプとトークン修飾子を定義する拡張機能は、テーマが追加されたセマンティックトークンタイプまたは修飾子にテーマルールを定義していない場合に、TextMateスコープをフォールバックとして提供します
{ "contributes": { "semanticTokenScopes": [ { "scopes": { "templateType": ["entity.name.type.template"] } } ] } }
-
TextMate 文法のプロバイダーは、言語固有のスコープを記述できます。これは、言語固有のテーマルールを含むテーマに役立ちます。
{ "contributes": { "semanticTokenScopes": [ { "language": "typescript", "scopes": { "property.readonly": ["variable.other.constant.property.ts"] } } ] } }
試してみる
セマンティックトークンプロバイダーの作成方法を示す セマンティックトークンサンプル があります。
スコープインスペクターツールを使用すると、ソースファイルに存在するセマンティックトークンと、それらが一致するテーマルールを調べることができます。セマンティックトークンを表示するには、TypeScript ファイルで組み込みテーマ (例: Dark+) を使用します。