Класс Linter

Назначение и роль в архитектуре ESLint

Класс Linter представляет собой низкоуровневый программный интерфейс, реализующий механизм анализа исходного кода на соответствие набору правил. Он используется тогда, когда требуется встроить линтинг непосредственно в приложение или инструмент сборки без запуска CLI-обвязки.

В отличие от высокоуровневых механизмов конфигурации через файлы .eslintrc и командную строку, Linter работает как самостоятельный вычислительный модуль: ему передаются код, конфигурация и правила, после чего он возвращает структурированный результат анализа.

Основная ответственность класса:

  • синтаксический и семантический разбор исходного кода
  • применение набора правил к абстрактному представлению программы
  • генерация списка нарушений (messages)
  • опциональное автоматическое исправление кода
  • управление регистрацией пользовательских правил

Класс является частью внутреннего API ESLint и часто используется в инструментах, интегрирующих анализ кода в редакторы, серверные пайплайны и кастомные системы проверки качества.


Общая модель работы

Процесс анализа через Linter можно представить как последовательность этапов:

  1. Парсинг исходного кода в AST (Abstract Syntax Tree)
  2. Построение контекста анализа (SourceCode)
  3. Инициализация набора правил
  4. Обход AST и применение правил
  5. Сбор сообщений об ошибках и предупреждениях
  6. (опционально) применение автофиксов

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


Создание экземпляра Linter

Базовая форма использования заключается в создании экземпляра класса:

import { Linter } from "eslint";

const linter = new Linter();

После создания экземпляр может многократно использоваться для анализа различных фрагментов кода.


Метод verify

Основной метод анализа — verify.

Сигнатура:

linter.verify(code, config, options);

Параметры:

  • code — строка исходного JavaScript-кода
  • config — объект конфигурации правил
  • options — дополнительные параметры анализа

Возвращаемое значение — массив сообщений о проблемах.

Каждое сообщение содержит:

  • ruleId — идентификатор правила
  • message — текст ошибки
  • line, column — позиция в коде
  • severity — уровень (warning/error)
  • nodeType — тип AST-узла
  • fix — данные для автоматического исправления (если доступно)

Пример:

const messages = linter.verify("const a = 1", {
  rules: {
    semi: "error"
  }
});

console.log(messages);

Конфигурация правил

Конфигурация передаётся в виде объекта, содержащего секцию rules.

{
  rules: {
    "no-unused-vars": "error",
    "no-console": "warn"
  }
}

Возможные значения:

  • "off" или 0 — отключено
  • "warn" или 1 — предупреждение
  • "error" или 2 — ошибка

Также поддерживается расширенная форма:

"no-console": ["warn", { allow: ["warn", "error"] }]

Метод verifyAndFix

Метод verifyAndFix расширяет функциональность verify, добавляя автоматическое исправление кода.

const result = linter.verifyAndFix(code, config);

Результат содержит:

  • messages — список найденных проблем
  • output — исправленный код

Пример:

const result = linter.verifyAndFix("var a = 1", {
  rules: {
    "no-var": "error"
  }
});

console.log(result.output);

Регистрация пользовательских правил

Класс Linter позволяет добавлять собственные правила через defineRule.

linter.defineRule("no-foo", {
  create(context) {
    return {
      Identifier(node) {
        if (node.name === "foo") {
          context.report({
            node,
            message: "Использование foo запрещено"
          });
        }
      }
    };
  }
});

Структура правила:

  • create(context) — функция, возвращающая набор обработчиков AST
  • обработчики соответствуют типам узлов AST
  • context.report — механизм генерации сообщения

Контекст выполнения правила

Объект context предоставляет API для взаимодействия с анализируемым кодом:

  • context.getSourceCode() — доступ к исходному коду
  • context.report() — регистрация нарушения
  • context.options — параметры правила

Пример использования:

create(context) {
  const sourceCode = context.getSourceCode();

  return {
    Program() {
      const text = sourceCode.getText();
    }
  };
}

Работа с AST и SourceCode

Linter оперирует абстрактным синтаксическим деревом, которое строится на основе входного кода.

Каждый узел AST содержит:

  • тип конструкции (VariableDeclaration, FunctionDeclaration)
  • диапазон символов (range)
  • координаты (loc)

SourceCode предоставляет:

  • доступ к исходному тексту
  • методы навигации по токенам
  • утилиты для анализа комментариев

Производительность и повторное использование экземпляра

Экземпляр Linter не требует пересоздания для каждого файла. Повторное использование:

  • снижает накладные расходы на инициализацию правил
  • уменьшает время анализа в пакетных операциях
  • позволяет кэшировать внутренние структуры

Однако состояние правил должно оставаться статeless, так как один экземпляр может использоваться параллельно в разных контекстах анализа.


Обработка ошибок и исключений

Во время работы Linter может выбрасывать ошибки в случаях:

  • некорректной конфигурации правил
  • синтаксических ошибок парсинга (в зависимости от настроек)
  • отсутствующих плагинов или правил

Ошибки правил обычно связаны с некорректной реализацией create или обращением к несуществующим свойствам AST.


Режимы анализа

Linter поддерживает различные режимы, определяемые конфигурацией:

  • стандартный анализ JavaScript
  • анализ с кастомным парсером
  • поддержка экспериментальных синтаксисов через parser options

Пример:

linter.verify(code, {
  parserOptions: {
    ecmaVersion: 2021,
    sourceType: "module"
  }
});

Ограничения Linter API

Несмотря на гибкость, Linter имеет ряд ограничений:

  • не управляет файловой системой
  • не выполняет разрешение зависимостей модулей
  • не применяет конфигурации .eslintrc автоматически
  • не кэширует результаты между вызовами без внешней логики

Эти задачи делегируются CLI-инструменту ESLint или внешним интеграциям.


Взаимодействие с системой правил ESLint

Класс Linter является ядром исполнения правил, но сам по себе не определяет их набор. Правила подключаются через:

  • defineRule
  • передаваемую конфигурацию
  • сторонние плагины (вручную интегрируемые)

Каждое правило выполняется в изолированном контексте и реагирует на события обхода AST, что формирует событийно-ориентированную модель анализа.