程序化语言特性
程序化语言特性是一系列由 vscode.languages.*
API 提供支持的智能编辑功能。在 Visual Studio Code 中提供动态语言特性有两种常见方式。我们以悬停信息为例
vscode.languages.registerHoverProvider('javascript', {
provideHover(document, position, token) {
return {
contents: ['Hover Content']
};
}
});
如上所述,vscode.languages.registerHoverProvider
API 提供了一种轻松为 JavaScript 文件提供悬停内容的方式。此扩展激活后,每当您将鼠标悬停在某些 JavaScript 代码上时,VS Code 都会查询所有 JavaScript 的 HoverProvider
并将结果显示在悬停小组件中。语言特性列表和下面的图示 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 方法
提供诊断信息
诊断是一种指示代码问题的方式。
语言服务器协议
您的语言服务器将 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);
});
})
}
基本
报告打开的编辑器的诊断信息。最少,这需要在每次保存时发生。更好的是,诊断信息应基于编辑器中未保存的内容计算。
高级
不仅报告打开的编辑器的诊断信息,还报告打开文件夹中所有资源的诊断信息,无论这些资源是否在编辑器中打开过。
显示代码补全建议
代码补全向用户提供上下文敏感的建议。
语言服务器协议
在对 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 提供程序。
高级
您支持 resolve 提供程序,它们为用户选择的补全建议计算额外信息。此信息与选定项一起显示。
显示悬停信息
悬停信息显示鼠标光标下方的符号/对象信息。这通常是符号的类型和描述。
语言服务器协议
在对 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()));
...
}
基本
显示类型信息,如果可用则包含文档。
高级
以与代码高亮相同的方式高亮方法签名。
帮助显示函数和方法签名
当用户输入函数或方法时,显示有关正在调用的函数/方法的信息。
语言服务器协议
在对 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(), '(', ','));
...
}
基本
确保签名帮助包含函数或方法参数的文档。
高级
无额外要求。
显示符号定义
允许用户在使用变量/函数/方法的位置查看变量/函数/方法的定义。
语言服务器协议
在对 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()));
...
}
基本
如果一个符号是歧义的,您可以显示多个定义。
高级
无额外要求。
查找符号的所有引用
允许用户查看特定变量/函数/方法/符号在源代码中使用的所有位置。
语言服务器协议
在对 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 和范围)。
高级
无额外要求。
高亮显示文档中符号的所有出现位置
允许用户在打开的编辑器中查看符号的所有出现位置。
语言服务器协议
在对 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()));
...
}
基本
您返回在编辑器文档中找到引用的范围。
高级
无额外要求。
显示文档中的所有符号定义
允许用户快速导航到打开的编辑器中的任何符号定义。
语言服务器协议
在对 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 中打开的文件夹(工作区)中的任何符号定义。
语言服务器协议
在对 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()));
...
}
基本
返回打开文件夹中源代码定义的所有符号。定义符号的种类,例如变量、函数、类、方法等。
高级
无额外要求。
错误或警告的可能操作
在错误或警告旁边为用户提供可能的纠正操作。如果操作可用,错误或警告旁边会出现一个灯泡。当用户点击灯泡时,会显示可用代码操作列表。
语言服务器协议
在对 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()));
...
}
基本
为错误/警告纠正操作提供 Code Actions。
高级
此外,提供源代码操作操作,例如重构。例如,提取方法。
CodeLens - 在源代码中显示可操作的上下文信息
为用户提供穿插在源代码中的可操作上下文信息。
语言服务器协议
在对 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 结果绑定到命令。
显示颜色装饰器
允许用户预览和修改文档中的颜色。
语言服务器协议
在对 initialize
方法的响应中,您的语言服务器需要宣布它提供颜色信息。
{
...
"capabilities" : {
"colorProvider" : "true"
...
}
}
此外,您的语言服务器需要响应 textDocument/documentColor
和 textDocument/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(...))提供颜色表示。
高级
无额外要求。
在编辑器中格式化源代码
为用户提供格式化整个文档的支持。
语言服务器协议
在对 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()));
...
}
基本
不提供格式化支持。
高级
您应该始终返回产生格式化源代码的最小可能文本编辑。这对于确保诸如诊断结果之类的标记正确调整且不丢失至关重要。
格式化编辑器中的选定行
为用户提供格式化文档中选定行范围的支持。
语言服务器协议
在对 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
控制用户键入时是否格式化源代码。
语言服务器协议
在对 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()));
...
}
基本
不提供格式化支持。
高级
您应该始终返回产生格式化源代码的最小可能文本编辑。这对于确保诸如诊断结果之类的标记正确调整且不丢失至关重要。
重命名符号
允许用户重命名符号并更新对该符号的所有引用。
语言服务器协议
在对 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()));
...
}
基本
不提供重命名支持。
高级
返回需要执行的所有工作区编辑列表,例如包含符号引用的所有文件中的所有编辑。