Posted in

Visual Studio Code 插件开发中的语言功能_AI阅读总结 — 包阅AI

包阅导读总结

1.

关键词:Visual Studio Code、插件开发、CodeLens、语言功能、API

2.

总结:本文以 CodeLens 功能为例,讲解如何使用 Visual Studio Code 插件开发中的语言功能,介绍了程序化语言功能的调用方式,通过分析示例项目的关键代码,详细说明了实现 CodeLens 功能的步骤及相关配置。

3.

主要内容:

– Visual Studio Code 插件开发中的语言功能

– 语言功能可提供智能编辑能力,本身不提供内置语言支持,而是提供 API 实现丰富功能

– 语言功能分类

– 声明式语言功能

– 程序化语言功能

– CodeLens 功能

– 是实用功能,可提供代码上下文信息和快速操作能力

– 实现方式

– 通过 vscode.languages. API 调用

– 启动支持语言服务器协议的语言服务器

– 实现 CodeLens 功能的示例

– extension.ts 文件:注册 Provider 及相关命令

– CodelensProvider.ts 文件:定义 CodeLensProvider

– 命令注册与控制

– 在代码中注册命令并添加响应函数

– 在 package.json 中绑定命令标识

– 在设置中控制 CodeLens 的显示

思维导图:

文章地址:https://mp.weixin.qq.com/s/dvTFEYPaY4xA-l4ZLo0M7Q

文章来源:mp.weixin.qq.com

作者:崔丽

发布时间:2024/9/11 2:54

语言:中文

总字数:2104字

预计阅读时间:9分钟

评分:87分

标签:Visual Studio Code,插件开发,CodeLens,前端开发,API 调用


以下为原文内容

本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com

本文作者为360奇舞团前端开发工程师

本文将以 CodeLens 功能为例,通过 vscode.languages.* API 调用来讲解如何使用 Visual Studio Code 插件开发中的语言功能(Language Feature)。

Visual Studio Code 的语言功能可以提供智能编辑能力。VS Code 本身并不提供内置的语言支持,而是提供了一组 API 来实现丰富的语言功能。例如,VS Code 包含一个 HTML 扩展,使 VS Code 能够为 HTML 文件显示语法高亮。

CodeLens 则是 Visual Studio Code 中一项非常实用的功能,它可以为开发者提供关于代码的上下文信息快速操作的能力。

CodeLens 在编辑器中的特定代码行上方显示可操作的、与上下文相关的信息。这些信息可以是代码引用次数、单元测试结果、代码更改历史、Bug 追踪、任务关联等。

如下图示例:

VS Code 的语言功能(Language Feature)

语言功能大致分为两类:

声明式语言功能

程序化语言功能

本文的例子 CodeLens 功能属于程序化语言功能

程序化语言功能通常由语言服务器提供支持,语言服务器是一个通过分析项目代码以提供动态功能的程序。

有两种方法可以调用程序化语言功能:

1. 通过 vscode.languages.* API 调用。

2. 通过启动一个语言服务器,这个服务器需要支持语言服务器协议。

下面我们使用第一种方式实现 CodeLens 功能。

1. 使用语言服务 API 实现 CodeLens 功能

官方给了一个简单的例子 codelens-sample[1]

官方例子演示:

启动 codelens-sample 项目

首先,从地址将示例插件下载到本地,使用命令npm install安装依赖。然后在调试视图中运行插件,就会在新打开的 VS code 窗口中运行插件了。

可以看到 codelens-sample 示例插件为每一行代码都添加了 CodeLens 功能。

codelens-sample 项目的主要文件有两个:

  • extension.ts 文件的任务是注册 Provider ,以及注册相关命令(registerCommand)。
  • CodelensProvider.ts 则是定义了一个 codelensProviderextension.ts 注册时使用。

extension.ts 文件

内容如下:

//Themodule'vscode'containstheVSCodeextensibilityAPI
//Importthemoduleandreferenceitwiththealiasvscodeinyourcodebelow
import{ExtensionContext,languages,commands,Disposable,workspace,window}from'vscode';
import{CodelensProvider}from'./CodelensProvider';

