Spec-Zone.ru › ESLint

Руководство по настраиваемым правилам

В этом руководстве показано, как создать настраиваемое правило для ESLint и распространить его с помощью плагина.

Вы можете создавать настраиваемые правила для проверки соответствия вашего кода определенным ожиданиям и определения действий в случае несоответствия. Плагины упаковывают настраиваемые правила и другие настройки, позволяя легко делиться ими и повторно использовать их в различных проектах.

Чтобы узнать больше о настраиваемых правилах и плагинах, обратитесь к следующей документации:

  • Настраиваемые правила
  • Плагины

Зачем создавать настраиваемое правило?

Создавайте настраиваемое правило, если встроенные правила ESLint и опубликованные сообществом настраиваемые правила не удовлетворяют ваши потребности. Вы можете создать настраиваемое правило для соблюдения лучшей практики для вашей компании или проекта, предотвращения повторения определенной ошибки или обеспечения соблюдения руководства по стилю.

Прежде чем создавать настраиваемое правило, которое не специфично для вашей компании или проекта, стоит поискать в интернете, не опубликовал ли кто-нибудь плагин с настраиваемым правилом, решающим вашу задачу. Вероятно, такое правило уже существует.

Предварительные требования

Перед началом убедитесь, что в вашей среде разработки установлено следующее:

  • Node.js
  • npm

Это руководство также предполагает, что вы имеете базовые знания о ESLint и правилах ESLint.

Настраиваемое правило

Настраиваемое правило в этом руководстве требует, чтобы все const переменные с именем foo были присвоены строковый литерал "bar". Правило определено в файле enforce-foo-bar.js. Правило также предлагает заменить любое другое значение, присвоенное const foo, на "bar".

Например, предположим, что у вас есть следующий foo.js файл:

// foo.js

const foo = "baz123";

Запуск ESLint с правилом выведет "baz123" как неверное значение для переменной foo. Если ESLint работает в режиме автоматической коррекции, ESLint исправит файл, чтобы он содержал следующее:

// foo.js

const foo = "bar";

Шаг 1: Настройка проекта

Сначала создайте новый проект для вашего настраиваемого правила. Создайте новую директорию, инициализируйте новый проект npm в ней и создайте новый файл для настраиваемого правила:

mkdir eslint-custom-rule-example # create directory
cd eslint-custom-rule-example # enter the directory
npm init -y # init new npm project
touch enforce-foo-bar.js # create file enforce-foo-bar.js

Шаг 2: Создайте шаблон файла правила

В файле enforce-foo-bar.js добавьте структуру для enforce-foo-bar настраиваемого правила. Также добавьте объект meta с базовой информацией о правиле.

// enforce-foo-bar.js

module.exports = {
    meta: {
       // TODO: add metadata
    },
    create(context) {
        return {
            // TODO: add callback function(s)
        };
    }
};

Шаг 3: Добавьте метаданные правила

Прежде чем писать правило, добавьте метаданные в объект правила. ESLint использует эту информацию при запуске правила.

Начните с экспорта объекта с свойством meta, содержащим метаданные правила, такие как тип правила, документация и возможность исправления. В этом случае тип правила — «проблема», описание — «Требование, чтобы переменная с именем foo могла быть назначена только значением ‘bar’», и правило может быть исправлено путем изменения кода.

// enforce-foo-bar.js

module.exports = {
    meta: {
        type: "problem",
        docs: {
            description: "Enforce that a variable named `foo` can only be assigned a value of 'bar'.",
        },
        fixable: "code",
        schema: []
    },
    create(context) {
        return {
            // TODO: add callback function(s)
        };
    }
};

Чтобы узнать больше о метаданных правила, обратитесь к Структуре правила.

Шаг 4: Добавьте методы посетителя правила

Определите функцию create правила, которая принимает объект context и возвращает объект со свойством для каждого типа узла синтаксического анализа, который вы хотите обработать. В данном случае вы хотите обработать узлы VariableDeclarator. Вы можете выбрать любой тип узла ESTree или селектор.

Подсказка

Вы можете просмотреть AST для любого кода JavaScript с помощью Code Explorer. Это полезно для определения типов узлов, которые вы хотите нацелить.

Внутри метода посетителя VariableDeclarator проверьте, представляет ли узел объявление переменной const, если ее имя foo, и если оно не присвоено строке "bar". Вы делаете это, оценивая node, переданное методу VariableDeclaration.

Если объявление const foo присвоено значение "bar", то правило ничего не делает. Если const foo не присвоено значение "bar", тогда context.report() сообщает об ошибке ESLint. Отчет об ошибке содержит информацию об ошибке и о том, как ее исправить.

// enforce-foo-bar.js

