程式化語言功能

程式語言功能是一組由 vscode.languages.* API 支援的智慧編輯功能。在 Visual Studio Code 中提供動態語言功能有兩種常見方式。讓我們以 Hover(游標懸停提示) 為例。

vscode.languages.registerHoverProvider('javascript', {
  provideHover(document, position, token) {
    return {
      contents: ['Hover Content']
    };
  }
});

如上所示,vscode.languages.registerHoverProvider API 提供了一種簡單的方法,為 JavaScript 檔案提供游標懸停內容。當此擴充功能啟用後,每當您將游標懸停在 JavaScript 程式碼上時,VS Code 會查詢所有 JavaScript 的 HoverProvider,並將結果顯示在 Hover 小工具中。下方的語言功能清單和示意 GIF 為您提供了一種簡單的方法,來定位您的擴充功能需要哪種 VS Code API 或 LSP 方法。

另一種方法是實作一個支援 Language Server Protocol(語言伺服器協定)的語言伺服器。其運作方式如下:

  • 擴充功能為 JavaScript 提供語言用戶端 (Language Client) 和語言伺服器 (Language Server)。
  • 語言用戶端就像任何其他 VS Code 擴充功能一樣,在 Node.js 擴充功能主機環境中執行。當它被啟用時,它會在另一個處理序中啟動語言伺服器,並透過 Language Server Protocol 與其進行通訊。
  • 您在 VS Code 中將游標懸停於 JavaScript 程式碼上。
  • VS Code 將懸停事件通知語言用戶端。
  • 語言用戶端向語言伺服器查詢懸停結果,並將其傳回給 VS Code。
  • VS Code 在 Hover 小工具中顯示懸停結果。

這個過程看起來比較複雜,但它提供了兩個主要好處:

  • 語言伺服器可以用任何語言編寫。
  • 語言伺服器可以被重複使用,為多個編輯器提供智慧編輯功能。

如需更深入的指南,請前往 語言伺服器擴充功能指南


語言功能清單

此清單包含每項語言功能的下列項目:

  • 該語言功能在 VS Code 中的示意圖。
  • 相關的 VS Code API。
  • 相關的 LSP 方法。
VS Code API LSP 方法
createDiagnosticCollection PublishDiagnostics
registerCompletionItemProvider Completion(自動完成)Completion Resolve(完成解析)
registerInlineCompletionItemProvider
registerHoverProvider 懸停
registerSignatureHelpProvider SignatureHelp(簽名協助)
registerDefinitionProvider Definition(定義)
registerTypeDefinitionProvider TypeDefinition(類型定義)
registerImplementationProvider Implementation(實作)
registerReferenceProvider 參考資料
registerDocumentHighlightProvider DocumentHighlight(文件高亮)
registerDocumentSymbolProvider DocumentSymbol(文件符號)
registerCodeActionsProvider CodeAction(程式碼動作)
registerCodeLensProvider CodeLensCodeLens Resolve(CodeLens 解析)
registerDocumentLinkProvider DocumentLink(文件連結)DocumentLink Resolve(文件連結解析)
registerColorProvider DocumentColor(文件色彩)Color Presentation(色彩呈現)
registerDocumentFormattingEditProvider 格式化
registerDocumentRangeFormattingEditProvider RangeFormatting(範圍格式化)
registerOnTypeFormattingEditProvider OnTypeFormatting(輸入時格式化)
registerRenameProvider Rename(重新命名)Prepare Rename(準備重新命名)
registerFoldingRangeProvider FoldingRange(摺疊範圍)

提供診斷 (Provide Diagnostics)

診斷是用於指出程式碼問題的一種方式。

Diagnostics indicating a misspelled method name

語言伺服器通訊協定 (Language Server Protocol)

您的語言伺服器會將 textDocument/publishDiagnostics 訊息傳送給語言用戶端。該訊息包含資源 URI 的診斷項目陣列。

注意:用戶端不會主動向伺服器請求診斷。伺服器會主動將診斷資訊推送至用戶端。

直接實作

let diagnosticCollection: vscode.DiagnosticCollection;

