VSCode插件开发全攻略(六)开发调试技巧
更多文章請(qǐng)戳VSCode插件開(kāi)發(fā)全攻略系列目錄導(dǎo)航。
前言
在介紹完一些比較簡(jiǎn)單的內(nèi)容點(diǎn)之后,我覺(jué)得有必要先和大家介紹一些開(kāi)發(fā)中遇到的一些細(xì)節(jié)問(wèn)題以及技巧,特別是后面一章節(jié)將要介紹WebView的知識(shí),這個(gè)坑會(huì)比較多,避免大家走彎路。
開(kāi)發(fā)方式
最理想的方式是準(zhǔn)備雙顯示器,一個(gè)寫(xiě)代碼,一個(gè)運(yùn)行插件,實(shí)踐證明這種方式開(kāi)發(fā)效率會(huì)提升很多,每次修改完代碼之后直接Ctrl+R重新加載即可,非常方便。
日志查看
就我目前遇到的情況來(lái)看,vscode日志主要有這5種:
舊窗口的調(diào)試控制臺(tái)
擴(kuò)展里的console.log()日志一般輸出在這里,但是有很大的限制,結(jié)構(gòu)稍微深一點(diǎn)的對(duì)象在這里了就顯示不了:
Unable to log remote console arguments Output omitted for an object that cannot be inspected (Error: [sxei.vscode-plugin-demo]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api sxei.vscode-plugin-demo)
這里只能看成是新窗口開(kāi)發(fā)者控制臺(tái)日志的一種快捷顯示,以下是舊窗口調(diào)試控制臺(tái)顯示的內(nèi)容:
而對(duì)應(yīng)的內(nèi)容在新窗口的開(kāi)發(fā)者控制臺(tái)顯示如下:
可以看到,結(jié)構(gòu)較深的對(duì)象即使在控制臺(tái)也無(wú)法顯示,目前發(fā)現(xiàn)的唯一比較好的方法就是在輸出的地方打一個(gè)斷點(diǎn),然后運(yùn)行的時(shí)候會(huì)自動(dòng)卡在這里,鼠標(biāo)懸停就可以查看對(duì)象的內(nèi)容。
新窗口的調(diào)試控制臺(tái)
一般沒(méi)什么擴(kuò)展相關(guān)日志會(huì)輸出在這里。
舊窗口的開(kāi)發(fā)者控制臺(tái)
快捷鍵Ctrl+Alt+I,這里一般顯示vscode本身一些日志,和擴(kuò)展相關(guān)的不會(huì)顯示在這里,所以這個(gè)也不用太多關(guān)心。
新窗口的開(kāi)發(fā)者控制臺(tái)
快捷鍵也是Ctrl+Alt+I,不記得的可以從幫助 -> 切換開(kāi)發(fā)人員工具找到。這個(gè)控制臺(tái)很重要,有時(shí)候如果發(fā)現(xiàn)你的代碼莫名其妙沒(méi)生效,很有可能是報(bào)錯(cuò)了,這種報(bào)錯(cuò)是不會(huì)顯示在舊窗口調(diào)試控制臺(tái)的,如果你不知道到這里來(lái)查看日志,那么你只能一臉懵逼的到處亂試了,調(diào)試控制臺(tái)只打印常規(guī)日志,語(yǔ)法錯(cuò)誤并不會(huì)顯示在這里。
例如,我在跳轉(zhuǎn)定義實(shí)現(xiàn)前人為制造一個(gè)錯(cuò)誤:
function provideDefinition(document, position, token) {console.log(aaf);const fileName = document.fileName;// 省略其它代碼 }運(yùn)行后就會(huì)發(fā)現(xiàn)點(diǎn)擊跳轉(zhuǎn)不生效,但是也沒(méi)有什么報(bào)錯(cuò)提示,此時(shí)只能打開(kāi)控制臺(tái)查看才能發(fā)現(xiàn)問(wèn)題:
WebView控制臺(tái)
WebView我們會(huì)在下一章節(jié)介紹,這里先提一下。Webview的控制臺(tái)比較特殊,需要特殊的命令才能打開(kāi),按下Ctrl+Shift+P然后執(zhí)行打開(kāi)Webview開(kāi)發(fā)工具,英文版應(yīng)該是Open Webview Developer Tools:
開(kāi)發(fā)時(shí)我們把它當(dāng)成一個(gè)普通的網(wǎng)頁(yè)來(lái)看就好了。
調(diào)試
vscode插件的調(diào)試非常簡(jiǎn)單方便,只需要在需要調(diào)試的地方打個(gè)斷點(diǎn),然后按F5執(zhí)行即可:
幾個(gè)調(diào)試快捷鍵:
- F5運(yùn)行
- Ctrl+F2停止運(yùn)行
- F6下一步跳過(guò)(類(lèi)似于Chrome的F10)
- F5下一步跳入
- F8跳過(guò)
如何快速找到我想找的內(nèi)容
剛開(kāi)始只能先大概對(duì)整個(gè)vscode的api有一個(gè)大概了解,了解了之后就大概清楚一般什么功能會(huì)怎么實(shí)現(xiàn),該去什么地方找,所有的vscode的api都可以在vscode.d.ts文件里面找到:
不得不佩服,正規(guī)大型項(xiàng)目的注釋寫(xiě)的真的不是一般的詳細(xì),官網(wǎng)的API文檔肯定也是基于這個(gè)自動(dòng)生成的,反正把這個(gè)ts文件吃透了,基本上你想實(shí)現(xiàn)什么功能要怎么實(shí)現(xiàn)都了如指掌了。
查看插件存放目錄
插件安裝后根據(jù)操作系統(tǒng)不同會(huì)放在如下目錄:
- Windows系統(tǒng):%USERPROFILE%\.vscode\extensions
- Mac/Linux:~/.vscode/extensions
想要學(xué)習(xí)查看其它插件的代碼可以找到這個(gè)目錄:
一些個(gè)人經(jīng)驗(yàn)分享
調(diào)試控制臺(tái)日志不可靠
vscode有一個(gè)很坑爹的地方,這里特別要注意,當(dāng)require一個(gè)function進(jìn)來(lái)并打印輸出時(shí),雖然打印在控制臺(tái)顯示為null,但其實(shí)是有值的,不知道的人很容易被誤導(dǎo),直接就是被這個(gè)現(xiàn)象騙了很久,切記切記!
test-require-function.js:
function testRequireFunction(a, b) {console.log('進(jìn)入testRequireFunction方法');console.log(a, b); } module.exports = testRequireFunction;extension.js:
exports.activate = function(context) {const testFn = require('./test-require-function');console.log(testFn); // vscode的日志輸出不可靠,這里竟然會(huì)打印null?!testFn(1, 2); // 1, 2 };輸出結(jié)果:
null 進(jìn)入testRequireFunction方法 1 2代碼為什么沒(méi)生效
代碼沒(méi)生效一般從這幾個(gè)地方去查找:
- activationEvents里面添加了嗎?開(kāi)發(fā)的時(shí)候如果老是忘記可以直接設(shè)置成*;
- 代碼是不是報(bào)錯(cuò)了?如前文所說(shuō),很多錯(cuò)誤是不會(huì)暴露出來(lái)的,需要手動(dòng)打開(kāi)控制臺(tái)查看;
- 代碼是不是忘記引入了?有時(shí)候拆分多個(gè)文件之后可能忘了引入;
- 邏輯是不是寫(xiě)錯(cuò)了?最好的辦法就是debug,這是找問(wèn)題最快的方法;
- 版本沖突
這里重點(diǎn)說(shuō)一下最后面的版本沖突,這個(gè)甚至可以說(shuō)是vscode本身的一些bug,經(jīng)常發(fā)現(xiàn)代碼莫名其妙地沒(méi)生效,怎么調(diào)試都不對(duì),后來(lái)發(fā)現(xiàn)運(yùn)行的根本就不是我們正在開(kāi)發(fā)的那個(gè)版本,特別是當(dāng)你的插件已經(jīng)發(fā)了一版到應(yīng)用市場(chǎng)并安裝后,本地再按F5運(yùn)行,理論上說(shuō)debug運(yùn)行的會(huì)覆蓋已安裝的,但有時(shí)候還是會(huì)出現(xiàn)異常情況,所以為了以防萬(wàn)一,當(dāng)出現(xiàn)這種情況時(shí)可以先把已經(jīng)安裝的給卸載。
還有一個(gè)問(wèn)題就是,有時(shí)候明明安裝了版本更加新的那個(gè),結(jié)果運(yùn)行的卻是舊的,打開(kāi)擴(kuò)展目錄會(huì)發(fā)現(xiàn)很多并存的同名不同版本插件,或者可能先是通過(guò)vsix方式安裝了一個(gè)版本,然后又從應(yīng)用市場(chǎng)安裝一個(gè),總之解決這類(lèi)問(wèn)題最好的方法就是:先卸載再安裝,實(shí)在不行手動(dòng)去插件目錄刪除之!
打開(kāi)文件
打開(kāi)文件是vscode.window.showTextDocument而不是vscode.workspace.openTextDocument,這個(gè)根據(jù)字面意思很容易搞錯(cuò),原來(lái)老外也有命名不準(zhǔn)確的時(shí)候啊,哈哈。
- vscode.workspace.openTextDocument僅僅是加載文檔并返回一個(gè)TextDocument對(duì)象,但是并不在vscode中打開(kāi);
- vscode.window.showTextDocument則是在vscode中打開(kāi)一個(gè)文檔;
其實(shí):
vscode.workspace.openTextDocument('someFilePath').then(document => {vscode.window.showTextDocument(document, editor => {// 可以操作文檔的editor對(duì)象}); })等價(jià)于:
vscode.window.showTextDocument(vscode.Uri.file('someFilePath'), editor => {// 可以操作文檔的editor對(duì)象 });工程根目錄的獲取
被這個(gè)問(wèn)題踩過(guò)很多次坑,所有重點(diǎn)介紹一下。
有的人的vscode工作空間是這樣的,每一個(gè)工程一個(gè)個(gè)地單獨(dú)拖入:
也有的人是直接用打開(kāi)文件夾的方式把存放代碼的父文件夾給打開(kāi):
但是如果此時(shí)你點(diǎn)擊將工作區(qū)另存為保存了工作區(qū)之后就變成這樣了(請(qǐng)注意圖標(biāo)的變化):
所以,即便拿到了某個(gè)文件的完整路徑也不好獲取這個(gè)文件的工程路徑,因?yàn)椴恢拦ぷ鲄^(qū)的這個(gè)文件夾名字是你的工程名還是存放工程的父文件夾的名字。
已知:
- vscode以前有一個(gè)vscode.workspace.rootPath,由于后來(lái)vscode支持multipleRoot模式,所以這個(gè)字段已經(jīng)過(guò)時(shí)作廢了。
- vscode.workspace.workspaceFolders可以獲取當(dāng)前工作區(qū)所有根文件夾數(shù)組;
之前我寫(xiě)了一個(gè)簡(jiǎn)單粗暴的獲取工程目錄方式:
/*** 獲取當(dāng)前所在工程根目錄,有3種使用方法:<br>* getProjectPath(uri) uri 表示工程內(nèi)某個(gè)文件的路徑<br>* getProjectPath(document) document 表示當(dāng)前被打開(kāi)的文件document對(duì)象<br>* getProjectPath() 會(huì)自動(dòng)從 activeTextEditor 拿document對(duì)象,如果沒(méi)有拿到則報(bào)錯(cuò)* @param {*} document */ getProjectPath(document) {if (!document) {document = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.document : null;}if (!document) {this.showError('當(dāng)前激活的編輯器不是文件或者沒(méi)有文件被打開(kāi)!');return '';}const currentFile = (document.uri ? document.uri : document).fsPath;let projectPath = null;let workspaceFolders = vscode.workspace.workspaceFolders.map(item => item.uri.path);// 由于存在Multi-root工作區(qū),暫時(shí)沒(méi)有特別好的判斷方法,先這樣粗暴判斷// 如果發(fā)現(xiàn)只有一個(gè)根文件夾,讀取其子文件夾作為 workspaceFoldersif (workspaceFolders.length == 1 && workspaceFolders[0] === vscode.workspace.rootPath) {const rootPath = workspaceFolders[0];var files = fs.readdirSync(rootPath);workspaceFolders = files.filter(name => !/^\./g.test(name)).map(name => path.resolve(rootPath, name));// vscode.workspace.rootPath會(huì)不準(zhǔn)確,且已過(guò)時(shí)// return vscode.workspace.rootPath + '/' + this._getProjectName(vscode, document);}workspaceFolders.forEach(folder => {if (currentFile.indexOf(folder) === 0) {projectPath = folder;}})if (!projectPath) {this.showError('獲取工程根路徑異常!');return '';}return projectPath; },這種方式生效的前提是,如果是按照第一種方式存放工作空間的,工程的數(shù)目必須大于等于2,但是這種判斷方式不用說(shuō)肯定會(huì)不準(zhǔn)確。
后來(lái)?yè)Q成了另外一種方式,考慮到工作接觸到的項(xiàng)目無(wú)論是node端還是前端都會(huì)有package.json文件在根目錄,所以就根據(jù)哪個(gè)文件夾有這個(gè)文件來(lái)判斷,也只能是這樣了。
總結(jié)
以上是生活随笔為你收集整理的VSCode插件开发全攻略(六)开发调试技巧的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android Annotation-让
- 下一篇: 20181009-9 每周例行报告