跳转到定义

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

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

vscode JavaScript 怎么跳转到指定函数 vscode定义跳转_json

代码以下:node

/**
* 跳转到定义示例,本示例支持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:json
"activationEvents": [
"onLanguage:json"
],

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

1.1. 高亮显示范围

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

vscode JavaScript 怎么跳转到指定函数 vscode定义跳转_vscode打开自动提示_02

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

自动补全

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

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

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

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

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

vscode JavaScript 怎么跳转到指定函数 vscode定义跳转_ide_03

实现代码以下:

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
}, '.'));
};

悬停提示

从上面的跳转到定义咱们能够看到,虽然咱们只是定义了如何调整,到按住Ctrl键可是不点击的时候,vscode默认就会帮咱们预览一部份内容做为提示,除此以外,若是想得到更多的提示,咱们还能够经过vscode.languages.registerHoverProvider命令来实现。

下面咱们依然经过package.json中依赖跳转的例子来演示如何实现一个自定义hover,以下标红的内容是咱们本身实现的,当鼠标停在package.json的dependencies或者devDependencies时,自动显示对应包的名称、版本号和许可协议:

vscode JavaScript 怎么跳转到指定函数 vscode定义跳转_ide_04

如何实现的呢?也很简单,咱们直接上代码:

const vscode = require('vscode');
const path = require('path');
const fs = require('fs');
/**
* 鼠标悬停提示,当鼠标停在package.json的dependencies或者devDependencies时,
* 自动显示对应包的名称、版本号和许可协议
* @param {*} document
* @param {*} position
* @param {*} token
*/
function provideHover(document, position, token) {
const fileName = document.fileName;
const workDir = path.dirname(fileName);
const word = document.getText(document.getWordRangeAtPosition(position));
if (/\/package\.json$/.test(fileName)) {
console.log('进入provideHover方法');
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)) {
const content = require(destPath);
console.log('hover已生效');
// hover内容支持markdown语法
return new vscode.Hover(`* **名称**:${content.name}\n* **版本**:${content.version}\n* **许可协议**:${content.license}`);
}
}
}
}
module.exports = function(context) {
// 注册鼠标悬停提示
context.subscriptions.push(vscode.languages.registerHoverProvider('json', {
provideHover
}));
};

有些时候某个字段可能自己已经有提示内容了,若是咱们仍然给它注册了hover的实现的话,那么vscode会自动将多个hover内容合并一块儿显示。