找回密码
 会员注册
查看: 19|回复: 0

VisualStudioCode插件开发中的语言功能

[复制链接]

2万

主题

0

回帖

6万

积分

超级版主

积分
64125
发表于 2024-10-11 21:46:56 | 显示全部楼层 |阅读模式
本文作者为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 则是定义了一个 codelensProvider 供 extension.ts 注册时使用。extension.ts 文件内容如下://Themodule'vscode'containstheVSCodeextensibilityAPI//Importthemoduleandreferenceitwiththealiasvscodeinyourcodebelowimport{ExtensionContext,languages,commands,Disposable,workspace,window}from'vscode';import{CodelensProvider}from'./CodelensProvider';//thismethodiscalledwhenyourextensionisactivated//yourextensionisactivatedtheveryfirsttimethecommandisexecutedletdisposablesisposable[]=[];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}`);});}//thismethodiscalledwhenyourextensionisdeactivatedexportfunctiondeactivate(){if(disposables){disposables.forEach(item=>item.dispose());}disposables=[];}文件主要做了两件事情:registerCodeLensProvider 注册 ProviderregisterCommand 注册命令这里先来看下 registerCodeLensProvider ,下个再说 registerCommand。registerCodeLensProviderlanguages.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{......}publicresolveCodeLens(codeLens:vscode.CodeLens,token:vscode.CancellationToken){......}}CodeLensProvider 需要提供两个方法provideCodeLensesresolveCodeLensprovideCodeLenses展开看下代码:publicprovideCodeLenses(document:vscode.TextDocument,token:vscode.CancellationToken):vscode.CodeLens[]|Thenable{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 要求返回一个数组、 undefined 或 null。数组项要是 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-END-如果您关注前端+AI 相关领域可以扫码进群交流添加小编微信进群关于奇舞团奇舞团是 360 集团最大的大前端团队,非常重视人才培养,有工程师、讲师、翻译官、业务接口人、团队 Leader 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-26 13:12 , Processed in 0.332597 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表