ESLint опирается на промежуточное представление исходного кода — AST (Abstract Syntax Tree), которое формируется парсером. Основной парсер по умолчанию — Espree, реализующий разбор стандарта ECMAScript с поддержкой современных версий языка.
Плагины и правила ESLint не работают напрямую с текстом кода. Они зависят от структуры AST, которую возвращает парсер. Любое расхождение между ожиданиями плагина и фактическим AST приводит к ошибкам, пропуску правил или некорректному анализу.
Ключевая проблема заключается в том, что ESLint сам по себе не фиксирует единый формат AST для всех сценариев. Он лишь ожидает совместимость с ESTree-совместимым деревом, но конкретная реализация может отличаться.
Разные парсеры формируют различные AST даже при одинаковом исходном коде:
Каждое расширение меняет форму дерева: добавляются новые типы узлов,
изменяется структура выражений, появляются дополнительные поля
(typeAnnotation, range, loc,
parent).
Плагины ESLint, написанные под один AST, часто ломаются при переключении на другой парсер.
ESLint-правила используют селекторы AST:
CallExpressionMemberExpressionImportDeclarationЕсли парсер изменяет структуру узлов, селекторы перестают срабатывать.
Пример проблемы:
ArrowFunctionExpressionTSAsExpression, TSTypeAssertion)В TypeScript-окружении это проявляется особенно часто: один и тот же
синтаксис может иметь разные AST-формы в зависимости от конфигурации
parserOptions.
Плагины ESLint часто завязаны на внутренние API:
context.getSourceCode()context.report()При изменении версии ESLint меняется структура внутренних объектов.
Типичный сценарий конфликта:
Особенно критично это при использовании кастомных парсеров, так как они часто тестируются только на ограниченном наборе версий ESLint.
Поддержка JSX требует отдельного парсера или расширения синтаксиса. При использовании @babel/eslint-parser или аналогов появляются дополнительные узлы:
JSXElementJSXFragmentJSXOpeningElementПлагины, не учитывающие JSX AST, могут:
Аналогичная ситуация возникает с современными Stage 3–4 предложениями ECMAScript, такими как pipeline operator или decorators, где AST может радикально отличаться в зависимости от парсера.
@typescript-eslint/parser создаёт AST, который отличается не только синтаксически, но и семантически.
Основные отличия:
TSTypeReference,
TSInterfaceDeclaration)TSAsExpression,
NonNullExpression)Проблема возникает, когда плагин ожидает JavaScript AST, но получает TypeScript-расширение. В результате:
undefinedНекоторые плагины вынуждены реализовывать отдельные ветки логики для TypeScript AST, что усложняет поддержку.
Конфигурация parserOptions напрямую влияет на структуру
AST:
ecmaVersionsourceType: "module" | "script"ecmaFeatures.jsxРазличные комбинации параметров могут менять:
ImportDeclarationНеправильная настройка приводит к ситуации, когда:
Это создаёт ложное ощущение, что правило “сломалось”, хотя фактически изменился входной формат.
Плагины ESLint не изолированы. Они работают в одном дереве AST.
Если один плагин:
другой плагин может:
Особенно это заметно при комбинации:
Использование нестандартного парсера — частая причина несовместимости.
Типичные сценарии:
Каждый парсер может:
range,
loc)В результате плагины, ориентированные на стандартный ESTree, начинают работать непредсказуемо.
Многие правила ESLint написаны с предположением о фиксированной структуре узлов:
if (node.type === "CallExpression") {
node.callee.object.name
}
При изменении парсера:
callee может быть не MemberExpression, а
обёрткойobject может отсутствоватьЭто приводит к runtime-ошибкам:
Cannot read properties of undefinedЭволюция ESLint привела к значительным изменениям внутреннего API, особенно в новых архитектурных версиях. Плагины, ориентированные на старую модель:
В экосистеме возникает эффект “фрагментации”:
Типичные проявления проблем:
На уровне проекта это приводит к нестабильности качества кода: одна и та же база может проходить проверку локально и падать в CI.
Некоторые плагины фактически зависят от конкретного парсера, хотя формально это не указано:
Такие зависимости сложно обнаружить, пока не произойдёт смена парсера или обновление версии ESLint.
Проблемы совместимости возникают системно, поэтому их снижение обычно достигается архитектурными ограничениями:
Главный источник нестабильности — неоднородность AST в одном анализируемом контексте, где разные части системы ожидают разные структуры данных.