export function activate(ctx: vscode.ExtensionContext): void {
  ...
  ctx.subscriptions.push(getDisposable());
  diagnosticCollection = vscode.languages.createDiagnosticCollection('go');
  ctx.subscriptions.push(diagnosticCollection);
  ...
}

function onChange() {
  let uri = document.uri;
  check(uri.fsPath, goConfig).then(errors => {
    diagnosticCollection.clear();
    let diagnosticMap: Map<string, vscode.Diagnostic[]> = new Map();
    errors.forEach(error => {
      let canonicalFile = vscode.Uri.file(error.file).toString();
      let range = new vscode.Range(error.line-1, error.startColumn, error.line-1, error.endColumn);
      let diagnostics = diagnosticMap.get(canonicalFile);
      if (!diagnostics) { diagnostics = []; }
      diagnostics.push(new vscode.Diagnostic(range, error.msg, error.severity));
      diagnosticMap.set(canonicalFile, diagnostics);
    });
    diagnosticMap.forEach((diags, file) => {
      diagnosticCollection.set(vscode.Uri.parse(file), diags);
    });
  })
}

基本

針對已開啟的編輯器報告診斷。最低限度,這需要在每次儲存時進行。更好的做法是根據編輯器中未儲存的內容來計算診斷。

進階

不僅針對已開啟的編輯器,還要針對已開啟資料夾中的所有資源進行診斷報告,無論它們是否曾在編輯器中開啟過。

顯示程式碼完成建議

程式碼完成功能會為使用者提供內容敏感的建議。

Code Completion prompting variable, method, and parameter names while writing code

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供完成功能,以及是否支援 completionItem/resolve 方法,以便為計算出的完成項目提供額外資訊。

{
    ...
    "capabilities" : {
        "completionProvider" : {
            "resolveProvider": "true",
            "triggerCharacters": [ '.' ]
        }
        ...
    }
}

直接實作

class GoCompletionItemProvider implements vscode.CompletionItemProvider {
    public provideCompletionItems(
        document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken):
        Thenable<vscode.CompletionItem[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(getDisposable());
    ctx.subscriptions.push(
        vscode.languages.registerCompletionItemProvider(
            GO_MODE, new GoCompletionItemProvider(), '.', '\"'));
    ...
}

基本

您不支援解析提供者 (resolve providers)。

進階

您支援解析提供者,可為使用者選取的完成建議計算額外資訊。此資訊將顯示在所選項目的旁邊。

顯示行內完成 (Inline Completions)

行內完成直接在編輯器中呈現多詞彙建議(幽靈文字)。

Inline Completions suggesting code as ghost text while writing code

直接實作

vscode.languages.registerInlineCompletionItemProvider({ language: 'javascript' }, {
    provideInlineCompletionItems(document, position, context, token) {
        const result: vscode.InlineCompletionList = {
            items: [],
            commands: [],
        };

        ...

        return result;
    }
});

您可以在 行內完成範例擴充功能 中探索完整的範例。

基本

僅針對特定語言,根據當前行內容中已知的模式清單傳回行內完成。

進階

根據整個文件或工作區中的內容及更複雜的模式傳回行內完成。

顯示懸停提示 (Show Hovers)

懸停提示會顯示滑鼠游標下方符號/物件的相關資訊。這通常是符號的類型及說明。

Showing details about a workspace and a method when hovering over them

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供懸停功能。

{
    ...
    "capabilities" : {
        "hoverProvider" : "true",
        ...
    }
}

此外,您的語言伺服器需要回應 textDocument/hover 請求。

直接實作

class GoHoverProvider implements HoverProvider {
    public provideHover(
        document: TextDocument, position: Position, token: CancellationToken):
        Thenable<Hover> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerHoverProvider(
            GO_MODE, new GoHoverProvider()));
    ...
}

基本

顯示類型資訊,並在可用時包含文件說明。

進階

以與程式碼著色相同的風格為方法簽名著色。

函數與方法簽名協助

當使用者輸入函數或方法時,顯示正在呼叫的函數/方法的資訊。

Showing information about the getPackageInfo method including the necessary parameters

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供簽名協助。

