老釜 發表於 2020-11-11 22:04:00

VSCode 微信小程序扩展开发

<h3>写在前面</h3>
<p>为什么要开发这个扩展呢,是因为微信开发者工具自身不支持页面引入组件的跳转,人工根据引入组件路径查看对应代码的方式,效率偏低。就形如这样的json文件,引入了多个组件,比如要查看</p>
<div>"/component/card-bg/card-bg"组件的源代码,通过人工检索目录查找对应文件,显然不如ctrl+鼠标左键单击一下这个组件路径,跳转到对应的组件文档,更高效。作为一个有追求的程序员。我们不能只做工具的使用者,我们要升级为工具的开发者。</div>
<p><img src="https://img2020.cnblogs.com/blog/861554/202011/861554-20201111205245355-446042379.png"></p>
<p>先看看效果,功能展示如下:按下ctrl+鼠标左键,就能实现下面5种跳转功能。</p>
<h4>1. app.json中的分包页面跳转</h4>
<p><img src="https://img2020.cnblogs.com/blog/861554/202011/861554-20201111203706912-569966203.gif"></p>
<h4>2. js文件中的wx.navigateTo,wx.redirectTo,wx.reLaunch跳转</h4>
<h2><img src="https://img2020.cnblogs.com/blog/861554/202011/861554-20201111203753029-1767652813.gif"></h2>
<h4>3. wxml文件中微信标签bindTap属性绑定的方法跳转</h4>
<h2><img src="https://img2020.cnblogs.com/blog/861554/202011/861554-20201111203832248-555790181.gif"></h2>
<h4>4. wxml文件中微信wxs标签src路径跳转</h4>
<h2><img src="https://img2020.cnblogs.com/blog/861554/202011/861554-20201111203931447-459478851.gif"></h2>
<h4>5. js文件中的ajax url跳转</h4>
<h2><img src="https://img2020.cnblogs.com/blog/861554/202011/861554-20201111204011677-9495549.gif"></h2>
<p>这个插件不仅可以在VSCode编辑器中使用,也可以在微信开发者工具中使用,效果一模一样。在微信开发者工具中的使用方法如下:</p>
<p>1. 微信开发者工具工具栏--编辑--&gt;打开编辑器扩展目录-将VSCode的扩展复制进去,假如你已经安装了某个扩展,这个扩展一般在C:\Users\xxx用户名\.vscode\extensions路径下。</p>
<p>2.&nbsp;微信开发者工具工具栏--编辑--&gt;管理编辑器扩展, 将VSCode扩展ID添加到扩展列表。扩展ID的查找方式见下图。</p>
<p><img src="https://img2020.cnblogs.com/blog/861554/202011/861554-20201111210715072-321331748.png"></p>
<p>&nbsp;3. 重启微信开发者工具。</p>
<h3>&nbsp;</h3>
<h3>如何开发出这样的VSCode 微信小程序扩展?</h3>
<p>step1 安装vscode扩展开发脚手架yo,generator-code和vsce</p>
<div class="cnblogs_code">
<pre>npm <span style="color: rgba(0, 0, 255, 1)">install</span> -g cnpm --registry=https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">registry.npm.taobao.org<br></span></pre>
<pre>cnpm install -g yo generator-code vsce</pre>
</div>
<p>step2 用yo初始化扩展项目</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">yo code
</span>? ==========================================================================<span style="color: rgba(0, 0, 0, 1)">
We</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">re constantly looking for ways to make yo better!</span>
May we anonymously report usage statistics to improve the tool over <span style="color: rgba(0, 0, 255, 1)">time</span>?<span style="color: rgba(0, 0, 0, 1)">
More </span><span style="color: rgba(0, 0, 255, 1)">info</span>: https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">github.com/yeoman/insight &amp; </span><span style="color: rgba(0, 128, 0, 1); text-decoration: underline">http://yeoman.io</span>
==========================================================================<span style="color: rgba(0, 0, 0, 1)"> No

   _</span>-----<span style="color: rgba(0, 0, 0, 1)">_   ╭──────────────────────────╮
    </span>|       |<span style="color: rgba(0, 0, 0, 1)">    │   Welcome to the Visual│
    </span>|--(o)--|<span style="color: rgba(0, 0, 0, 1)">    │   Studio Code Extension│
   `</span>---------´   │      generator!<span style="color: rgba(0, 0, 0, 1)">      │
    ( _´U`_ )    ╰──────────────────────────╯
    </span>/___A___\   /
   |~|<span style="color: rgba(0, 0, 0, 1)">
   __</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">.___.</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">__