//thismethodiscalledwhenyourextensionisactivated
//yourextensionisactivatedtheveryfirsttimethecommandisexecuted

letdisposables:Disposable[]=[];

exportfunctionactivate(context:ExtensionContext){
constcodelensProvider=newCodelensProvider();

languages.registerCodeLensProvider("*",codelensProvider);

commands.registerCommand("codelens-sample.enableCodeLens",()=>{
workspace.getConfiguration("codelens-sample").update("enableCodeLens",true,true);
});

commands.registerCommand("codelens-sample.disableCodeLens",()=>{
workspace.getConfiguration("codelens-sample").update("enableCodeLens",false,true);
});

commands.registerCommand("codelens-sample.codelensAction",(args:any)=>{
window.showInformationMessage(`CodeLensactionclickedwithargs=${args}`);
});
}

//thismethodiscalledwhenyourextensionisdeactivated
exportfunctiondeactivate(){
if(disposables){
disposables.forEach(item=>item.dispose());
}
disposables=[];
}

文件主要做了两件事情:

  • registerCodeLensProvider 注册 Provider

这里先来看下 registerCodeLensProvider ,下个标题再说 registerCommand

registerCodeLensProvider
languages.registerCodeLensProvider("*",codelensProvider)

注册时调用了 API languages.registerCodeLens

languages.registerCodeLensProvider 需要两个参数。

第一个参数是语言 ID,决定了我们注册的这个 Provider 会被应用于哪些类型的文件。* 表示所有文件都会被应用这个 Provider。

如果换成 typescript

languages.registerCodeLensProvider("typescript",codelensProvider);

我们就只能在 .ts 后缀的文件中看到 codelens

如果换成 ["typescript", "javascript"]

languages.registerCodeLensProvider(["typescript",'javascript'],codelensProvider);

则只能在 .ts.js 后缀的文件中看到 codelens。以此类推。

第二个参数要求是 CodeLensProvider 类型。这个 Provider 的作用就是在代码中以一横排的方式显示命令。

CodelensProvider.ts 文件

看下如何定义 CodelensProvider

import*asvscodefrom'vscode';

/**
*CodelensProvider
*/

exportclassCodelensProviderimplementsvscode.CodeLensProvider{

privatecodeLenses:vscode.CodeLens[]=[];
......

constructor(){
this.regex=/(.+)/g;

vscode.workspace.onDidChangeConfiguration((_)=>{
......
});
}

publicprovideCodeLenses(document:vscode.TextDocument,token:vscode.CancellationToken):vscode.CodeLens[]|Thenable<vscode.CodeLens[]>{
......
}

publicresolveCodeLens(codeLens:vscode.CodeLens,token:vscode.CancellationToken){
......
}
}

CodeLensProvider 需要提供两个方法

provideCodeLenses

展开看下代码:

publicprovideCodeLenses(document:vscode.TextDocument,token:vscode.CancellationToken):vscode.CodeLens[]|Thenable<vscode.CodeLens[]>{

if(vscode.workspace.getConfiguration("codelens-sample").get("enableCodeLens",true)){
this.codeLenses=[];
constregex=newRegExp(this.regex);
consttext=document.getText();
letmatches;
while((matches=regex.exec(text))!==null){
constline=document.lineAt(document.positionAt(matches.index).line);
constindexOf=line.text.indexOf(matches[0]);
constposition=newvscode.Position(line.lineNumber,indexOf);
constrange=document.getWordRangeAtPosition(position,newRegExp(this.regex));
if(range){
this.codeLenses.push(newvscode.CodeLens(range));
}
}
returnthis.codeLenses;
}
return[];
}

document 参数是指当前文档。通过 document.getText() 方法可以获取到文本内容。

consttext=document.getText();

然后将文档内容与定义的正则表达式进行匹配。

this.regex=/(.+)/g;
......
constregex=newRegExp(this.regex);
matches=regex.exec(text)

codelens-sample 示例之所以会在每一行都显示 codelens 就是因为在这里匹配到了每一行。

provideCodeLenses 要求返回一个数组、 undefinednull。数组项要是 CodeLens 实例。