{
    ...
    "capabilities" : {
        "signatureHelpProvider" : {
            "triggerCharacters": [ '(' ]
        }
        ...
    }
}

此外,您的語言伺服器需要回應 textDocument/signatureHelp 請求。

直接實作

class GoSignatureHelpProvider implements SignatureHelpProvider {
    public provideSignatureHelp(
        document: TextDocument, position: Position, token: CancellationToken):
        Promise<SignatureHelp> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerSignatureHelpProvider(
            GO_MODE, new GoSignatureHelpProvider(), '(', ','));
    ...
}

基本

確保簽名協助包含該函數或方法的參數說明文件。

進階

無額外內容。

顯示符號定義

允許使用者在變數/函數/方法被使用的地方直接查看其定義。

Right click a variable, function, or method and select "Go to Definition" to jump to the definition

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供跳轉至定義 (goto-definition) 的位置。

{
    ...
    "capabilities" : {
        "definitionProvider" : "true"
        ...
    }
}

此外,您的語言伺服器需要回應 textDocument/definition 請求。

直接實作

class GoDefinitionProvider implements vscode.DefinitionProvider {
    public provideDefinition(
        document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken):
        Thenable<vscode.Location> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerDefinitionProvider(
            GO_MODE, new GoDefinitionProvider()));
    ...
}

基本

如果符號具歧義,您可以顯示多個定義。

進階

無額外內容。

尋找符號的所有參考

允許使用者查看特定變數/函數/方法/符號在原始程式碼中被使用的所有位置。

Right clicking and selecting "Find All References" to highlight all the locations where that symbol is used

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供符號參考位置。

{
    ...
    "capabilities" : {
        "referencesProvider" : "true"
        ...
    }
}

此外,您的語言伺服器需要回應 textDocument/references 請求。

直接實作

class GoReferenceProvider implements vscode.ReferenceProvider {
    public provideReferences(
        document: vscode.TextDocument, position: vscode.Position,
        options: { includeDeclaration: boolean }, token: vscode.CancellationToken):
        Thenable<vscode.Location[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerReferenceProvider(
            GO_MODE, new GoReferenceProvider()));
    ...
}

基本

傳回所有參考的位置(資源 URI 和範圍)。

進階

無額外內容。

反白顯示文件中符號的所有出現位置

允許使用者查看符號在開啟的編輯器中出現的所有位置。

Select a symbol to highlight all occurrences

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供文件符號位置。

{
    ...
    "capabilities" : {
        "documentHighlightProvider" : "true"
        ...
    }
}

此外,您的語言伺服器需要回應 textDocument/documentHighlight 請求。

直接實作

class GoDocumentHighlightProvider implements vscode.DocumentHighlightProvider {
    public provideDocumentHighlights(
        document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken):
        vscode.DocumentHighlight[] | Thenable<vscode.DocumentHighlight[]>;
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerDocumentHighlightProvider(
            GO_MODE, new GoDocumentHighlightProvider()));
    ...
}

基本

您傳回在編輯器文件中找到參考的範圍。

進階

無額外內容。

顯示文件中所有的符號定義

允許使用者快速導航到開啟編輯器中的任何符號定義。

Navigate to a symbol definition in the open editor using @

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供文件符號位置。

{
    ...
    "capabilities" : {
        "documentSymbolProvider" : "true"
        ...
    }
}

此外,您的語言伺服器需要回應 textDocument/documentSymbol 請求。

直接實作

class GoDocumentSymbolProvider implements vscode.DocumentSymbolProvider {
    public provideDocumentSymbols(
        document: vscode.TextDocument, token: vscode.CancellationToken):
        Thenable<vscode.SymbolInformation[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerDocumentSymbolProvider(
            GO_MODE, new GoDocumentSymbolProvider()));
    ...
}

基本

傳回文件中的所有符號。定義符號的種類,例如變數、函數、類別、方法等。

進階

無額外內容。

顯示資料夾中所有的符號定義

允許使用者快速導航到 VS Code 中開啟資料夾(工作區)內任何地方的符號定義。

Navigate to symbol definitions in the workspace using #

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供全域符號位置。