´   `</span>|<span style="color: rgba(0, 0, 0, 1)">° ´ Y `

</span>? What type of extension <span style="color: rgba(0, 0, 255, 1)">do</span> you want to create?<span style="color: rgba(0, 0, 0, 1)"> New Extension (JavaScript)
</span>? What<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">s the name of your extension? wx-minipro-helper</span>
? What<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">s the identifier of your extension? wx-minipro-helper</span>
? What<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">s the description of your extension? 微信小程序开发助手,目前只实现了定义跳转功能</span>
? Enable JavaScript type checking <span style="color: rgba(0, 0, 255, 1)">in</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">jsconfig.json</span><span style="color: rgba(128, 0, 0, 1)">'</span>?<span style="color: rgba(0, 0, 0, 1)"> Yes
</span>? Initialize a git repository?<span style="color: rgba(0, 0, 0, 1)"> Yes
</span>? Which package manager to use? yarn</pre>
</div>
<p>step3&nbsp; 修改package.json文件</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">{
    </span>"name": "wx-minipro-helper"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"displayName": "wx-minipro-helper"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"description": "第一版本只实现了微信开发者工具不支持的 1.app.json内的页面路径跳转; 2. 页面下的json文件中引入的组件路径跳转; 3.页面文件下的js文件中的引入外部工具库跳转; 4.wx.navigateTo,wx.redirectTo,wx.reLaunch跳转; 5.wxml标签中绑定的方法跳转; 后续会添加自动补全,悬浮提示功能"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"version": "0.0.3"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"keywords"<span style="color: rgba(0, 0, 0, 1)">: [ // 添加搜索关键字
      </span>"wx"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"minipro"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"helper"<span style="color: rgba(0, 0, 0, 1)">
    ],
    </span>"publisher": "wph"<span style="color: rgba(0, 0, 0, 1)">, // 添加发布者
    </span>"icon": "src/images/icon.png"<span style="color: rgba(0, 0, 0, 1)">, // 添加图标至少是128*128
    </span>"main": "src/extension"<span style="color: rgba(0, 0, 0, 1)">, // 修改入口文件
    </span>"engines"<span style="color: rgba(0, 0, 0, 1)">: {
      </span>"vscode": "^1.5.0" // 依赖的vscode版本<span style="color: rgba(0, 0, 0, 1)">
    },
    </span>"categories"<span style="color: rgba(0, 0, 0, 1)">: [
      </span>"Other"<span style="color: rgba(0, 0, 0, 1)">
    ],
    </span>"activationEvents"<span style="color: rgba(0, 0, 0, 1)">: [ //启动时触发的命令
      </span>"*"<span style="color: rgba(0, 0, 0, 1)">
    ],
    </span>"contributes"<span style="color: rgba(0, 0, 0, 1)">: {
      </span>"commands"<span style="color: rgba(0, 0, 0, 1)">: [
            {
                </span>"command": "extension.wx-minipro-helper"<span style="color: rgba(0, 0, 0, 1)">,
                </span>"title": "wx-minipro-helper"<span style="color: rgba(0, 0, 0, 1)">
            }
      ]
    },
    </span>"scripts"<span style="color: rgba(0, 0, 0, 1)">: {
      </span>"lint": "eslint ."<span style="color: rgba(0, 0, 0, 1)">,
      </span>"pretest": "yarn run lint"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"test": "node ./test/runTest.js"<span style="color: rgba(0, 0, 0, 1)">
    },
    </span>"devDependencies"<span style="color: rgba(0, 0, 0, 1)">: {
      </span>"@types/glob": "^7.1.3"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"@types/mocha": "^8.0.0"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"@types/node": "^12.11.7"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"@types/vscode": "^1.5.0"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"eslint": "^7.9.0"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"fs": "^0.0.1-security"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"glob": "^7.1.6"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"mocha": "^8.1.3"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"os": "^0.1.1"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"path": "^0.12.7"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"typescript": "^4.0.2"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"vscode": "^1.1.37"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"vscode-test": "^1.4.0"<span style="color: rgba(0, 0, 0, 1)">
    },
    </span>"bugs"<span style="color: rgba(0, 0, 0, 1)">: {
      </span>"url": "https://github.com/wph/wx-minipro-helper/issues"<span style="color: rgba(0, 0, 0, 1)">
    },
    </span>"repository"<span style="color: rgba(0, 0, 0, 1)">: {
      </span>"type": "gitee"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"url": "https://gitee.com/getbetter/wx-minipro-helper.git"<span style="color: rgba(0, 0, 0, 1)">
    },
    </span>"homepage": "https://gitee.com/getbetter/wx-minipro-helper/blob/master/README.md"<span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<p>&nbsp;</p>
