程序化语言特性

编程语言功能是一组由 API 提供支持的智能编辑功能vscode.languages.*。在 Visual Studio Code 中提供动态语言功能有两种常见方法。我们以悬停为例:

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

正如您在上面看到的,vscode.languages.registerHoverProviderAPI 提供了一种向 JavaScript 文件提供悬停内容的简单方法。激活此扩展后,每当您将鼠标悬停在某些 JavaScript 代码上时,VS Code 都会查询所有HoverProviderJavaScript 并在悬停小部件中显示结果。下面的语言功能列表和图解 gif 为您提供了一种简单的方法来查找您的扩展需要哪种 VS Code API / LSP 方法。

另一种方法是实现使用语言服务器协议的语言服务器。它的工作方式是:

这个过程看起来比较复杂,但它提供了两个主要好处:

  • 语言服务器可以用任何语言编写
  • 语言服务器可以重复使用,为多个编辑器提供智能编辑功能

如需更深入的指南,请访问语言服务器扩展指南


语言特性列表

此列表包含每种语言功能的以下项目:

  • VS Code 中的语言功能图解
  • 相关 VS Code API
  • 相关LSP方法
VS代码API LSP法
createDiagnosticCollection 发布诊断
registerCompletionItemProvider 完成完成解决
registerHoverProvider 徘徊
registerSignatureHelpProvider 签名帮助
registerDefinitionProvider 定义
registerTypeDefinitionProvider 类型定义
registerImplementationProvider 执行
registerReferenceProvider 参考
registerDocumentHighlightProvider 文档亮点
registerDocumentSymbolProvider 文档符号
registerCodeActionsProvider 代码动作
registerCodeLensProvider CodeLensCodeLens Resolve
registerDocumentLinkProvider DocumentLinkDocumentLink 解析
registerColorProvider 文档颜色颜色呈现
registerDocumentFormattingEditProvider 格式化
registerDocumentRangeFormattingEditProvider 范围格式化
registerOnTypeFormattingEditProvider 类型格式化
registerRenameProvider 重命名准备重命名
registerFoldingRangeProvider 折叠范围

提供诊断

诊断是指示代码问题的一种方法。

诊断表明方法名称拼写错误

Language Server Protocol

您的语言服务器将textDocument/publishDiagnostics消息发送到语言客户端。该消息携带资源 URI 的诊断项数组。

注意:客户端不会向服务器请求诊断。服务器将诊断信息推送给客户端。

Direct Implementation

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);
    });
  })
}

基本的

为打开的编辑器报告诊断。至少,这需要在每次保存时发生。更好的是,诊断应该根据编辑器未保存的内容进行计算。

先进的

不仅针对打开的编辑器报告诊断,而且针对打开的文件夹中的所有资源报告诊断,无论它们是否曾经在编辑器中打开过。

显示代码完成建议

代码完成向用户提供上下文相关的建议。

编写代码时代码完成提示变量、方法和参数名称

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要声明它提供了补全,以及它是否支持该completionItem\resolve方法为计算的补全项提供附加信息。

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

Direct Implementation

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(), '.', '\"'));
    ...
}

基本的

您不支持解析提供程序。

先进的

您支持解析提供程序,为用户选择的完成建议计算附加信息。此信息与所选项目一起显示。

显示悬停

悬停显示有关鼠标光标下方的符号/对象的信息。这通常是符号的类型和描述。

将鼠标悬停在工作区和方法上时显示有关它们的详细信息

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要宣布它提供悬停。

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

此外,您的语言服务器需要响应该textDocument/hover请求。

Direct Implementation

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()));
    ...
}

基本的

显示类型信息并包含文档(如果有)。

先进的

以与代码着色相同的方式对方法签名进行着色。

函数和方法签名帮助

当用户输入函数或方法时,显示有关正在调用的函数/方法的信息。

显示有关 getPackageInfo 方法的信息,包括必要的参数

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要声明它提供签名帮助。

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

此外,您的语言服务器需要响应该textDocument/signatureHelp请求。

Direct Implementation

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(), '(', ','));
    ...
}

基本的

确保签名帮助包含函数或方法的参数的文档。

先进的

没有什么额外的。

显示符号的定义

允许用户在使用变量/函数/方法的地方查看变量/函数/方法的定义。

右键单击变量、函数或方法并选择“Go to Definition”以跳转到定义

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要声明它提供了 goto-definition 位置。

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

此外,您的语言服务器需要响应该textDocument/definition请求。

Direct Implementation

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()));
    ...
}

基本的

如果符号是矛盾的,您可以显示多个定义。