{
    ...
    "capabilities" : {
        "workspaceSymbolProvider" : "true"
        ...
    }
}

此外,您的語言伺服器需要回應 workspace/symbol 請求。

直接實作

class GoWorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvider {
    public provideWorkspaceSymbols(
        query: string, token: vscode.CancellationToken):
        Thenable<vscode.SymbolInformation[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerWorkspaceSymbolProvider(
            new GoWorkspaceSymbolProvider()));
    ...
}

基本

傳回已開啟資料夾內原始程式碼所定義的所有符號。定義符號的種類,例如變數、函數、類別、方法等。

進階

無額外內容。

錯誤或警告的可能動作

在錯誤或警告旁邊為使用者提供可能的修正動作。如果動作可用,錯誤或警告旁邊會出現燈泡圖示。當使用者點擊燈泡時,會顯示可用程式碼動作的清單。

Selecting a light bulb to view a list of available Code Actions

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供程式碼動作 (Code Actions)。

{
    ...
    "capabilities" : {
        "codeActionProvider" : "true"
        ...
    }
}

此外,您的語言伺服器需要回應 textDocument/codeAction 請求。

直接實作

class GoCodeActionProvider implements vscode.CodeActionProvider<vscode.CodeAction> {
    public provideCodeActions(
        document: vscode.TextDocument, range: vscode.Range | vscode.Selection,
        context: vscode.CodeActionContext, token: vscode.CancellationToken):
        Thenable<vscode.CodeAction[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerCodeActionsProvider(
            GO_MODE, new GoCodeActionProvider()));
    ...
}

基本

為錯誤/警告修正動作提供程式碼動作。

進階

此外,提供原始程式碼操作功能,例如重構。例如:擷取方法 (Extract Method)

CodeLens - 在原始程式碼中顯示可操作的上下文資訊

為使用者提供穿插在原始程式碼中、可操作且具備上下文的資訊。

CodeLens providing context

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供 CodeLens 結果,以及是否支援 codeLens/resolve 方法來將 CodeLens 綁定到其指令。

{
    ...
    "capabilities" : {
        "codeLensProvider" : {
            "resolveProvider": "true"
        }
        ...
    }
}

此外,您的語言伺服器需要回應 textDocument/codeLens 請求。

直接實作

class GoCodeLensProvider implements vscode.CodeLensProvider {
    public provideCodeLenses(document: TextDocument, token: CancellationToken):
        CodeLens[] | Thenable<CodeLens[]> {
    ...
    }

    public resolveCodeLens?(codeLens: CodeLens, token: CancellationToken):
         CodeLens | Thenable<CodeLens> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerCodeLensProvider(
            GO_MODE, new GoCodeLensProvider()));
    ...
}

基本

定義文件中可用的 CodeLens 結果。

進階

透過回應 codeLens/resolve 將 CodeLens 結果綁定到指令。

顯示色彩裝飾器 (Color Decorators)

允許使用者預覽並修改文件中的色彩。

Showing the color picker

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供色彩資訊。

{
    ...
    "capabilities" : {
        "colorProvider" : "true"
        ...
    }
}

此外,您的語言伺服器需要回應 textDocument/documentColortextDocument/colorPresentation 請求。

直接實作

class GoColorProvider implements vscode.DocumentColorProvider {
    public provideDocumentColors(
        document: vscode.TextDocument, token: vscode.CancellationToken):
        Thenable<vscode.ColorInformation[]> {
    ...
    }
    public provideColorPresentations(
        color: Color, context: { document: TextDocument, range: Range }, token: vscode.CancellationToken):
        Thenable<vscode.ColorPresentation[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerColorProvider(
            GO_MODE, new GoColorProvider()));
    ...
}

基本

傳回文件中的所有色彩參考。針對支援的色彩格式(例如 rgb(...)、hsl(...))提供色彩呈現。

進階

無額外內容。

在編輯器中格式化原始程式碼

為使用者提供格式化整個文件的支援。

Right click and select format code

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供文件格式化功能。

{
    ...
    "capabilities" : {
        "documentFormattingProvider" : "true"
        ...
    }
}

