🚀 VS Code で で入手しましょう!

セマンティックハイライトガイド

セマンティックハイライトは、シンタックスハイライトガイドで説明されているシンタックスハイライトへの追加機能です。Visual Studio Code は、主なトークン化エンジンとして TextMate グラマーを使用しています。TextMate グラマーは、単一のファイルを入力として処理し、正規表現で表現された字句規則に基づいてファイルを分割します。

セマンティックトークン化により、言語サーバーは、プロジェクトのコンテキストでシンボルを解決する方法に関する言語サーバーの知識に基づいて、追加のトークン情報を提供できます。テーマは、セマンティックトークンを使用するようにオプトインして、グラマーからのシンタックスハイライトを改善および改良できます。エディターは、グラマーからのハイライトの上にセマンティックトークンからのハイライトを適用します。

セマンティックハイライトが追加できる例を次に示します

セマンティックハイライトなし

without semantic highlighting

セマンティックハイライトあり

with semantic highlighting

言語サービスによるシンボルの理解に基づいた色の違いに注目してください

  • 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 説明
名前空間 名前空間、モジュール、またはパッケージを宣言または参照する識別子。
クラス クラス型を宣言または参照する識別子。
列挙型 列挙型を宣言または参照する識別子。
インターフェース インターフェース型を宣言または参照する識別子。
構造体 構造体型を宣言または参照する識別子。
型パラメーター 型パラメーターを宣言または参照する識別子。
上記でカバーされていない型を宣言または参照する識別子。
パラメーター 関数またはメソッドパラメーターを宣言または参照する識別子。
変数 ローカル変数またはグローバル変数を宣言または参照する識別子。
プロパティ メンバープロパティ、メンバーフィールド、またはメンバー変数を宣言または参照する識別子。
列挙メンバー 列挙プロパティ、定数、またはメンバーを宣言または参照する識別子。
デコレーター デコレーターとアノテーションを宣言または参照する識別子。
イベント イベントプロパティを宣言する識別子。
関数 関数を宣言する識別子。
メソッド メンバー関数またはメソッドを宣言する識別子。
マクロ マクロを宣言する識別子。
ラベル ラベルを宣言する識別子。
コメント コメントを表すトークン。
文字列 文字列リテラルを表すトークン。
キーワード 言語キーワードを表すトークン。
数値 数値リテラルを表すトークン。
正規表現 正規表現リテラルを表すトークン。
演算子 演算子を表すトークン。

標準トークン修飾子

ID 説明
宣言 シンボルの宣言。
定義 シンボルの定義(例:ヘッダーファイル内)。
読み取り専用 読み取り専用の変数およびメンバーフィールド(定数)。
静的 クラスメンバー(静的メンバー)。
非推奨 使用すべきでないシンボル。
抽象 抽象的な型およびメンバー関数。
非同期 非同期としてマークされた関数。
変更 変数が代入される変数参照。
ドキュメント ドキュメント内のシンボルの出現箇所。
既定のライブラリ 標準ライブラリの一部であるシンボル。

標準タイプと修飾子に加えて、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 スコープ
名前空間 entity.name.namespace
entity.name.type
type.defaultLibrary support.type
構造体 storage.type.struct
クラス entity.name.type.class
class.defaultLibrary support.class
インターフェース entity.name.type.interface
列挙型 entity.name.type.enum
関数 entity.name.function
function.defaultLibrary support.function
メソッド entity.name.function.member
マクロ entity.name.function.preprocessor
変数 variable.other.readwriteentity.name.variable
variable.readonly variable.other.constant
variable.readonly.defaultLibrary support.constant
パラメーター variable.parameter
プロパティ variable.other.property
property.readonly variable.other.constant.property
列挙メンバー variable.other.enummember
イベント 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+)を使用します。