程序化语言特性
编程语言功能是一组由 API 提供支持的智能编辑功能vscode.languages.*
。在 Visual Studio Code 中提供动态语言功能有两种常见方法。我们以悬停为例:
vscode.languages.registerHoverProvider('javascript', {
provideHover(document, position, token) {
return {
contents: ['Hover Content']
};
}
});
正如您在上面看到的,vscode.languages.registerHoverProvider
API 提供了一种向 JavaScript 文件提供悬停内容的简单方法。激活此扩展后,每当您将鼠标悬停在某些 JavaScript 代码上时,VS Code 都会查询所有HoverProvider
JavaScript 并在悬停小部件中显示结果。下面的语言功能列表和图解 gif 为您提供了一种简单的方法来查找您的扩展需要哪种 VS Code API / LSP 方法。
另一种方法是实现使用语言服务器协议的语言服务器。它的工作方式是:
- 扩展为 JavaScript 提供了语言客户端和语言服务器。
- 语言客户端与任何其他 VS Code 扩展一样,在 Node.js 扩展主机上下文中运行。当它被激活时,它会在另一个进程中生成语言服务器,并通过语言服务器协议与其进行通信。
- 将鼠标悬停在 VS Code 中的 JavaScript 代码上
- VS Code 通知语言客户端悬停
- 语言客户端向语言服务器查询悬停结果并将其发送回 VS Code
- VS Code 在悬停小部件中显示悬停结果
这个过程看起来比较复杂,但它提供了两个主要好处:
- 语言服务器可以用任何语言编写
- 语言服务器可以重复使用,为多个编辑器提供智能编辑功能
如需更深入的指南,请访问语言服务器扩展指南。
语言特性列表
此列表包含每种语言功能的以下项目:
- VS Code 中的语言功能图解
- 相关 VS Code API
- 相关LSP方法
提供诊断
诊断是指示代码问题的一种方法。
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()));
...
}
基本的
显示类型信息并包含文档(如果有)。
先进的
以与代码着色相同的方式对方法签名进行着色。
函数和方法签名帮助
当用户输入函数或方法时,显示有关正在调用的函数/方法的信息。
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(), '(', ','));
...
}
基本的
确保签名帮助包含函数或方法的参数的文档。
先进的
没有什么额外的。
显示符号的定义
允许用户在使用变量/函数/方法的地方查看变量/函数/方法的定义。
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 - 显示源代码中可操作的上下文信息
为用户提供可操作的上下文信息,这些信息散布在源代码中。
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/documentColor
和textDocument/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()));
...
}
基本的
不提供重命名支持。
先进的
返回需要执行的所有工作区编辑的列表,例如包含对该符号的引用的所有文件的所有编辑。