此外,您的語言伺服器需要回應 textDocument/formatting 請求。

直接實作

class GoDocumentFormatter implements vscode.DocumentFormattingEditProvider {
    provideDocumentFormattingEdits(
        document: vscode.TextDocument, options: vscode.FormattingOptions, token: vscode.CancellationToken)
        : vscode.ProviderResult<vscode.TextEdit[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerDocumentFormattingEditProvider(
            GO_MODE, new GoDocumentFormatter()));
    ...
}

基本

不提供格式化支援。

進階

您應該始終傳回能達成格式化原始程式碼的最小文字編輯量。這對於確保診斷結果等標記能正確調整且不會丟失至關重要。

在編輯器中格式化所選行

為使用者提供格式化文件中所選行範圍的支援。

Select lines, right click, and select format code

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供行範圍的格式化支援。

{
    ...
    "capabilities" : {
        "documentRangeFormattingProvider" : "true"
        ...
    }
}

此外,您的語言伺服器需要回應 textDocument/rangeFormatting 請求。

直接實作

class GoDocumentRangeFormatter implements vscode.DocumentRangeFormattingEditProvider{
    public provideDocumentRangeFormattingEdits(
        document: vscode.TextDocument, range: vscode.Range,
        options: vscode.FormattingOptions, token: vscode.CancellationToken):
        vscode.ProviderResult<vscode.TextEdit[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerDocumentRangeFormattingEditProvider(
            GO_MODE, new GoDocumentRangeFormatter()));
    ...
}

基本

不提供格式化支援。

進階

您應該始終傳回能達成格式化原始程式碼的最小文字編輯量。這對於確保診斷結果等標記能正確調整且不會丟失至關重要。

使用者輸入時的增量程式碼格式化

為使用者提供輸入時格式化文字的支援。

注意:使用者 設定 editor.formatOnType 控制是否在使用者輸入時格式化原始程式碼。

Visual indicators for formatting as code is typed

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供輸入時格式化功能。它還需要告知用戶端應該在哪個字元上觸發格式化。moreTriggerCharacters 是選填的。

{
    ...
    "capabilities" : {
        "documentOnTypeFormattingProvider" : {
            "firstTriggerCharacter": "}",
            "moreTriggerCharacter": [";", ","]
        }
        ...
    }
}

此外,您的語言伺服器需要回應 textDocument/onTypeFormatting 請求。

直接實作

class GoOnTypingFormatter implements vscode.OnTypeFormattingEditProvider{
    public provideOnTypeFormattingEdits(
        document: vscode.TextDocument, position: vscode.Position,
        ch: string, options: vscode.FormattingOptions, token: vscode.CancellationToken):
        vscode.ProviderResult<vscode.TextEdit[]> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerOnTypeFormattingEditProvider(
            GO_MODE, new GoOnTypingFormatter()));
    ...
}

基本

不提供格式化支援。

進階

您應該始終傳回能達成格式化原始程式碼的最小文字編輯量。這對於確保診斷結果等標記能正確調整且不會丟失至關重要。

重新命名符號

允許使用者重新命名符號並更新對該符號的所有參考。

Rename a symbol and update all references to the new name

語言伺服器通訊協定 (Language Server Protocol)

在回應 initialize 方法時,您的語言伺服器需要宣告它提供重新命名功能。

{
    ...
    "capabilities" : {
        "renameProvider" : "true"
        ...
    }
}

此外,您的語言伺服器需要回應 textDocument/rename 請求。

直接實作

class GoRenameProvider implements vscode.RenameProvider {
    public provideRenameEdits(
        document: vscode.TextDocument, position: vscode.Position,
        newName: string, token: vscode.CancellationToken):
        Thenable<vscode.WorkspaceEdit> {
    ...
    }
}

export function activate(ctx: vscode.ExtensionContext): void {
    ...
    ctx.subscriptions.push(
        vscode.languages.registerRenameProvider(
            GO_MODE, new GoRenameProvider()));
    ...
}

基本

不提供重新命名支援。

進階

傳回需要執行的所有工作區編輯清單,例如所有包含該符號參考的檔案中所需的編輯。

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