module.exports = {
    meta: {
        type: "problem",
        docs: {
            description: "Enforce that a variable named `foo` can only be assigned a value of 'bar'."
        },
        fixable: "code",
        schema: []
    },
    create(context) {
        return {

            // Performs action in the function on every variable declarator
            VariableDeclarator(node) {

                // Check if a `const` variable declaration
                if (node.parent.kind === "const") {

                    // Check if variable name is `foo`
                    if (node.id.type === "Identifier" && node.id.name === "foo") {

                        // Check if value of variable is "bar"
                        if (node.init && node.init.type === "Literal" && node.init.value !== "bar") {

                            /*
                             * Report error to ESLint. Error message uses
                             * a message placeholder to include the incorrect value
                             * in the error message.
                             * Also includes a `fix(fixer)` function that replaces
                             * any values assigned to `const foo` with "bar".
                             */
                            context.report({
                                node,
                                message: 'Value other than "bar" assigned to `const foo`. Unexpected value: {{ notBar }}.',
                                data: {
                                    notBar: node.init.value
                                },
                                fix(fixer) {
                                    return fixer.replaceText(node.init, '"bar"');
                                }
                            });
                        }
                    }
                }
            }
        };
    }
};

Шаг 5: Настройка тестирования

После написания правила можно проверить его, чтобы убедиться, что оно работает как ожидается.

ESLint предоставляет встроенный класс RuleTester для тестирования правил. Вам не нужно использовать сторонние библиотеки тестирования для проверки правил ESLint, но RuleTester работает без проблем с такими инструментами, как Mocha и Jest.

Далее создайте файл для тестов, enforce-foo-bar.test.js:

touch enforce-foo-bar.test.js

В файле тестов вы будете использовать пакет eslint.

Установите его как зависимость разработки:

npm install eslint --save-dev

И добавьте скрипт теста в ваш файл package.json для запуска тестов:

// package.json
{
    // ...other configuration
    "scripts": {
        "test": "node enforce-foo-bar.test.js"
    },
    // ...other configuration
}

Шаг 6: Написание теста

Чтобы написать тест с использованием RuleTester, импортируйте класс и ваше настраиваемое правило в файл enforce-foo-bar.test.js.

Метод RuleTester#run() тестирует правило на корректных и некорректных тестовых примерах. Если правило не проходит ни одну из тестовых ситуаций, этот метод выбросит ошибку. RuleTester требует наличия как минимум одного корректного и одного некорректного тестового примера.

// enforce-foo-bar.test.js
const {RuleTester} = require("eslint");
const fooBarRule = require("./enforce-foo-bar");

const ruleTester = new RuleTester({
  // Must use at least ecmaVersion 2015 because
  // that's when `const` variables were introduced.
  languageOptions: { ecmaVersion: 2015 }
});

// Throws error if the tests in ruleTester.run() do not pass
ruleTester.run(
  "enforce-foo-bar", // rule name
  fooBarRule, // rule code
  { // checks
    // 'valid' checks cases that should pass
    valid: [{
      code: "const foo = 'bar';",
    }],
    // 'invalid' checks cases that should not pass
    invalid: [{
      code: "const foo = 'baz';",
      output: 'const foo = "bar";',
      errors: 1,
    }],
  }
);

console.log("All tests passed!");

Запустите тест с помощью следующей команды:

npm test

Если тест пройден, в консоли должно быть следующее:

All tests passed!

Шаг 7: Упакуйте настраиваемое правило в плагин

Теперь, когда вы написали настраиваемое правило и проверили, что оно работает, вы можете включить его в плагин. Используя плагин, вы можете поделиться правилом в пакете npm, чтобы использовать его в других проектах.

Создайте файл для плагина:

touch eslint-plugin-example.js

Теперь напишите код плагина. Плагины — это просто экспортированные объекты JavaScript. Чтобы включить правило в плагин, включите его в объект rules плагина, который содержит пары «ключ-значение» имен правил и их исходного кода.

Чтобы узнать больше о создании плагинов, обратитесь к Создание плагинов.

// eslint-plugin-example.js

const fooBarRule = require("./enforce-foo-bar");
const plugin = { rules: { "enforce-foo-bar": fooBarRule } };
module.exports = plugin;

Шаг 8: Использование плагина локально

Вы можете использовать локально определенный плагин для выполнения настраиваемого правила в вашем проекте. Чтобы использовать локальный плагин, укажите путь к плагину в свойстве plugins файла конфигурации ESLint.

Вы можете захотеть использовать локально определенный плагин в следующих случаях:

  • Вы хотите протестировать плагин перед публикацией его в npm.
  • Вы хотите использовать плагин, но не хотите публиковать его в npm.

Перед добавлением плагина в проект создайте конфигурацию ESLint для вашего проекта с помощью плоского файла конфигурации, eslint.config.js:

touch eslint.config.js

Затем добавьте следующий код в eslint.config.js:

// eslint.config.js
"use strict";

// Import the ESLint plugin locally
const eslintPluginExample = require("./eslint-plugin-example");

module.exports = [
    {
        files: ["**/*.js"],
        languageOptions: {
            sourceType: "commonjs",
            ecmaVersion: "latest",
        },
        // Using the eslint-plugin-example plugin defined locally
        plugins: {"example": eslintPluginExample},
        rules: {
            "example/enforce-foo-bar": "error",
        },
    }
]

