VS Codeのエージェントモードを拡張するには、を試してください!

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

セマンティックハイライトは、構文ハイライトガイドで説明されている構文ハイライトの追加機能です。Visual Studio Code は、TextMate 文法を主要なトークン化エンジンとして使用します。TextMate 文法は、単一のファイルを入力として受け取り、正規表現で表現された字句規則に基づいて分解します。

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

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

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

without semantic highlighting

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

with semantic highlighting

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

  • 10行目: languageModes はパラメータとして色付けされています
  • 11行目: RangePosition はクラスとして、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.jsonsemanticTokenTypes および 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 によって決定されます。値は truefalse、および configuredByTheme です。

  • truefalse は、すべてのテーマでセマンティックハイライトをオンまたはオフにします。
  • configuredByTheme はデフォルトで、各テーマがセマンティックハイライトを有効にするかどうかを制御します。VS Code に付属するすべてのテーマ(例えば、「Dark+」デフォルト)は、デフォルトでセマンティックハイライトが有効になっています。

セマンティックトークンに依存する言語拡張機能は、package.json でその言語のデフォルトをオーバーライドできます

{
  "configurationDefaults": {
    "[languageId]": {
      "editor.semanticHighlighting.enabled": true
    }
  }
}

テーマ設定

テーマ設定とは、トークンに色とスタイルを割り当てることです。テーマ設定ルールは、カラーテーマファイル (JSON 形式) で指定されます。ユーザーはユーザー設定でテーマ設定ルールをカスタマイズすることもできます。

カラーテーマでのセマンティックカラーリング

セマンティックトークンに基づくハイライトをサポートするために、カラーテーマファイル形式に2つの新しいプロパティが追加されました。

プロパティ semanticHighlighting は、テーマがセマンティックトークンを使用したハイライトに対応しているかどうかを定義します。デフォルトでは false ですが、すべてのテーマでこれを有効にすることをお勧めします。このプロパティは、設定 editor.semanticHighlighting.enabledconfiguredByTheme に設定されている場合に使用されます。

プロパティ 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.readwriteentity.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+) を使用します。