Пользовательские парсеры
Пользовательские парсеры ESLint позволяют расширить ESLint для поддержки проверки новых нестандартных возможностей языка JavaScript или пользовательского синтаксиса в коде. Парсер отвечает за преобразование вашего кода в абстрактное синтаксическое дерево (AST), которое ESLint затем может анализировать и проверять.
Создание пользовательского парсера
Методы пользовательских парсеров
Пользовательский парсер — это объект 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. Пользовательские парсеры могут применять настраиваемый анализ областей видимости для экспериментального или расширенного синтаксиса. По умолчанию используется объектScopeManager, создаваемый eslint-scope.- Поддержка
scopeManagerдобавлена в ESLint v4.14.0. Версии ESLint с поддержкойscopeManagerпредоставляют свойствоeslintScopeManager: trueвparserOptions, которое можно использовать для определения наличия этой возможности. - Начиная с ESLint v10.0.0,
ScopeManagerдолжен автоматически разрешать ссылки на глобальные переменные, объявленные в коде, и предоставлять метод экземпляраaddGlobals(names: string[]), который создаёт переменные с заданными именами в глобальной области видимости и разрешает ссылки на них.
- Поддержка
-
visitorKeysможет быть объектом для настройки обхода AST. Ключи объекта — это типы узлов AST. Каждое значение представляет собой массив имён свойств, которые следует обходить. По умолчанию используются KEYS изeslint-visitor-keys.- Поддержка
visitorKeysдобавлена в ESLint v4.14.0. Версии ESLint с поддержкойvisitorKeysпредоставляют свойствоeslintVisitorKeys: trueвparserOptions, которое можно использовать для определения наличия этой возможности.
- Поддержка
Метаданные пользовательских парсеров
Для упрощения отладки и повышения эффективности кэширования пользовательских парсеров рекомендуется указать имя и версию в объекте 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[]) — это массив из двух чисел. Оба числа представляют собой индекс, отсчитываемый от нуля, то есть позицию в массиве символов исходного кода. Первое число — позиция начала узла, второе — позиция его конца.code.slice(node.range[0], node.range[1])должно содержать текст узла. Этот диапазон не включает пробелы и скобки, окружающие узел. -
loc(SourceLocation) не должно бытьnull. Свойствоlocв ESTree определено как допускающее значение 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
npm install --save-dev eslint-parser-myparser
yarn
yarn add --dev eslint-parser-myparser
pnpm
pnpm add --save-dev eslint-parser-myparser
bun
bun add --dev eslint-parser-myparser
Затем добавьте пользовательский парсер в файл конфигурации ESLint с помощью свойства languageOptions.parser. Например:
// eslint.config.js
const { defineConfig } = require("eslint/config");
const myparser = require("eslint-parser-myparser");
module.exports = defineConfig([
{
languageOptions: {
parser: myparser,
},
// ... rest of configuration
},
]);
При использовании устаревшего формата конфигурации укажите свойство parser в виде строки:
// .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:
// eslint.config.js
const { defineConfig } = require("eslint/config");
module.exports = defineConfig([
{
languageOptions: {
parser: require("./path/to/awesome-custom-parser"),
},
},
]);
Или, если используется устаревший формат конфигурации:
// .eslintrc.json
{
"parser": "./path/to/awesome-custom-parser.js"
}
© OpenJS Foundation and other contributors
Licensed under the MIT License.
https://eslint.org/docs/latest/extend/custom-parsers