成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為什么 Eslint 可以檢查和修復格式問題,而 Babel

開發 項目管理
Eslint 可以檢查出代碼中的錯誤和一些格式問題,并能自動修復,它的實現原理就是基于 AST (抽象語法樹)。

Eslint 可以檢查出代碼中的錯誤和一些格式問題,并能自動修復,它的實現原理就是基于 AST (抽象語法樹)。

通過 Parser 把源碼解析成 AST 對象樹,源碼字符串中的各種信息就被保存到了這個對象樹里,然后遍歷 AST,對每一部分做檢查就能實現 Lint 的功能,而自動 fix 的功能則是基于字符串替換實現的,指定某一段 range,替換成另一段文本即可。

說起來,Babel 也是基于 AST 實現的代碼分析和轉換,但是卻不能檢查和修復格式的問題,這是為什么呢?為什么 Eslint 可以檢查格式而 Babel 不可以呢?

我們先寫一個 Eslint 的 rule

來感受下 Eslint 是怎么檢查和修復格式問題的。

Eslint 檢查格式的 rule大括號有兩種主流寫法,一種是同一行寫:

if (name === 'guang') {
}

另一種是新開一行寫:

if (name === 'guang')
{
}

我們寫一個 eslint 的 rule 來檢查大括號的格式并自動修復成同一行的格式。

思路分析

Eslint 的檢查是基于 AST,我們要檢查的 AST 是塊語句 BlockStatement。

關于什么代碼是什么 AST 可以用 astexplorer.net 可視化的查看,parser 選擇 espree (Eslint 默認的 parser):

