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

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

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

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

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

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

without semantic highlighting

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

with semantic highlighting

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

  • 10行目:languageModesがパラメーターとして着色されています
  • 11行目:RangePositionがクラスとして、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によって決定されます。この設定は、truefalse、およびconfiguredByThemeの値を取ることができます。

  • trueおよびfalseは、すべてのテーマに対してセマンティックハイライトをオンまたはオフにします。
  • 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)?の形式を取ります。

値は、ルールが一致する場合のスタイルを記述します。これは、前景色を表す文字列か、または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+)を使用してください。