Каждое правило ESLint представляет собой модуль, содержащий не только логику анализа исходного кода, но и специальный объект метаданных. Метаданные позволяют ESLint и внешним инструментам получать информацию о назначении правила, уровне его зрелости, возможности автоматического исправления, наличии рекомендаций и других характеристиках.
Объект метаданных располагается в свойстве meta
экспортируемого правила:
module.exports = {
meta: {
// метаданные правила
},
create(context) {
return {};
}
};
Метаданные не участвуют непосредственно в анализе AST, однако играют важную роль при работе редакторов кода, генерации документации, автоматическом исправлении ошибок и конфигурировании наборов правил.
Типичная структура метаданных выглядит следующим образом:
module.exports = {
meta: {
type: "problem",
docs: {
description: "Disallow foo identifiers",
recommended: true
},
fixable: "code",
hasSuggestions: true,
schema: [],
messages: {
forbiddenFoo: "Identifier 'foo' is not allowed."
}
},
create(context) {
return {};
}
};
Основными свойствами являются:
typedocsfixablehasSuggestionsschemamessagesdeprecatedreplacedByНекоторые из них обязательны только в определённых ситуациях.
Поле type определяет категорию правила. ESLint
использует эту информацию для классификации найденных проблем.
Допустимые значения:
| Значение | Назначение |
|---|---|
problem |
Ошибки, потенциально приводящие к неправильной работе программы |
suggestion |
Улучшение структуры и качества кода |
layout |
Форматирование и оформление кода |
Используется для обнаружения реальных ошибок.
Пример:
meta: {
type: "problem"
}
Подобные правила могут обнаруживать:
Предназначен для рекомендаций по улучшению кода.
meta: {
type: "suggestion"
}
Такие правила могут:
Используется исключительно для оформления.
meta: {
type: "layout"
}
Примеры:
Раздел docs содержит информацию о документации
правила.
Пример:
meta: {
docs: {
description: "Disallow foo identifiers",
recommended: true
}
}
Краткое описание назначения правила.
docs: {
description: "Disallow foo identifiers"
}
Описание используется:
Описание должно быть коротким и понятным.
Флаг указывает, входит ли правило в рекомендуемый набор.
docs: {
description: "Disallow foo identifiers",
recommended: true
}
Значения:
recommended: true
или
recommended: false
Если правило включено в рекомендуемую конфигурацию, пользователи получают его автоматически после подключения набора рекомендаций.
Во многих современных плагинах указывается ссылка на документацию правила.
docs: {
description: "Disallow foo identifiers",
url: "https://example.com/rules/no-foo"
}
Редакторы кода могут отображать эту ссылку непосредственно в сообщениях ESLint.
Поле fixable сообщает ESLint, что правило поддерживает
автоматическое исправление.
Допустимые значения:
fixable: "code"
или
fixable: "whitespace"
Используется, когда правило изменяет программную логику или структуру кода.
meta: {
fixable: "code"
}
Пример автоматического исправления:
context.report({
node,
messageId: "replaceVar",
fix(fixer) {
return fixer.replaceText(node, "let");
}
});
Предназначено для исправлений, связанных только с пробельными символами.
meta: {
fixable: "whitespace"
}
Примеры:
Если правило использует функцию fix, но не содержит
свойство:
fixable: "code"
или
fixable: "whitespace"
ESLint выдаст ошибку при загрузке правила.
Таким образом предотвращается случайное создание исправлений без соответствующего объявления.
Начиная с современных версий ESLint правила могут не только автоматически исправлять код, но и предлагать варианты исправлений.
Для этого используется:
meta: {
hasSuggestions: true
}
Предложения отображаются в редакторах:
Пользователь самостоятельно выбирает подходящий вариант исправления.
Метаданные:
meta: {
hasSuggestions: true
}
Отчёт:
context.report({
node,
messageId: "avoidVar",
suggest: [
{
messageId: "replaceWithLet",
fix(fixer) {
return fixer.replaceText(node, "let");
}
}
]
});
Если правило использует массив:
suggest: []
но в метаданных отсутствует:
hasSuggestions: true
ESLint завершит работу с ошибкой.
Свойство schema описывает структуру параметров
правила.
Оно позволяет:
Если правило не принимает параметры:
meta: {
schema: []
}
Это наиболее распространённый вариант.
Предположим, правило принимает настройку:
{
allowFoo: true
}
Тогда схема может выглядеть следующим образом:
meta: {
schema: [
{
type: "object",
properties: {
allowFoo: {
type: "boolean"
}
},
additionalProperties: false
}
]
}
Конфигурация:
{
"my-plugin/no-foo": [
"error",
{
allowFoo: true
}
]
}
Будет успешно обработана.
Однако настройка:
{
"my-plugin/no-foo": [
"error",
{
allowFoo: "yes"
}
]
}
приведёт к ошибке валидации, поскольку ожидается логическое значение.
Поле schema базируется на стандарте JSON Schema.
Поддерживаются такие конструкции, как:
type
properties
required
enum
items
minimum
maximum
oneOf
anyOf
allOf
Пример ограничения набора значений:
schema: [
{
enum: ["always", "never"]
}
]
Допустимая конфигурация:
["error", "always"]
Недопустимая:
["error", "sometimes"]
Раздел messages содержит шаблоны сообщений об
ошибках.
Вместо непосредственной передачи текста в
context.report() рекомендуется использовать идентификаторы
сообщений.
Метаданные:
meta: {
messages: {
forbiddenFoo: "Identifier 'foo' is forbidden."
}
}
Использование:
context.report({
node,
messageId: "forbiddenFoo"
});
Использование идентификаторов обеспечивает:
Сообщения могут содержать плейсхолдеры.
Метаданные:
messages: {
forbiddenName:
"Identifier '{{name}}' is forbidden."
}
Отчёт:
context.report({
node,
messageId: "forbiddenName",
data: {
name: node.name
}
});
Результат:
Identifier 'foo' is forbidden.
Если правило считается устаревшим, используется флаг:
meta: {
deprecated: true
}
Это сообщает пользователям и инструментам, что правило больше не рекомендуется к использованию.
Наиболее распространённые причины:
Для устаревших правил можно указать замену.
meta: {
deprecated: true,
replacedBy: ["new-rule"]
}
При просмотре документации становится понятно, каким правилом следует заменить старое.
Иногда одно правило разбивается на несколько новых.
meta: {
deprecated: true,
replacedBy: [
"new-rule-a",
"new-rule-b"
]
}
module.exports = {
meta: {
type: "suggestion",
docs: {
description:
"Disallow foo identifiers",
recommended: true,
url:
"https://example.com/rules/no-foo"
},
fixable: "code",
hasSuggestions: true,
schema: [
{
type: "object",
properties: {
allowFoo: {
type: "boolean"
}
},
additionalProperties: false
}
],
messages: {
forbiddenFoo:
"Identifier 'foo' is forbidden.",
replaceWithBar:
"Replace with 'bar'."
}
},
create(context) {
return {};
}
};
В данном примере правило:
Большинство возможностей context.report() опирается на
сведения из объекта meta.
Соответствие выглядит следующим образом:
| Возможность | Свойство meta |
|---|---|
| Автоисправление | fixable |
| Предложения | hasSuggestions |
| Идентификаторы сообщений | messages |
| Настройки правила | schema |
| Документация | docs |
| Категория правила | type |
Из-за этой взаимосвязи объект meta фактически выступает
контрактом между правилом, ядром ESLint, редакторами кода и
инструментами экосистемы.
При разработке собственных правил обычно придерживаются следующих принципов:
type.docs.description.messageId вместо строковых сообщений
внутри context.report().schema даже для простых настроек.fixable только при действительно безопасном
исправлении.hasSuggestions для неоднозначных вариантов
исправления.docs.url.deprecated и
replacedBy.Грамотно оформленные метаданные делают правило полноценным элементом экосистемы ESLint, обеспечивая корректную интеграцию с редакторами, конфигураторами, генераторами документации и механизмами автоматического исправления кода.