this.codeLenses.push(newvscode.CodeLens(range))

上行代码中的 range 是指代码范围,这个范围不能超过一行。

最终每一个匹配到的代码上方都会出现 CodeLens 命令。

resolveCodeLens

命令行的内容则是在 resolveCodeLens 方法中添加的。

publicresolveCodeLens(codeLens:vscode.CodeLens,token:vscode.CancellationToken){
if(vscode.workspace.getConfiguration("codelens-sample").get("enableCodeLens",true)){
codeLens.command={
title:"Codelensprovidedbysampleextension",
tooltip:"Tooltipprovidedbysampleextension",
command:"codelens-sample.codelensAction",
arguments:["Argument1",false]
};
returncodeLens;
}
returnnull;
}

resolveCodeLens 的参数 codeLens 就是 provideCodeLenses 匹配到并返回的 codeLens 实例 。在 codeLens.command 中配置 UI 显示的命令文字。

command 各属性的含义如下:

  • command.title:在 UI 中显示的命令名
  • command.tooltip:在 UI 中展示的命令提示,如图:
  • command.command:实际命令处理程序的标识符(由 commands.registerCommand 进行注册)
  • command.arguments:命令处理程序的参数
registerCommand

现在回到上文 extension.ts 文件中提到的 registerCommand 命令注册。

command.command 中用到的程序标识符 codelens-sample.codelensAction 是在 extension.ts 文件中定义的:

commands.registerCommand("codelens-sample.codelensAction",(args:any,aa)=>{
window.showInformationMessage(`CodeLensactionclickedwithargs=${args}`);
});

args 参数就是通过 command.arguments 传过来的。

例子中点击命令会在右下角弹出一个提示,提示信息可以拿到参数值 Argument 1 并显示出来。

在命令面板中控制 codelens 是否显示


在 Visual Studio Code 中最常用的就是命令面板,那么如何在命令面板注册命令呢?

需要两个步骤:

第一步:在代码中注册命令,并添加响应函数。

第二步:在 package.json 中绑定命令标识。这样才能在命令面板中看到命令。

例子中是有做这个功能的。

可以注意到 extension.ts 文件中还注册了另外两个命令:

commands.registerCommand("codelens-sample.enableCodeLens",()=>{
workspace.getConfiguration("codelens-sample").update("enableCodeLens",true,true);
});

commands.registerCommand("codelens-sample.disableCodeLens",()=>{
workspace.getConfiguration("codelens-sample").update("enableCodeLens",false,true);
});

这里绑定了命令触发时的响应函数。两个命令都是在被触发时去改变 enableCodeLens 的值。在 CodelensProvider.ts 文件中 codelens 会被显示的前提条件就是 enableCodeLens 的值为 true 。这个值是是从哪里取的呢?会在后标题“在设置中控制 codelens 的显示”中说到。

接下来看 package.json 文件的配置:

{
"contributes":{
"commands":[
{
"title":"EnableCodeLens",
"command":"codelens-sample.enableCodeLens",
"category":"CodeLensSample"
},
{
"title":"DisableCodelens",
"command":"codelens-sample.disableCodeLens",
"category":"CodeLensSample"
}
]
}
}

字段含义如前边 commands 一样。

完成这两步,就可以在命令面板中控制 codelens 是否显示了。

在设置中控制 codelens 的显示

前文提到过 enableCodeLens,这个值就是从设置配置里面获取的。

设置配置也是在 package.json 配置的:

"contributes":{
"configuration":{
"properties":{
"codelens-sample.enableCodeLens":{
"type":"boolean",
"default":false
}
}
}
}

配置的的 enableCodeLens 属性会以 Enable Code Lens 的格式在配置面板中显示。

codelens-sample 则是一个命名空间。codelens-sample.enableCodeLens 的值可以通过:

workspace.getConfiguration("codelens-sample").get("enableCodeLens")

获取到,同时可以进行更改值等操作。

以上就是如何在 VS Code 添加 CodeLens 功能的简单例子,希望可以对你有帮助。

感谢阅读~

[1]

官方例子(codelens-sample): https://github.com/microsoft/vscode-extension-samples/tree/main/codelens-sample