Архитектура линтинга в JavaScript опирается на разделение ответственности между парсером, ядром линтера и плагинами правил. Парсер преобразует исходный код в абстрактное синтаксическое дерево (AST), ядро анализирует структуру и применяет правила, а плагины расширяют набор проверок. Любое нарушение совместимости между этими компонентами приводит к ошибкам анализа, ложным срабатываниям или невозможности выполнения правил.
Парсер определяет форму AST, с которой работает вся система правил. В экосистеме ESLint по умолчанию используется парсер Espree, реализующий стандарт ESTree-совместимое дерево.
Ключевые задачи парсера:
Любой плагин ESLint опирается на структуру AST, поэтому несовместимость на уровне парсера автоматически ломает правила анализа.
Большинство парсеров ориентируются на спецификацию ESTree. Это де-факто стандарт описания JavaScript AST.
Основные элементы ESTree:
Плагины ESLint предполагают наличие этих узлов. Если парсер вводит собственные расширения без обратной совместимости, правила могут перестать работать.
В реальных проектах используются несколько ключевых парсеров:
Каждый из этих парсеров может формировать AST с отличиями, которые влияют на совместимость плагинов.
Несовместимость чаще всего проявляется не в синтаксисе языка, а в деталях структуры дерева:
TSInterfaceDeclaration против
отсутствия аналогов в стандартном AST)parent, loc,
range)Плагины, рассчитанные на один тип AST, могут некорректно работать с другим.
Конфигурация parserOptions определяет поведение парсера
и напрямую влияет на то, какой AST будет сгенерирован.
Основные параметры:
ecmaVersion — версия стандарта ECMAScriptsourceType — script или
moduleecmaFeatures.jsx — включение JSXНесовпадение ecmaVersion между парсером и ожиданиями
плагина часто приводит к ошибкам разбора или отсутствию нужных
узлов.
Плагин в ESLint представляет собой набор правил, которые работают с AST. Примеры популярных плагинов:
Каждый плагин предполагает определённую форму дерева и наличие специфических узлов.
Структурная зависимость
Семантическая зависимость
Type-aware зависимость
Некоторые парсеры предоставляют parserServices —
дополнительный слой информации поверх AST.
Пример:
Однако использование parserServices ограничивает
совместимость:
Совместимость часто нарушается на уровне зависимостей:
Типичный сценарий конфликта:
JSX является частым источником несовместимости:
Несовпадение парсера и плагина приводит к тому, что JSX воспринимается как неизвестный синтаксис.
Использование @typescript-eslint/parser вводит дополнительные уровни сложности:
Плагины, не рассчитанные на TypeScript AST, игнорируют или некорректно обрабатывают узлы.
@babel/eslint-parser создаёт AST, который может отличаться от стандартного ESTree из-за:
Некоторые плагины требуют нормализации AST перед анализом.
В практике разработки используются несколько подходов:
Новая модель конфигурации ESLint (flat config) усиливает явное управление парсером на уровне каждого набора файлов. Это уменьшает скрытые конфликты, но делает зависимости более явными:
Совместимость парсеров и плагинов можно разделить на несколько категорий:
Каждый класс требует отдельного подхода на уровне конфигурации и выбора инструментов, поскольку единая модель AST является лишь теоретической основой, но на практике реализуется разными парсерами с различной степенью отклонений.