自訂解析器
ESLint 自訂解析器可讓您擴充 ESLint,以支援程式碼中新的非標準 JavaScript 語言功能或自訂語法。解析器負責接收您的程式碼並將其轉換為抽象語法樹 (AST),然後 ESLint 可以分析和檢查該 AST。
建立自訂解析器
自訂解析器中的方法
自訂解析器是一個 JavaScript 物件,具有 parse()
或 parseForESLint()
方法。 parse
方法僅傳回 AST,而 parseForESLint()
也會傳回額外的值,讓解析器可以進一步自訂 ESLint 的行為。
這兩種方法都應該是實例(自有)屬性,並將原始碼作為第一個引數,以及一個可選的設定物件作為第二個引數,該物件在設定檔中以 parserOptions
提供。
// customParser.js
const espree = require("espree");
// Logs the duration it takes to parse each file.
function parse(code, options) {
const label = `Parsing file "${options.filePath}"`;
console.time(label);
const ast = espree.parse(code, options);
console.timeEnd(label);
return ast; // Only the AST is returned.
};
module.exports = { parse };
parse
的回傳物件
parse
方法應該只傳回 AST 物件。
parseForESLint
的回傳物件
parseForESLint
方法應傳回一個物件,其中包含必要屬性 ast
和可選屬性 services
、scopeManager
和 visitorKeys
。
ast
應該包含 AST 物件。services
可以包含任何依賴解析器的服務(例如節點的類型檢查器)。services
屬性的值可作為規則中的context.sourceCode.parserServices
使用。預設值為空物件。scopeManager
可以是 ScopeManager 物件。自訂解析器可以使用自訂範圍分析來處理實驗性/增強語法。預設值是 eslint-scope 建立的ScopeManager
物件。- ESLint v4.14.0 中新增了對
scopeManager
的支援。支援scopeManager
的 ESLint 版本將在parserOptions
中提供eslintScopeManager: true
屬性,可用於功能偵測。
- ESLint v4.14.0 中新增了對
visitorKeys
可以是一個物件,用於自訂 AST 遍歷。物件的鍵是 AST 節點的類型。每個值都是應該遍歷的屬性名稱陣列。預設值是eslint-visitor-keys
的 KEYS。- ESLint v4.14.0 中新增了對
visitorKeys
的支援。支援visitorKeys
的 ESLint 版本將在parserOptions
中提供eslintVisitorKeys: true
屬性,可用於功能偵測。
- ESLint v4.14.0 中新增了對
自訂解析器中的 Meta 資料
為了更容易偵錯和更有效地快取自訂解析器,建議在您的自訂解析器根目錄的 meta
物件中提供名稱和版本,如下所示
// preferred location of name and version
module.exports = {
meta: {
name: "eslint-parser-custom",
version: "1.2.3"
}
};
meta.name
屬性應該與您的自訂解析器的 npm 套件名稱相符,而 meta.version
屬性應該與您的自訂解析器的 npm 套件版本相符。完成此操作的最簡單方法是從您的 package.json
中讀取此資訊。
AST 規格
自訂解析器應建立的 AST 是基於 ESTree。AST 需要一些關於原始碼詳細資訊的額外屬性。
所有節點
所有節點都必須有 range
屬性。
range
(number[]
) 是兩個數字的陣列。這兩個數字都是從 0 開始的索引,即原始碼字元陣列中的位置。第一個是節點的起始位置,第二個是節點的結束位置。code.slice(node.range[0], node.range[1])
必須是節點的文字。此範圍不包含節點周圍的空格/括號。loc
(SourceLocation
) 不得為null
。 ESTree 將loc
屬性定義為可為 null,但 ESLint 需要此屬性。SourceLocation#source
屬性可以為undefined
。 ESLint 不會使用SourceLocation#source
屬性。
所有節點的 parent
屬性必須可重寫。在任何規則存取 AST 之前,ESLint 會在遍歷時將每個節點的 parent
屬性設定為其父節點。
Program
節點
Program
節點必須具有 tokens
和 comments
屬性。這兩個屬性都是下面 Token
介面的陣列。
interface Token {
type: string;
loc: SourceLocation;
// See the "All Nodes" section for details of the `range` property.
range: [number, number];
value: string;
}
tokens
(Token[]
) 是影響程式行為的標記陣列。標記之間可以存在任意空格,因此規則會檢查Token#range
以偵測標記之間的空格。此陣列必須依Token#range[0]
排序。comments
(Token[]
) 是註解標記的陣列。此陣列必須依Token#range[0]
排序。
所有標記和註解的範圍索引不得與其他標記和註解的範圍重疊。
Literal
節點
Literal
節點必須具有 raw
屬性。
raw
(string
) 是此文字的原始碼。這與code.slice(node.range[0], node.range[1])
相同。
封裝自訂解析器
若要將您的自訂解析器發佈到 npm,請執行下列操作
- 依照上述「建立自訂解析器」章節建立自訂解析器。
- 為自訂解析器建立 npm 套件。
- 在您的
package.json
檔案中,將main
欄位設定為匯出自訂解析器的檔案。 - 發佈 npm 套件。
如需更多關於發佈 npm 套件的資訊,請參閱 npm 文件。
一旦您發佈了 npm 套件,您就可以將該套件新增到您的專案中來使用它。例如
npm install eslint-parser-myparser --save-dev
然後使用 parser
屬性將自訂解析器新增到您的 ESLint 設定檔中。例如
// .eslintrc.js
module.exports = {
parser: 'eslint-parser-myparser',
// ... rest of configuration
};
若要深入瞭解如何在您的專案中使用 ESLint 解析器,請參閱 設定解析器。
範例
如需自訂解析器的複雜範例,請參閱 @typescript-eslint/parser
原始碼。
一個簡單的自訂解析器,可為規則提供 context.sourceCode.parserServices.foo()
方法。
// awesome-custom-parser.js
var espree = require("espree");
function parseForESLint(code, options) {
return {
ast: espree.parse(code, options),
services: {
foo: function() {
console.log("foo");
}
},
scopeManager: null,
visitorKeys: null
};
};
module.exports = { parseForESLint };
在 ESLint 設定檔中包含自訂解析器
// .eslintrc.json
{
"parser": "./path/to/awesome-custom-parser.js"
}