<p>step4&nbsp; 写扩展的功能,扩展入口extension.js内容如下</p>
<div class="cnblogs_code">
<pre>const vscode = require('vscode'<span style="color: rgba(0, 0, 0, 1)">);

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 插件被激活时触发,所有代码总入口
* @param {*} context 插件上下文
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
exports.activate </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (context) {
console.log(</span>'扩展“wx-minipro-helper”已被激活!'<span style="color: rgba(0, 0, 0, 1)">);
require(</span>'./jump-to-definition')(context); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 跳转到定义</span>
<span style="color: rgba(0, 0, 0, 1)">};

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 插件被释放时触发
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
exports.deactivate </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
console.log(</span>'扩展“wx-minipro-helper”已被释放!'<span style="color: rgba(0, 0, 0, 1)">);
};</span></pre>
</div>
<p>extension.js引入的jump-to-definition文件,是跳转功能的具体实现,我为这部分代码写了详尽的注释, 基本原理就是VSCode提供了光标点击事件的一些属性,如点击了什么文件,点击了那一行,点击了文件中的什么文本,根据这些信息可以拿到跳转路径,然后调用vscode提供的跳转api,就能实现定义跳转功能</p>
<div class="cnblogs_code">
<pre>const vscode = require('vscode'<span style="color: rgba(0, 0, 0, 1)">);
const path </span>= require('path'<span style="color: rgba(0, 0, 0, 1)">);
const fs </span>= require('fs'<span style="color: rgba(0, 0, 0, 1)">);
const util </span>= require('./utils'<span style="color: rgba(0, 0, 0, 1)">);

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 查找文件定义的provider,匹配到了就return一个location,否则不做处理
* @param {*} document
* @param {*} position
* @param {*} token
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> provideDefinition(document, position, token) {

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取工作目录</span>
const projectPath =<span style="color: rgba(0, 0, 0, 1)"> util.getProjectPath(document);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取光标所在行的文档路径</span>
const { fileName } =<span style="color: rgba(0, 0, 0, 1)"> document;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取光标所在行的文档夹路径</span>
const workDir =<span style="color: rgba(0, 0, 0, 1)"> path.dirname(fileName);

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取光标所在位置的双引号范围内的文本路径,并去除空格,引号,逗号</span>
let textPath = document.getText(document.getWordRangeAtPosition(position, /[\'\"](.*?)[\'\"]/<span style="color: rgba(0, 0, 0, 1)">g));
textPath </span>= textPath.replace(/,|\s|\'|\"/gi, ''<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取光标所在行的信息</span>
const line =<span style="color: rgba(0, 0, 0, 1)"> document.lineAt(position);


</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果跳转行存在import字样,屏蔽掉这个工具的跳转功能,因为会与开发编辑工具的跳转功能冲突</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (line.text.includes('import')) <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> wxml文件中微信标签上bindTap绑定方法跳转, 因为在wxml文件中,获取到的光标所在处的文本是整个文档,所以要修改</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 光标所在行截取出来的字符串,没有.或/等路径符</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (/\.wxml$/.test(fileName) &amp;&amp; !/[\/\.]/<span style="color: rgba(0, 0, 0, 1)">.test(textPath)) {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> const textLine = document.lineAt(position);</span>
    const wordRange = document.getWordRangeAtPosition(position, /[\w|\-]+\b/<span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> const tag = (textLine.text.match(/(?&lt;=&lt;\/?)[\w|\-]+\b/) || []);</span>
    const word =<span style="color: rgba(0, 0, 0, 1)"> document.getText(wordRange);
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log(wordRange, word, tag, textPath);</span>
   
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 在wxml文件对应的js文件中,查找方法名所在的行号和列数</span>
    const filePath = fileName.replace(/\.wxml$/, '.js'<span style="color: rgba(0, 0, 0, 1)">);
    const pos </span>=<span style="color: rgba(0, 0, 0, 1)"> util.findStrInFile({ filePath, str: word});
    const { row, col } </span>=<span style="color: rgba(0, 0, 0, 1)"> pos;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 判断是否找到</span>
    <span style="color: rgba(0, 0, 255, 1)">if</span> (row != 0 &amp;&amp; col != 0<span style="color: rgba(0, 0, 0, 1)">) {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> vscode.Location(vscode.Uri.file(filePath), <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> vscode.Position(row, col));
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> [];
}



</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 项目定制需求--ajax url跳转,不通用</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 检测光标所在行的字符串中是否有ajax('')字样</span>
const ajaxReg1 = <span style="color: rgba(0, 0, 255, 1)">new</span> RegExp(`ajax\\(\\s*.*('|")${textPath}('|"<span style="color: rgba(0, 0, 0, 1)">),?`, 'gm');
//检测光标所在行的字符串中是否有yield call(ajax字样
const ajaxReg2 = new RegExp(`yield call\\(ajax\\, ?('|</span>")${textPath}('|"), ?`, 'gm'<span style="color: rgba(0, 0, 0, 1)">);
const json = document.getText();
if (ajaxReg1.test(json) || ajaxReg2.test(json)) {
    // webapp项目
    const destPath1 = `${projectPath}/src/config/api.js`;
    // 小程序项目
    const destPath2 = `${projectPath}/config/api-config.js`;
    let destPath = </span>''<span style="color: rgba(0, 0, 0, 1)">;
    if (fs.existsSync(destPath1)) {
      destPath = destPath1;
    } else if (fs.existsSync(destPath2)) {
      destPath = destPath2;
    }
    // 文件存在
    if (fs.existsSync(destPath)) {
      try {
      // 查找关键字在文件中的行号和列号
      const pos = util.findStrInFile({ filePath:destPath, str: textPath });
      const { row, col } = pos;
      return new vscode.Location(vscode.Uri.file(destPath), new vscode.Position(row, col));
      } catch (error) {
      vscode.window.showErrorMessage(</span>'%c error:', 'color: #0e93e0;background: #aaefe5;'<span style="color: rgba(0, 0, 0, 1)">, JSON.stringify(error));
      return [];
      }
    }
    return []
}

// 微信小程序app.json跳转逻辑比较特殊,存在分包路径,如果是分包路径,要拼接子包root路径部分
if (fileName.includes(</span>'app.json'<span style="color: rgba(0, 0, 0, 1)">)) {
    const json = JSON.parse(document.getText());
    // 分包路径判断
    let isSubPath = json.subpackages.some((item) =&gt; {
      if (item.pages.includes(textPath)) {
      // 如果是分包路径,则要拼接分包的root路径部分
      textPath = `/${item.root}/${textPath}`;
      return true;
      }
      return false;
    });
    // 如果是正常页面路径,要在页面路径前面加绝对路径符号/
    if (!isSubPath) {
      textPath = `/${textPath}`;
    }
}

// 如果没有文件后缀,说明是json,或者js,jsx文件中的navigateTo跳转,默认跳转到对应页面的wxml文件
const reg = /\.\w+$/;
let isNoSuffix = !reg.exec(textPath);
// 没有文件后缀,添加默认的跳转文件类型
if (isNoSuffix) {
    textPath = `${textPath}.wxml`;
}

let jumpPath;
if (textPath.startsWith(</span>'/')) {
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 为绝对路径时-直接拼接工程路径+截取的路径字符串</span>
    jumpPath =<span style="color: rgba(0, 0, 0, 1)"> path.join(projectPath, textPath);
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 为相对路径时-转换成绝对路径</span>
    jumpPath =<span style="color: rgba(0, 0, 0, 1)"> path.resolve(workDir, textPath);
}

console.log(</span>'====== 进入 provideDefinition 方法 ======'<span style="color: rgba(0, 0, 0, 1)">);
console.log(</span>'projectPath=%s ', projectPath); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 当前工程目录</span>
console.log('document:', document); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 文档对象</span>
console.log('position:', position); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 位置</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log('token=%o', token); // 分词</span>
console.log('line:', line); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 当前光标所在行</span>
console.log('fileName=%s ', fileName); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 当前文件名</span>
console.log('workDir=%s', workDir); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 当前文件所在目录</span>
console.log('textPath=%s', textPath); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 跳转短路径</span>
console.log('jumpPath=%s ', jumpPath); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 跳转路径</span>

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 路径不存在则不跳转</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (!jumpPath || !<span style="color: rgba(0, 0, 0, 1)">fs.existsSync(jumpPath)) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> vscode.Location(vscode.Uri.file(jumpPath), <span style="color: rgba(0, 0, 255, 1)">new</span> vscode.Position(0, 0<span style="color: rgba(0, 0, 0, 1)">));
}
}

module.exports </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (context) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 注册如何实现跳转到定义,第一个参数表示仅对js,jsx,ts,tsx,json,wxml文件生效</span>
<span style="color: rgba(0, 0, 0, 1)">context.subscriptions.push(
    vscode.languages.registerDefinitionProvider(
      { pattern: </span>'**/*.{ts,js,jsx,tsx,json,wxml}'<span style="color: rgba(0, 0, 0, 1)"> },
      {
      provideDefinition,
      }
    )
);
};</span></pre>
</div>
<p>step5&nbsp; 调试VSCode 扩展,按下F5, VSCode会启动一个新的窗口,在新窗口调试功能,在旧窗口看调试日志,下图的第一张图是旧窗口,第二张图是新窗口</p>
<p><img src="https://img2020.cnblogs.com/blog/861554/202011/861554-20201111213322117-1830544682.png"></p>
<p><img src="https://img2020.cnblogs.com/blog/861554/202011/861554-20201111213638392-551256301.png"></p>
<p>&nbsp;step6&nbsp; 扩展开发完成后,就可以准备发布了。首先你需要注册一个发布账号&nbsp;marketplace.visualstudio.com/manage/,填写各种注册信息,注册完之后,安装官方发布脚本,然后执行打包脚本命令</p>
<div class="cnblogs_code">
<pre>E:\study\wx-minipro-helper&gt;<span style="color: rgba(0, 0, 0, 1)">vsce package
INFO Detected presense of yarn.lock. Using </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">yarn</span><span style="color: rgba(128, 0, 0, 1)">'</span> instead of <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">npm</span><span style="color: rgba(128, 0, 0, 1)">'</span> (to override this pass <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">--no-yarn</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)"> on the command line).
DONE Packaged: E:\study\wx</span>-minipro-helper\wx-minipro-helper-<span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">3</span>.vsix (<span style="color: rgba(128, 0, 128, 1)">10</span> files, <span style="color: rgba(128, 0, 128, 1)">23</span>.06KB)</pre>
</div>
<p>step7 在vscode应用市场发布扩展 ,刚才生成的扩展wx-minipro-helper-0.0.3.vsix&nbsp;</p>
<p><img src="https://img2020.cnblogs.com/blog/861554/202011/861554-20201111214307269-634061342.png"></p>
<p>&nbsp;</p>
<p>&nbsp;扩展的更新方法</p>
<p><img src="https://img2020.cnblogs.com/blog/861554/202011/861554-20201111214818535-747250136.gif"></p>
<p>&nbsp;</p>
<h3>避坑指南</h3>
<p>1. VSCode 扩展 的js文件,只要有一处报错,调试控制台就没有任何日志输出,不好排查错误。新手这个时候很茫然,惊慌失措。不知道哪里出了问题。看了这篇文章之后,你要淡定一些。</p>
<p>2. package.json中的vscode版本很重要,不能太高,我用yo code生成的初始项目,vscode的版本配置是 "vscode": "^1.51.0",结果我发现这个扩展只能在VSCode编辑器中使用,不能在微信开发者工具中使用,</p>
<p>我猜测可能是微信开发者工具只支持vscode工具包的低级版本。我把vscode的版本改成下面的配置后,在微信开发者工具中也可以使用了。</p>
<div class="cnblogs_code">
<pre>"engines"<span style="color: rgba(0, 0, 0, 1)">: {
      </span>"vscode": "^1.5.0" <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 依赖的vscode版本</span>
   },</pre>
</div>
<p>3.在不同的文件类型中,document.getText(document.getWordRangeAtPosition(position)获取到的光标所在处的字符串不一样,在json文件中,能拿到双引号之间的全部内容,在js,jsx,ts,tsx,wxml文件中,只能拿到光标所在处的哪个单词,所以要用正则表达式,取出跳转路径。</p>
<p>4.安装的同类插件太多了,插件之间会打架,出现如下这种情况,不进行跳转,处理方法就是修改下载到本地的插件源代码,屏蔽掉自己插件或别人插件的同类功能。</p>
<p><img src="https://img2020.cnblogs.com/blog/861554/202011/861554-20201112094119356-1372503960.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3>最后</h3>
<p>本文实现的微信小程序扩展插件代码托管在码云,&nbsp;欢迎下载&nbsp;</p>
<p>这个扩展已经发布到vscode 应用扩展市场,输入wx-minipro-helper就可以搜到</p>
<p><img src="https://img2020.cnblogs.com/blog/861554/202011/861554-20201111220819348-832836455.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>参考文章</p>
<p> VSCode 插件开发全攻略&nbsp;</p>
<p>&nbsp;如何在 10 分钟内完成一款 vscode 扩展开发&nbsp;</p><br><br>
来源:https://www.cnblogs.com/wangpenghui522/p/13943408.html
頁: [1]
查看完整版本: VSCode 微信小程序扩展开发