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

简介: 更多文章请戳[VSCode插件开发全攻略系列目录导航](https://www.atatech.org/articles/121864)。 # 跳转到定义 跳转到定义其实很简单,通过`vscode.languages.registerDefinitionProvider`注册一个`provider`,这个`provider`如果返回了`new vscode.Location()`就表示

更多文章请戳VSCode插件开发全攻略系列目录导航

跳转到定义

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

为了示例更加有意义,我在这里写了一个支持package.jsondependenciesdevDependencies跳转到对应依赖包的例子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个参数:

  • 第一个是要关联的文件类型;
  • 第二个是一个对象,里面必须包含provideCompletionItemsresolveCompletionItem这2个方法;
  • 第三个是一个可选的触发提示的字符列表;

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

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

悬停提示

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

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

_W828xH716_

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

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内容合并一起显示。

目录
相关文章
|
10月前
|
自然语言处理 API C++
阿里通义推出SmartVscode插件,自然语言控制VS Code,轻松开发应用,核心技术开源!
SmartVscode插件深度解析:自然语言控制VS Code的革命性工具及其开源框架App-Controller
1481 1
阿里通义推出SmartVscode插件,自然语言控制VS Code,轻松开发应用,核心技术开源!
|
6月前
|
人工智能 开发工具 C++
利用通义灵码AI在VS Code中快速开发扫雷游戏:Qwen2.5-Max模型的应用实例
本文介绍了如何利用阿里云通义灵码AI程序员的Qwen2.5-Max模型,在VS Code中一键生成扫雷小游戏。通过安装通义灵码插件并配置模型,输入指令即可自动生成包含游戏逻辑与UI设计的Python代码。生成的游戏支持难度选择,运行稳定无Bug。实践表明,AI工具显著提升开发效率,但人机协作仍是未来趋势。建议开发者积极拥抱新技术,同时不断提升自身技能以适应行业发展需求。
22463 18
利用通义灵码AI在VS Code中快速开发扫雷游戏:Qwen2.5-Max模型的应用实例
|
5月前
|
JavaScript 前端开发 程序员
甚至用不了五分钟就能学会vscode插件开发
本文介绍了VSCode插件的开发流程,从创建项目到最终发布。首先通过安装`yo`和`generator-code`脚手架工具初始化项目,选择JavaScript语言配置基础信息。接着,在`extension.js`中实现业务逻辑,例如将中文“变量”替换为“var”。通过F5进入调试模式验证功能。完成后使用`vsce`工具进行打包,解决可能遇到的版本不兼容或README文档问题。最后生成`.vsix`文件,可通过VSCode的“从VSIX安装”加载插件,实现开发闭环。进一步可将插件发布至官方市场供更多开发者使用。
|
8月前
|
JavaScript 前端开发 jenkins
抛弃node和vscode,如何用记事本开发出一个完整的vue前端项目
本文探讨了在不依赖Node和VSCode的情况下,仅使用记事本和浏览器开发一个完整的Vue3前端项目的方法。通过CDN引入Vue、Vue Router、Element-UI等库,直接编写HTML文件实现页面功能,展示了前端开发的本质是生成HTML。虽然日常开发离不开现代工具,但掌握这种基础方法有助于快速实现想法或应对特殊环境限制。文章还介绍了如何用Node简单部署HTML文件到服务器,提供了一种高效、轻量的开发思路。
172 10
|
9月前
|
Linux Go iOS开发
怎么禁用 vscode 中点击 go 包名时自动打开浏览器跳转到 pkg.go.dev
本文介绍了如何在 VSCode 中禁用点击 Go 包名时自动打开浏览器跳转到 pkg.go.dev 的功能。通过将 gopls 的 `ui.navigation.importShortcut` 设置为 "Definition",可以实现仅跳转到定义处而不打开链接。具体操作步骤包括:打开设置、搜索 gopls、编辑 settings.json 文件并保存更改,最后重启 VSCode 使设置生效。
340 8
怎么禁用 vscode 中点击 go 包名时自动打开浏览器跳转到 pkg.go.dev
|
10月前
|
开发工具 C++ git
利用VS Code提升开发效率的五大插件推荐
本文推荐了五款能显著提升开发效率的VS Code插件:ESLint用于代码质量和风格检查;Prettier自动格式化代码;GitLens增强Git功能;Live Server提供前端实时预览;Docker支持容器管理。
|
11月前
|
网络安全 Docker 容器
VScode远程服务器之远程 远程容器 进行开发(五)
VScode远程服务器之远程 远程容器 进行开发(五)
381 1
|
11月前
|
前端开发 JavaScript 编译器
2024最新VSCode实用插件推荐,开发效率遥遥领先!超全面,快收藏~
【10月更文挑战第11天】2024最新VSCode实用插件推荐,开发效率遥遥领先!超全面,快收藏~
2233 0
2024最新VSCode实用插件推荐,开发效率遥遥领先!超全面,快收藏~
|
11月前
|
IDE 开发工具
Vscode的远程开发之VScode优势(一)
Vscode的远程开发之VScode优势(一)
181 1
|
11月前
|
Kubernetes 网络安全 容器
VScode远程服务器进行开发(三)
VScode远程服务器进行开发(三)
251 0

热门文章

最新文章