VSCode插件开发全攻略(五)跳转到定义、自动补全、悬停提示

跳转到定义其实很简单,通过vscode.languages.registerDefinitionProvider注册一个provider,这个provider如果返回了new vscode.Location()就表示当前光标所在单词支持跳转,并且跳转到对应location。

为了示例更加有意义,我在这里写了一个支持package.json中dependencies、devDependencies跳转到对应依赖包的例子jump-to-definition.js(当然我们这里只是很简单的实现,没有考虑特殊情况,直接从node_modules文件夹下面去找):

W618xH405

代码如下:

/** * 跳转到定义示例,本示例支持package.json中dependencies、devDependencies跳转到对应依赖包。 */ const vscode = require('vscode'); const path = require('path'); const fs = require('fs'); const util = require('./util'); /** * 查找文件定义的provider,匹配到了就return一个location,否则不做处理 * 最终效果是,当按住Ctrl键时,如果return了一个location,字符串就会变成一个可以点击的链接,否则无任何效果 * @param {*} document * @param {*} position * @param {*} token */ function provideDefinition(document, position, token) { const fileName = document.fileName; const workDir = path.dirname(fileName); const word = document.getText(document.getWordRangeAtPosition(position)); const line = document.lineAt(position); const projectPath = util.getProjectPath(document); console.log('====== 进入 provideDefinition 方法 ======'); console.log('fileName: ' + fileName); // 当前文件完整路径 console.log('workDir: ' + workDir); // 当前文件所在目录 console.log('word: ' + word); // 当前光标所在单词 console.log('line: ' + line.text); // 当前光标所在行 console.log('projectPath: ' + projectPath); // 当前工程目录 // 只处理package.json文件 if (/\/package\.json$/.test(fileName)) { console.log(word, line.text); const json = document.getText(); if (new RegExp(`"(dependencies|devDependencies)":\\s*?\\{[\\s\\S]*?${word.replace(/\//g, '\\/')}[\\s\\S]*?\\}`, 'gm').test(json)) { let destPath = `${workDir}/node_modules/${word.replace(/"/g, '')}/package.json`; if (fs.existsSync(destPath)) { // new vscode.Position(0, 0) 表示跳转到某个文件的第一行第一列 return new vscode.Location(vscode.Uri.file(destPath), new vscode.Position(0, 0)); } } } } module.exports = function(context) { // 注册如何实现跳转到定义,第一个参数表示仅对json文件生效 context.subscriptions.push(vscode.languages.registerDefinitionProvider(['json'], { provideDefinition })); };

注意不要忘了修改activationEvents:

"activationEvents": [ "onLanguage:json" ],

new vscode.Location接收2个参数,第一个是要跳转到文件的路径,第二个是跳转之后光标所在位置,接收Range或者Position对象,Position对象的初始化接收2个参数,行row和列col。

高亮显示范围

这里有一个问题我一直没找到解决方案,如下图所示:

W944xH278

当按住Ctrl跳转的时候,虽然可以控制跳转目标位置,但是却无法控制高亮显示的范围,下图我本应该让page/video/list.html全部变成蓝色的,但是默认却只能以单词为粒度变色,这个问题我找了很久官方文档就是没找到解决办法,如果大家有知道的欢迎评论指出。

自动补全

通过vscode.languages.registerCompletionItemProvider方法注册自动完成实现,接收3个参数:

第一个是要关联的文件类型;

第二个是一个对象,里面必须包含provideCompletionItems和resolveCompletionItem这2个方法;

第三个是一个可选的触发提示的字符列表;

这里我们实现这样一个例子,当输入this.dependencies.xxx时自动把package.json中的依赖全部带出来,包括dependencies、devDependencies,就像这样:

W1082xH412

实现代码如下:

const vscode = require('vscode'); const util = require('./util'); /** * 自动提示实现,这里模拟一个很简单的操作 * 当输入 this.dependencies.xxx时自动把package.json中的依赖带出来 * 当然这个例子没啥实际意义,仅仅是为了演示如何实现功能 * @param {*} document * @param {*} position * @param {*} token * @param {*} context */ function provideCompletionItems(document, position, token, context) { const line = document.lineAt(position); const projectPath = util.getProjectPath(document); // 只截取到光标位置为止,防止一些特殊情况 const lineText = line.text.substring(0, position.character); // 简单匹配,只要当前光标前的字符串为`this.dependencies.`都自动带出所有的依赖 if(/(^|=| )\w+\.dependencies\.$/g.test(lineText)) { const json = require(`${projectPath}/package.json`); const dependencies = Object.keys(json.dependencies || {}).concat(Object.keys(json.devDependencies || {})); return dependencies.map(dep => { // vscode.CompletionItemKind 表示提示的类型 return new vscode.CompletionItem(dep, vscode.CompletionItemKind.Field); }) } } /** * 光标选中当前自动补全item时触发动作,一般情况下无需处理 * @param {*} item * @param {*} token */ function resolveCompletionItem(item, token) { return null; } module.exports = function(context) { // 注册代码建议提示,只有当按下“.”时才触发 context.subscriptions.push(vscode.languages.registerCompletionItemProvider('javascript', { provideCompletionItems, resolveCompletionItem }, '.')); }; 悬停提示

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwxpgx.html