В основе работы ESLint лежит преобразование исходного кода в структуру, пригодную для анализа. Эту задачу выполняет парсер, который превращает текст JavaScript (или его диалекты) в абстрактное синтаксическое дерево (AST). Именно от качества и возможностей парсера зависит, какие конструкции языка доступны для анализа и насколько точно инструмент сможет интерпретировать код.
Стандартный парсер ESLint основан на Espree, который ориентирован на спецификацию ECMAScript и поддерживает актуальные версии стандарта языка. Однако современная экосистема JavaScript давно вышла за пределы «чистого» ECMAScript, что привело к необходимости использования отдельных парсеров.
Espree и аналогичные базовые реализации хорошо справляются с классическим JavaScript, но сталкиваются с ограничениями при обработке расширений языка:
Попытка обработать такие конструкции стандартным парсером приводит к синтаксическим ошибкам, даже если код корректен в контексте своей экосистемы. Это делает невозможным полноценный статический анализ без расширения слоя парсинга.
Архитектура ESLint построена так, чтобы логика анализа была независимой от синтаксиса. Разделение парсера и движка правил решает несколько фундаментальных задач.
Разные проекты используют разные расширения Jav * aScript:
Отдельный парсер позволяет адаптировать ESLint под конкретную среду без изменения ядра.
Каждый парсер формирует собственное AST-представление. Например, TypeScript-парсер добавляет узлы, описывающие типы, интерфейсы и дженерики. ESLint при этом продолжает работать через единый интерфейс обхода дерева, не привязываясь к конкретной реализации синтаксиса.
Правила ESLint написаны так, чтобы работать с абстрактной структурой данных, а не с конкретным языком. Это позволяет:
Процесс анализа начинается с конфигурации, где явно или неявно указывается используемый парсер. Далее происходит следующая цепочка:
Ключевой момент заключается в том, что ESLint не требует, чтобы все парсеры были идентичны. Важно лишь соблюдение контракта: предоставление корректного AST и метаданных о коде.
С развитием экосистемы появились специализированные парсеры, каждый из которых решает собственные задачи.
Парсер @typescript-eslint/parser расширяет стандартный
AST, добавляя поддержку типов и синтаксических конструкций TypeScript.
Он не просто «понимает» TypeScript, но и обеспечивает совместимость с
правилами ESLint через нормализацию структуры.
Особенность заключается в том, что часть узлов существует только на уровне типов и не влияет на runtime-код, но всё равно доступна для анализа.
@babel/eslint-parser используется для поддержки
экспериментальных предложений ECMAScript и нестандартных трансформаций.
Babel способен обрабатывать код, который ещё не вошёл в стандарт языка,
но активно используется в проектах.
Этот парсер важен в условиях быстрого развития JavaScript, когда новые синтаксические конструкции появляются раньше их стандартизации.
Vue и Svelte используют собственные парсеры, поскольку код в этих системах состоит не только из JavaScript, но и из шаблонов и декларативных блоков. Такие парсеры:
Выбор парсера напрямую определяет, какие правила могут быть применены. Если парсер не поддерживает определённый синтаксис, правила, работающие с ним, становятся недоступны.
Пример ситуации:
Это приводит к необходимости согласования парсера и набора плагинов.
Несмотря на единый принцип работы, разные парсеры могут по-разному представлять одни и те же конструкции. Это создаёт несколько типов сложностей:
Для решения этих проблем используется слой адаптации внутри плагинов, который нормализует данные перед анализом.
Парсинг является одной из самых затратных операций в процессе линтинга. Отдельные парсеры позволяют оптимизировать этот этап:
В крупных проектах разница в скорости между универсальным и специализированным парсером становится критичной.
Разделение парсера и ядра ESLint стало ключевым фактором масштабируемости инструмента. Оно позволило экосистеме развиваться параллельно с самим языком, не ломая обратную совместимость.
Появление новых синтаксических возможностей перестало требовать переписывания анализатора — достаточно подключить новый парсер, который корректно интерпретирует код и предоставляет совместимый AST.