に参加して、VS Code の AI 支援開発について学びましょう。

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

セマンティックハイライトは、構文ハイライトガイドで説明されているように、構文ハイライトに追加されるものです。Visual Studio Codeは、TextMateグラマーを主要なトークン化エンジンとして使用しています。TextMateグラマーは、1つのファイルを入力として、正規表現で表現された字句規則に基づいてファイルを分割します。

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

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

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

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

標準トークン修飾子

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

標準の型と修飾子に加えて、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スコープ
名前空間 entity.name.namespace
type entity.name.type
type.defaultLibrary support.type
構造体 storage.type.struct
クラス entity.name.type.class
class.defaultLibrary support.class
インターフェース entity.name.type.interface
enum entity.name.type.enum
関数 entity.name.function
function.defaultLibrary support.function
メソッド entity.name.function.member
マクロ entity.name.function.preprocessor
variable variable.other.readwrite , entity.name.variable
variable.readonly variable.other.constant
variable.readonly.defaultLibrary support.constant
パラメータ variable.parameter
property variable.other.property
property.readonly variable.other.constant.property
enumMember variable.other.enummember
event variable.other.event

カスタムTextMateスコープマッピング

このマップは、拡張機能のpackage.jsonsemanticTokenScopes貢献ポイントを通じて、拡張機能によって拡張できます。

拡張機能がこれを行うためのユースケースは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+)を使用します。

© . This site is unofficial and not affiliated with Microsoft.