現已釋出!閱讀關於 11 月新增功能和修復的內容。

語義高亮指南

語義高亮是語法高亮功能的補充,相關內容請參閱 語法高亮指南。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 有兩種形式,以適應語言伺服器的能力

  • 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 表示註釋的分詞。
字串 表示字串字面量的分詞。
keyword 表示語言關鍵字的分詞。
number 表示數字字面量的分詞。
regexp 表示正則表示式字面量的分詞。
operator 表示運算子的分詞。

標準分詞修飾符

ID 描述
declaration 用於符號的宣告。
definition 用於符號的定義,例如在標頭檔案中。
readonly 用於只讀變數和成員欄位(常量)。
static 用於類成員(靜態成員)。
deprecated 用於不再應使用的符號。
abstract 用於抽象的型別和成員函式。
async 用於標記為非同步的函式。
modification 用於變數引用,其中變數正在被賦值。
documentation 用於文件中符號的出現。
defaultLibrary 用於屬於標準庫的符號。

除了標準型別和修飾符之外,VS Code 還定義了型別和修飾符到類似 TextMate 範圍的對映。這在 語義分詞範圍對映 部分進行了介紹。

自定義分詞型別和修飾符

如果需要,擴充套件可以透過其 package.json 中的 semanticTokenTypessemanticTokenModifiers 貢獻點宣告新的型別和修飾符,或建立現有型別的子型別。

{
  "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 決定。它可以具有 truefalseconfiguredByTheme 的值。

  • truefalse 分別啟用或停用所有主題的語義高亮。
  • configuredByTheme 是預設值,它允許每個主題控制是否啟用語義高亮。所有 VS Code 自帶的主題(例如,“Dark+” 預設主題)預設都啟用了語義高亮。

依賴語義分詞的語言擴充套件可以在其 package.json 中覆蓋其語言的預設設定。

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

主題

主題是指為分詞分配顏色和樣式。主題規則在顏色主題檔案(JSON 格式)中指定。使用者還可以在使用者設定中自定義主題規則。

顏色主題中的語義著色

為了支援基於語義分詞的高亮,顏色主題檔案格式中添加了兩個新屬性。

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)?

值描述了規則匹配時的樣式。它可以是字串,表示前景色;也可以是物件,形式為 { foreground: string, bold: boolean, italic: boolean, underline: boolean }{ foreground: string, fontStyle: string },用於 TextMate 主題規則中的 tokenColors

前景色必須遵循 顏色格式 中描述的顏色格式。不支援透明度。

以下是選擇器和樣式的其他示例

  • "*.declaration": { "bold": true } // 所有宣告都是粗體
  • "class:java": { "foreground": "#0f0", "italic": true } // Java 中的類

如果沒有規則匹配,或者主題沒有 semanticTokenColors 部分(但 semanticHighlighting 已啟用),VS Code 將使用 語義分詞範圍對映 來評估給定語義分詞的 TextMate 範圍。該範圍將與主題的 TextMate 主題規則在 tokenColors 中進行匹配。

語義分詞範圍對映

為了使尚未定義任何特定語義規則的主題能夠實現語義高亮,並作為自定義分詞型別和修飾符的回退,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 貢獻點來擴充套件此對映。

擴充套件進行此操作有兩種用例:

  • 定義自定義分詞型別和分詞修飾符的擴充套件,在主題未為新增的語義分詞型別或修飾符定義主題規則時,提供 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.