セマンティックハイライトガイド
セマンティックハイライトは、シンタックスハイライトガイドで説明されているシンタックスハイライトへの追加機能です。Visual Studio Codeは、TextMate文法を主要なトークン化エンジンとして使用しています。TextMate文法は、単一のファイルを入力として扱い、正規表現で表現された字句規則に基づいて分解します。
セマンティックトークン化により、言語サーバーはプロジェクトのコンテキストでシンボルを解決する方法に関する言語サーバーの知識に基づいて、追加のトークン情報を提供できます。テーマはセマンティックトークンを使用することを選択し、文法からのシンタックスハイライトを改善および洗練することができます。エディターは、文法からのハイライトの上にセマンティックトークンからのハイライトを適用します。
セマンティックハイライトが追加できる例を以下に示します
セマンティックハイライトなし
セマンティックハイライトあり
言語サービスがシンボルを理解していることに基づく色の違いに注目してください
- 10行目:
languageModes
がパラメーターとして着色されています - 11行目:
Range
とPosition
がクラスとして、document
がパラメーターとして着色されています。 - 13行目:
getFoldingRanges
が関数として着色されています。
セマンティックトークンプロバイダー
セマンティックハイライトを実装するために、言語拡張機能はドキュメント言語および/またはファイル名によってsemantic token provider
を登録できます。エディターは、セマンティックトークンが必要なときにプロバイダーにリクエストを送信します。
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 |
使用されなくなったシンボルの場合。 |
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)?
の形式を取ります。
値は、ルールが一致する場合のスタイルを記述します。これは、前景色を表す文字列か、またはtokenColors
でTextMateテーマルールに使用される{ foreground: string, bold: boolean, italic: boolean, underline: boolean }
または{ 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+)を使用してください。