摘要:的初衷是為了讓程序員可以創(chuàng)建自己的檢測(cè)規(guī)則。為了便于人們使用,內(nèi)置了一些規(guī)則,當(dāng)然,你可以在使用過(guò)程中自定義規(guī)則。所有的規(guī)則默認(rèn)都是禁用的。在文件里的字段進(jìn)行配置。如何編寫一個(gè)知道了的原理,接下來(lái)可以自定義一個(gè)。
eslint介紹
ESLint 是一個(gè)開(kāi)源的 JavaScript 代碼檢查工具,由 Nicholas C. Zakas 于2013年6月創(chuàng)建。代碼檢查是一種靜態(tài)的分析,常用于尋找有問(wèn)題的模式或者代碼,并且不依賴于具體的編碼風(fēng)格。對(duì)大多數(shù)編程語(yǔ)言來(lái)說(shuō)都會(huì)有代碼檢查,一般來(lái)說(shuō)編譯程序會(huì)內(nèi)置檢查工具。
JavaScript 是一個(gè)動(dòng)態(tài)的弱類型語(yǔ)言,在開(kāi)發(fā)中比較容易出錯(cuò)。因?yàn)闆](méi)有編譯程序,為了尋找 JavaScript 代碼錯(cuò)誤通常需要在執(zhí)行過(guò)程中不斷調(diào)試。像 ESLint 這樣的可以讓程序員在編碼的過(guò)程中發(fā)現(xiàn)問(wèn)題而不是在執(zhí)行的過(guò)程中。
ESLint 的初衷是為了讓程序員可以創(chuàng)建自己的檢測(cè)規(guī)則。ESLint 的所有規(guī)則都被設(shè)計(jì)成可插拔的。為了便于人們使用,ESLint 內(nèi)置了一些規(guī)則,當(dāng)然,你可以在使用過(guò)程中自定義規(guī)則。所有的規(guī)則默認(rèn)都是禁用的。
ESLint 使用 Node.js 編寫。
eslint配置一般都采用.eslintrc.* 的配置文件進(jìn)行配置, 如果放在項(xiàng)目的根目錄中,則會(huì)作用于整個(gè)項(xiàng)目。如果在項(xiàng)目的子目錄中也包含著.eslintrc文件,則對(duì)于子目錄中文件的檢查會(huì)忽略掉根目錄中的配置,而直接采用子目錄中的配置,這就能夠在不同的目錄范圍內(nèi)應(yīng)用不同的檢查規(guī)則,顯得比較靈活。ESLint采用逐級(jí)向上查找的方式查找.eslintrc.*文件,當(dāng)找到帶有 "root": true 配置項(xiàng)的.eslintrc.* 文件時(shí),將會(huì)停止向上查找。
在 package.json文件里的 eslintConfig 字段進(jìn)行配置。
以使用項(xiàng)目為例,簡(jiǎn)單介紹一下eslint的具體配置及作用:
module.exports = { parser: "babel-eslint", // parser指定解析器,默認(rèn)的為espree。babel-eslint是一個(gè)Babel parser的包裝器,這個(gè)包裝器使得 Babel parser 可以和 ESLint 協(xié)調(diào)工作 parserOptions: { sourceType: "module", // 設(shè)置為 "script" (默認(rèn)) 或 "module"(ES6)。 ecmaFeatures: { // 這是個(gè)對(duì)象,表示你想使用的額外的語(yǔ)言特性: jsx: true // 啟用 JSX } }, extends: ["eslint:recommended"], // 使用eslint推薦的規(guī)則作為基礎(chǔ)配置,可以在rules中覆蓋 plugins: ["html", "vue", "prettier", "import"], // vue是eslint-plugin-vue的簡(jiǎn)寫,此插件的作用是可以讓eslint識(shí)別.vue中的script代碼 rules: { // 0或者off表示規(guī)則關(guān)閉,出錯(cuò)也被忽略;1或者warn表示如果出錯(cuò)會(huì)給出警告(不會(huì)導(dǎo)致程序退出);2或者error表示如果出錯(cuò)會(huì)報(bào)出錯(cuò)誤(會(huì)導(dǎo)致程序退出,退出碼是1) "no-console": "off", "prefer-const": "error", "prettier/prettier": "warn", "prefer-arrow-callback": "warn", "no-debugger": process.env.NODE_ENV === "production" ? 2 : 0 }, globals: { // 允許在代碼中使用全局變量 location: true, setTimeout: true } };
具體的配置文檔:http://eslint.cn/docs/user-guide/configuring
具體的eslint:recommended支持的規(guī)則:https://cn.eslint.org/docs/rules/
“extends”除了可以引入推薦規(guī)則,還可以以文件形式引入其它的自定義規(guī)則,然后在這些自定義規(guī)則的基礎(chǔ)上用rules去定義個(gè)別規(guī)則,從而覆蓋掉”extends”中引入的規(guī)則。
{ "extends": [ "./node_modules/coding-standard/eslintDefaults.js", // Override eslintDefaults.js "./node_modules/coding-standard/.eslintrc-es6", // Override .eslintrc-es6 "./node_modules/coding-standard/.eslintrc-jsx", ], "rules": { // Override any settings from the "parent" configuration "eqeqeq": "warn" } }
除了在配置文件中指定規(guī)則外,還可以在代碼中指定規(guī)則,代碼文件內(nèi)以注釋配置的規(guī)則會(huì)覆蓋配置文件里的規(guī)則,即優(yōu)先級(jí)要更高。平時(shí)我們常用的就是 `eslint-disable-next-line
`
可以通過(guò)在項(xiàng)目目錄下建立.eslintignore文件,并在其中配置忽略掉對(duì)哪些文件的檢查。需要注意的是,不管你有沒(méi)有在.eslintignore中進(jìn)行配置,eslint都會(huì)默認(rèn)忽略掉對(duì)/node_modules/** 的檢查。也可以在package.json文件的 eslintIgnore 字段進(jìn)行配置。
eslint檢查原理要實(shí)現(xiàn)靜態(tài)分析則需要自建一個(gè)預(yù)編譯階段對(duì)代碼進(jìn)行解析。
首先我們看看大部分編譯器工作時(shí)的三個(gè)階段:
解析:將未經(jīng)處理的代碼解析成更為抽象的表達(dá)式,通常為抽象語(yǔ)法樹(shù),即 AST。
轉(zhuǎn)換:通過(guò)修改解析后的代碼表達(dá)式,將其轉(zhuǎn)換為符合預(yù)期的新格式。
代碼生成:將轉(zhuǎn)換后的表達(dá)式生成為新的目標(biāo)代碼。
對(duì)于eslint來(lái)說(shuō),規(guī)則校驗(yàn)發(fā)生在將JavaScript 代碼解析為 AST 之后,遍歷 AST 的過(guò)程中。eslint采用 Espree 來(lái)生成AST。具體的生成方法在這里。
我們可以使用AST explorer來(lái)查看代碼被解析后生成的AST。
首先來(lái)看看eslint源碼中關(guān)于rules的編寫。eslint中的rules源碼存在于lib/rules下。每一個(gè)rules都是一個(gè)node模塊,用module.exports導(dǎo)出一個(gè)meta對(duì)象及一個(gè)create函數(shù)。
module.exports = { meta: { type: "suggestion", docs: { description: "disallow unnecessary semicolons", category: "Possible Errors", recommended: true, url: "https://eslint.org/docs/rules/no-extra-semi" }, fixable: "code", schema: [] // no options }, create: function(context) { return { // callback functions }; } };
meta 代表了這條規(guī)則的元數(shù)據(jù),如這條規(guī)則的類別,文檔,可接收的參數(shù) schema 等等。
create 返回一個(gè)對(duì)象,其中定義了一些在 AST 遍歷訪問(wèn)到對(duì)應(yīng)節(jié)點(diǎn)需要執(zhí)行的方法等等。函數(shù)接受一個(gè)context對(duì)象作為參數(shù),里面包含了例如可以報(bào)告錯(cuò)誤或者警告的context.report()、可以獲取源代碼的context.getSourceCode()等方法,可以簡(jiǎn)化規(guī)則的編寫。
function checkLastSegment (node) { // report problem for function if last code path segment is reachable } module.exports = { meta: { ... }, create: function(context) { // declare the state of the rule return { ReturnStatement: function(node) { // 在AST從上向下遍歷到ReturnStatement node 時(shí)執(zhí)行 }, // 在AST 從下向上遍歷到 function expression node 時(shí)執(zhí)行: "FunctionExpression:exit": checkLastSegment, "ArrowFunctionExpression:exit": checkLastSegment, onCodePathStart: function (codePath, node) { // 在分析代碼路徑開(kāi)始時(shí)執(zhí)行 }, onCodePathEnd: function(codePath, node) { // 在分析代碼路徑結(jié)束時(shí)執(zhí)行 } }; } };
遍歷 AST 的過(guò)程中會(huì)以“從上至下”再“從下至上”的順序經(jīng)過(guò)節(jié)點(diǎn)兩次,selector 默認(rèn)會(huì)在下行的過(guò)程中執(zhí)行對(duì)應(yīng)的訪問(wèn)函數(shù),如果需要再上行的過(guò)程中執(zhí)行,則需要添加:exit。
詳細(xì)的原理在官方文檔中有說(shuō)明,點(diǎn)這里。
詳細(xì)的代碼路徑分析在這里。
知道了rules的原理,接下來(lái)可以自定義一個(gè)rules。每一個(gè)rules需要有三個(gè)以該規(guī)則名命名的文件,分別是:
在 lib/rules 目錄下: 一個(gè)源文件(例如,no-extra-semi.js)
在 tests/lib/rules 目錄下: 一個(gè)測(cè)試文件 (例如, no-extra-semi.js)
在 docs/rules 目錄: 一個(gè) markdown 文檔文件 (例如, no-extra-semi)
接下來(lái)我們來(lái)編寫一個(gè)簡(jiǎn)單的rules,例如禁止塊級(jí)注釋,當(dāng)代碼中使用了塊級(jí)注釋,eslint將報(bào)錯(cuò)。
rules文件:
// lib/rules/no-block-comments.js module.exports = { meta: { docs: { description: "禁止塊級(jí)注釋", category: "Stylistic Issues", recommended: true } }, create (context) { // 獲取源代碼 const sourceCode = context.getSourceCode() return { Program () { // 獲取源代碼中所有的注釋 const comments = sourceCode.getAllComments() const blockComments = comments.filter(({ type }) => type === "Block") blockComments.length && context.report({ node: node, message: "No block comments" }) } } } }
rules的測(cè)試文件:
// tests/lib/rules/no-block-comments.js const RuleTester = require("eslint").RuleTester; const rule = require("../../../lib/rules/no-block-comments"); const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2018 } }); // You do have to tell eslint what js you"re using ruleTester.run("no-block-comments", rule, { valid: ["var a = 1; console.log(a)"], invalid: [ { code: "var a = 1; /* block comments */ console.log(a)", errors: [ { messageId: "blockComments", line: 1, nodeType: "Block" } ] } ] });
官網(wǎng)的working with rules文檔中有關(guān)于如何編寫一個(gè)rules的詳細(xì)介紹。
編寫好的rules需要發(fā)布到npm上,作為一個(gè)eslint-plugin,在項(xiàng)目中下載下來(lái)才能夠使用。例子中代碼的npm在這里。
在項(xiàng)目中的配置:
// .eslintrc.js module.exports = { ... "plugins": [ "eslint-plugin-no-block-comments" // 你 publish 的 npm 包名稱,可以省略 eslint-plugin ], "rules": { // 啟用的規(guī)則及其各自的錯(cuò)誤級(jí)別 "no-console": "off", "no-block-comments/no-block-comments": 2 // 引用no-block-comments插件中的no-block-comments規(guī)則 } };
之后就可以對(duì)代碼進(jìn)行檢查了。比如我要檢查的代碼如下:
// src/index.js const a = 1; /* 這里是塊級(jí)注釋 */ console.log(a);
在命令行中執(zhí)行eslint src,就可以看到報(bào)錯(cuò)結(jié)果。
ESlint官網(wǎng)
ESLint 工作原理探討
開(kāi)發(fā) eslint 規(guī)則
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/106449.html
摘要:以前沒(méi)時(shí)間過(guò),每次項(xiàng)目編輯器的插件就關(guān)掉,老項(xiàng)目都沒(méi)注意過(guò)相關(guān)的代碼規(guī)范,這次新項(xiàng)目加入進(jìn)去實(shí)踐下三個(gè)插件功自動(dòng)有些規(guī)則是沖突的,需要確定優(yōu)先順序,其他插件進(jìn)行自定義化的配置都可以自動(dòng)保存格式化的功能用和寫出高質(zhì)量代碼在中對(duì)兩者進(jìn)行配置使用 以前沒(méi)時(shí)間過(guò)eslint,每次項(xiàng)目vscode 編輯器的eslint插件就關(guān)掉eslint,老項(xiàng)目都沒(méi)注意過(guò)相關(guān)的代碼規(guī)范,這次新項(xiàng)目加入進(jìn)去實(shí)踐...
摘要:配置添加包配置此處如果不使用需要將替換為效果代碼提交的格式不符合標(biāo)準(zhǔn)就會(huì)直接被拒絕。 Commitlint 配置 添加包 yarn add @commitlint/cli @commitlint/config-conventional husky -D 配置package.json husky: { hooks: { // 此處如果不使用husky 需要將H...
摘要:自定義規(guī)則校驗(yàn)代碼業(yè)務(wù)邏輯是社區(qū)中主流的工具,提供的大量規(guī)則有效的保障了許多項(xiàng)目的代碼質(zhì)量。本文將介紹如何通過(guò)自定義檢查規(guī)則,校驗(yàn)項(xiàng)目中特有的一些業(yè)務(wù)邏輯,如特殊作用域特殊使用規(guī)范性等。 自定義 eslint 規(guī)則校驗(yàn)代碼業(yè)務(wù)邏輯 eslint 是 JavaScript 社區(qū)中主流的 lint 工具,提供的大量規(guī)則有效的保障了許多項(xiàng)目的代碼質(zhì)量。本文將介紹如何通過(guò)自定義 eslint ...
須知:使用vite需要node版本在12以上 一:npm構(gòu)建 1、npm init vite@latest 2、Project name:(項(xiàng)目名稱) 3、Select a framework:(選擇要用什么構(gòu)建自己的項(xiàng)目,這邊選vue)然后會(huì)有兩個(gè)選項(xiàng)一個(gè)是vue(vue+js) ,一個(gè)是vue+ts,要依照自己需求做選擇 4、cd到項(xiàng)目下npm install 安裝一下依賴 注...
摘要:工具幫助避免在編寫時(shí)出現(xiàn)愚蠢的錯(cuò)誤。并不檢測(cè)潛在的,比如,未使用的變量或意外的全局變量等。在提到的所有工具中,它具有最廣泛的功能支持。使用工具是捕獲問(wèn)題的良好步驟,但只能看到規(guī)則允許的錯(cuò)誤。也可用于此目的。 Lint工具幫助避免在編寫JavaScript時(shí)出現(xiàn)愚蠢的錯(cuò)誤。盡管有多年的經(jīng)驗(yàn),我仍然鍵入不正確的變量名稱,出現(xiàn)語(yǔ)法錯(cuò)誤,以及忘記正確地處理error。在浪費(fèi)自己時(shí)間,或更糟糕地...
閱讀 782·2021-09-30 09:46
閱讀 3797·2021-09-03 10:45
閱讀 3617·2019-08-30 14:11
閱讀 2551·2019-08-30 13:54
閱讀 2262·2019-08-30 11:00
閱讀 2357·2019-08-29 13:03
閱讀 1564·2019-08-29 11:16
閱讀 3588·2019-08-26 13:52