Прежде чем вы сможете протестировать правило, вам необходимо создать файл для тестирования правила.

Создайте файл example.js:

touch example.js

Добавьте следующий код в example.js:

// example.js

function correctFooBar() {
  const foo = "bar";
}

function incorrectFoo(){
  const foo = "baz"; // Problem!
}

Теперь вы готовы протестировать настраиваемое правило с помощью локально определенного плагина.

Запустите ESLint на example.js:

npx eslint example.js

Это выведет следующее в терминале:

/<path-to-directory>/eslint-custom-rule-example/example.js
  8:11  error  Value other than "bar" assigned to `const foo`. Unexpected value: baz  example/enforce-foo-bar

✖ 1 problem (1 error, 0 warnings)
  1 error and 0 warnings potentially fixable with the `--fix` option.

Шаг 9: Публикация плагина

Чтобы опубликовать плагин, содержащий правило, в npm, вам необходимо настроить package.json. Добавьте следующее в соответствующие поля:

  1. "name": Уникальное имя для пакета. В npm не может быть другого пакета с таким же именем.
  2. "main": Относительный путь к файлу плагина. В соответствии с этим примером, путь — "eslint-plugin-example.js".
  3. "description": Описание пакета, которое видно в npm.
  4. "peerDependencies": Добавьте "eslint": ">=9.0.0" в качестве зависимости peer. Любая версия, большая или равная этой, необходима для использования плагина. Объявление eslint как peer-зависимости требует, чтобы пользователи добавляли пакет в проект отдельно от плагина.
  5. "keywords": Включите стандартные ключевые слова ["eslint", "eslintplugin", "eslint-plugin"], чтобы пакет было легко найти. Вы также можете добавить другие ключевые слова, которые могут быть актуальны для вашего плагина.

Полный аннотированный пример того, как должен выглядеть файл package.json плагина:

// package.json
{
  // Name npm package.
  // Add your own package name. eslint-plugin-example is taken!
  "name": "eslint-plugin-example",
  "version": "1.0.0",
  "description": "ESLint plugin for enforce-foo-bar rule.",
  "main": "eslint-plugin-example.js", // plugin entry point
  "scripts": {
    "test": "node enforce-foo-bar.test.js"
  },
  // Add eslint>=9.0.0 as a peer dependency.
  "peerDependencies": {
    "eslint": ">=9.0.0"
  },
  // Add these standard keywords to make plugin easy to find!
  "keywords": [
    "eslint",
    "eslintplugin",
    "eslint-plugin"
  ],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "eslint": "^9.0.0"
  }
}

Чтобы опубликовать пакет, запустите npm publish и следуйте инструкциям в командной строке.

Вы увидите пакет в npm!

Шаг 10: Использование опубликованного настраиваемого правила

Далее вы можете использовать опубликованный плагин.

Выполните следующую команду в своем проекте, чтобы загрузить пакет:

npm install --save-dev eslint-plugin-example # Add your package name here

Обновите eslint.config.js для использования упакованной версии плагина:

// eslint.config.js
"use strict";

// Import the plugin downloaded from npm
const eslintPluginExample = require("eslint-plugin-example");

// ... rest of configuration

Теперь вы готовы протестировать настраиваемое правило.

Запустите ESLint на файле example.js, который вы создали на шаге 8, теперь с загруженным плагином:

npx eslint example.js

Это выведет следующее в терминале:

/<path-to-directory>/eslint-custom-rule-example/example.js
  8:11  error  Value other than "bar" assigned to `const foo`. Unexpected value: baz  example/enforce-foo-bar

✖ 1 problem (1 error, 0 warnings)
  1 error and 0 warnings potentially fixable with the `--fix` option.

Как вы можете видеть в вышеуказанном сообщении, вы можете фактически исправить проблему с --fix флажком, исправив присвоение переменной на "bar".

Запустите ESLint еще раз с флагом --fix:

npx eslint example.js --fix

В терминале нет сообщений об ошибках, но вы можете увидеть примененное исправление в example.js. Вы должны увидеть следующее:

// example.js

// ... rest of file

function incorrectFoo(){
  const foo = "bar"; // Fixed!
}

Заключение

В этом руководстве вы создали настраиваемое правило, которое требует, чтобы все const переменные с именем foo были присвоены строке "bar", и предлагает заменить любое другое значение, присвоенное const foo, на "bar". Вы также добавили правило в плагин и опубликовали плагин в npm.

Сделав это, вы изучили практики, которые можете применять для создания других настраиваемых правил и плагинов:

  1. Создание пользовательского правила ESLint
  2. Тестирование пользовательского правила
  3. Создание плагина для правила
  4. Публикация плагина
  5. Использование правила из плагина

Просмотреть код учебника

Вы можете просмотреть аннотированный исходный код учебника здесь.

© OpenJS Foundation and other contributors
Licensed under the MIT License.
https://eslint.org/docs/latest/extend/custom-rule-tutorial

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API