具體來說檢查的是 BlockStatement 的最開始的 token { 的行號,是不是和它前一個 token 在同一行。(token 是指最小的不可再細分的單詞,比如關鍵字、變量名等標識符、各種分隔符等)

如果是同一行,則說明了是符合規范的。當然我們還可以進一步檢查一下大括號 { 和前一個 token 之間有沒有空格。

思路理清了,我們來寫下代碼:

代碼實現

Eslint 的 rule 的格式是這樣的:

 module.exports = {
meta: {
docs: {
description: "enforce consistent brace style for blocks"
},

fixable: true
},

create(context) {
return {
BlockStatement(node) {
}
}
}
};

分為 meta 和 create 兩部分:

  • meta:描述各種元信息,比如文檔描述、是否可自動修復等
  • create:實現對各種 AST 檢查的代碼,rule 的主體部分

我們在 create 里聲明了對 BlockStatement 節點的檢查,它的參數就是對應的節點對象。

但是我們要檢查的是 token,這個用 context 里的一個 api:

create(context) {
const sourceCode = context.getSourceCode();
return {
BlockStatement(node) {
const firstToken = sourceCode.getFirstToken(node);
const beforFirstToken = sourceCode.getTokenBefore(node);
}
}
}

我們從 context 中拿到了 sourceCode 的 api,它就是用來取 token 的。

我們用 getFirstToken 拿到了當前 node 的開始 token,也就是 {,

然后又拿到了當前 node 的前面一個節點的 token,也就是 (:

token 中保存了行列號信息,那么對比下行列號就知道是否有格式問題了:

如果 { 所在的行和 ) 所在的行不是同一行,就報錯

if (firstToken.loc.start.line !== beforFirstToken.loc.start.line) {
context.report({
node,
loc: firstToken.loc,
message: '大括號格式不對'
});
}

修復的方式自然就是把 { 和 ) 之間的部分替換成一個空格,這個使用 fixer 提供的 api:replaceTextRange:

if (firstToken.loc.start.line !== beforFirstToken.loc.start.line) {
context.report({
node,
loc: firstToken.loc,
message: '大括號格式不對'
fix: fixer => {
return fixer.replaceTextRange([beforFirstToken.range[1], firstToken.range[0]], ' ');
}
});
}

同理,也可以檢查出 { 和 ) 之間沒有空格的格式錯誤,修復方式一樣:

if (firstToken.loc.start.column === beforFirstToken.loc.start.column + 1){
context.report({
node,
loc: firstToken.loc,
message: '大括號前缺少空格',
fix: fixer => {
return fixer.replaceTextRange([beforFirstToken.range[1], firstToken.range[0]], ' ');
}
});
}

這樣就實現了大括號格式的檢查和自動修復。

我們來試下效果:

測試 rule

Eslint 除了提供命令行外,也提供了 api,我們調用它的 api 來測試 rule:

先創建 ESLint 對象,指定 rulePaths 也就是查找 rule 的目錄為當前目錄:

const { ESLint } = require("eslint");

const engine = new ESLint({
fix: false,
overrideConfig: {
parserOptions: {
ecmaVersion: 6,
},
rules: {
'my-brace-style': ['error']
}
},
rulePaths: [__dirname],
useEslintrc: false
});

useEslintrc 為 false 是不查找配置文件, fix 為 false 是不自動修復。

然后調用它的 lintText 代碼來測試,返回的結果使用 formatter 打印:

(async function main() {
const results = await engine.lintText(`
if (print)
{
const num = a + b;
console.log(num);
}
for(let i = 0;i<100;i++)
{
console.log(i);
}
`);

console.log(results[0].output);

const formatter = await engine.loadFormatter("stylish");
const resultText = formatter.format(results);
console.log(resultText);
})();

我們來試一下效果:

三處格式錯誤都檢查出來了!

然后把 fix 設為 true,來測試下自動修復:

格式自動修復了!

這樣我們就通過 Eslint 的 rule 實現了代碼格式的檢查和自動修復。

代碼上傳到了 github:https://github.com/QuarkGluonPlasma/eslint-plugin-exercize

那么再回到最開始的問題,為什么 Eslint 可以檢查代碼格式,而 Babel 不可以呢?

為什么 Eslint 可以檢查格式 Babel 不可以

我們寫了一個檢查大括號格式的 rule,可以發現能夠做格式檢查關鍵是能找到關聯的 token。

Eslint 的 AST 記錄了所有的 token,token 中有行列號信息,而且 AST 中也保存了 range,也就是當前節點的開始結束位置。并且還提供了 SourceCode 的 api 可以根據 range 去查詢 token。這是它能實現格式檢查的原因。

而 Babel 其實也支持 range 和 token,但是卻沒有提供根據 range 查詢 token 的 api,這是它不能做格式檢查的原因。

其實 Babel 和 Eslint 原理差不多,但是 Eslint 是被設計來做代碼錯誤和格式檢查與修復的,而 Babel 是被設計用來做代碼分析和轉換的,目的不同,所以也就提供了不同的 api,能夠做不同的事情。

總結

Eslint 是用來檢查代碼中的錯誤和格式問題的,基于 AST,Babel 也是基于 AST 做的代碼分析和轉換,但是卻不能檢查格式。

為了探究原因,我們寫了一個 EsLint 的檢查大括號格式的 rule,通過 SourceCode 的 api 拿到 { 和 ( 的 token,對比下行列號來做檢查。并且通過 fixer 的字符串替換做了自動修復。

寫完之后,我們發現 EsLint 能做格式檢查的原因是因為 AST 中記錄了 range,也保留了 token信息,并且提供了根據 range 查詢 token 的 api,而 Babel 沒有。

EsLint 和 Babel 原理大同小異,但是有不同的設計目的,所以提供了不同的 api,有著不同的功能。

責任編輯:姜華 來源: 神光的編程秘籍
相關推薦

2021-09-02 13:38:48

Eslint Babel 插件

2021-09-07 13:06:32

Eslint Fix 功能算法

2021-09-02 16:15:29

開發技能代碼

2021-09-11 19:46:14

配置

2021-09-05 11:37:31

Eslint插件Vue

2021-11-19 23:54:19

插件Eslint

2013-11-29 09:51:26

C++雙重檢查鎖定

2022-06-06 08:21:13

MySQL數據庫命令

2013-03-25 10:14:18

NginxApache

2019-04-19 11:56:48

框架AI開發

2021-06-01 06:00:06

typescriptjavascript

2021-10-31 23:57:33

Eslint原理

2022-02-15 07:03:04

start 源碼run線程

2012-10-10 16:52:21

CentOSDebianUbuntu

2021-10-30 19:57:00

HTTP2 HTTP

2021-08-14 09:04:58

TypeScriptJavaScript開發

2019-12-27 14:47:06

Python編程語言

2023-11-04 16:26:18

C語言數組

2022-05-24 08:31:05

C語言檢查數組

2023-09-26 11:28:08

代碼注釋軟件開發
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲综合电影 | 日韩视频区 | 最新伦理片| avav在线看| 日韩一级精品视频在线观看 | 色必久久| 夜夜爽99久久国产综合精品女不卡 | 久久精品国产v日韩v亚洲 | 黄色一级大片在线免费看产 | 99精品久久久国产一区二区三 | 亚洲一区二区电影网 | 韩国成人在线视频 | 亚洲精品天堂 | 久久久精品影院 | 精品国产乱码一区二区三区a | 国产福利二区 | 国内毛片毛片毛片毛片 | 免费中文字幕日韩欧美 | 久草免费在线视频 | 成人性视频免费网站 | 国产福利91精品一区二区三区 | 污污免费网站 | 成人欧美一区二区三区黑人孕妇 | 欧美日韩视频在线 | 国产精品欧美精品 | 精品欧美一区二区三区久久久小说 | 久久激情网 | 国产一区二区三区 | 国产精品久久一区二区三区 | 欧美精品区 | 日本精品免费在线观看 | 天天干com| 久久91av | 午夜精品一区二区三区在线 | 亚洲精品中文字幕在线观看 | 天堂va在线 | 色小姐综合网 | 性色av一区 | 久久aⅴ乱码一区二区三区 亚洲国产成人精品久久久国产成人一区 | 欧美在线一区二区三区四区 | 国产欧美一区二区三区日本久久久 |