先进的

没有什么额外的。

查找对符号的所有引用

允许用户查看使用某个变量/函数/方法/符号的所有源代码位置。

右键单击并选择“查找所有引用”以突出显示使用该符号的所有位置

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要声明它提供符号引用位置。

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

此外,您的语言服务器需要响应该textDocument/references请求。

Direct Implementation

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 和范围)。

先进的

没有什么额外的。

突出显示文档中出现的所有符号

允许用户查看打开的编辑器中出现的所有符号。

选择一个符号以突出显示所有出现的情况

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要声明它提供符号文档位置。

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

此外,您的语言服务器需要响应该textDocument/documentHighlight请求。

Direct Implementation

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()));
    ...
}

基本的

您返回编辑器文档中找到引用的范围。

先进的

没有什么额外的。

显示文档中的所有符号定义

允许用户快速导航到打开的编辑器中的任何符号定义。

使用 @ 导航到打开的编辑器中的符号定义

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要声明它提供符号文档位置。

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

此外,您的语言服务器需要响应该textDocument/documentSymbol请求。

Direct Implementation

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 打开的文件夹(工作区)中任意位置的符号定义。

使用 # 导航到工作区中的符号定义

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要声明它提供全局符号位置。

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

此外,您的语言服务器需要响应该workspace/symbol请求。

Direct Implementation

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()));
    ...
}

基本的

返回打开的文件夹中源代码定义的所有符号。定义变量、函数、类、方法等符号的种类。

先进的

没有什么额外的。

针对错误或警告可能采取的措施

在错误或警告旁边为用户提供可能的纠正措施。如果可以采取措施,错误或警告旁边会出现一个灯泡。当用户单击灯泡时,将显示可用代码操作的列表。

选择灯泡以查看可用代码操作的列表

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要声明它提供代码操作。

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

此外,您的语言服务器需要响应该textDocument/codeAction请求。

Direct Implementation

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()));
    ...
}

基本的

提供代码操作以纠正错误/警告操作。

先进的

此外,还提供源代码操作操作,例如重构。例如,提取方法

CodeLens - 显示源代码中可操作的上下文信息

为用户提供可操作的上下文信息,这些信息散布在源代码中。

CodeLens 提供上下文

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要声明它提供了 CodeLens 结果以及它是否支持codeLens\resolve将 CodeLens 与其命令绑定的方法。

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

此外,您的语言服务器需要响应该textDocument/codeLens请求。

Direct Implementation

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 结果绑定到命令codeLens/resolve

显示颜色装饰器

允许用户预览和修改文档中的颜色。

显示颜色选择器

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要声明它提供颜色信息。

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

此外,您的语言服务器需要响应textDocument/documentColortextDocument/colorPresentation请求。

Direct Implementation

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(...))。

先进的

没有什么额外的。

在编辑器中格式化源代码

为用户提供格式化整个文档的支持。

右键单击并选择格式代码

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要声明它提供文档格式。

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

此外,您的语言服务器需要响应该textDocument/formatting请求。

Direct Implementation

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()));
    ...
}

基本的

不提供格式化支持。

先进的

您应该始终返回导致源代码格式化的尽可能最小的文本编辑。这对于确保诊断结果等标记得到正确调整且不会丢失至关重要。

在编辑器中设置所选行的格式

为用户提供对文档中选定行范围的格式设置的支持。

选择行,右键单击,然后选择格式代码

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要声明它为行范围提供格式化支持。

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

此外,您的语言服务器需要响应该textDocument/rangeFormatting请求。

Direct Implementation

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控制源代码是否在用户键入时格式化。

键入代码时用于格式化的视觉指示器

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要声明它在用户键入时提供格式。它还需要告诉客户端应该触发哪些字符格式。moreTriggerCharacters是可选的。

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

此外,您的语言服务器需要响应该textDocument/onTypeFormatting请求。

Direct Implementation

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()));
    ...
}

基本的

不提供格式化支持。

先进的

您应该始终返回导致源代码格式化的尽可能最小的文本编辑。这对于确保诊断结果等标记得到调整、纠正且不丢失至关重要。

重命名符号

允许用户重命名符号并更新对该符号的所有引用。

重命名符号并将所有引用更新为新名称

Language Server Protocol

在对该方法的响应中initialize,您的语言服务器需要声明它提供重命名。

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

此外,您的语言服务器需要响应该textDocument/rename请求。

Direct Implementation

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()));
    ...
}

基本的

不提供重命名支持。

先进的

返回需要执行的所有工作区编辑的列表,例如包含对该符号的引用的所有文件的所有编辑。