Сегодняшний тред будет про инструменты работы с AST. AST (abstract syntax tree) — это представление исходного текста программы в виде дерева, компилятор использует его для кодогенерации. AST ещё используется для анализа исходного текста программы и его трансформации.
Чем AST может помочь в повседневной работе? Например, для сбора статистики о кодовой базе: какое количество раз и где используется определённая библиотека, вызов задеприкейченного API и т.п.
Причём можно правильно обработать нетривиальные случаи, например, когда библиотека импортируется под неканоничным названием, например import myLodash from 'lodash'.
AST используют бандлеры, для построения графа зависимостей между модулями и правильной сборки большого количество модулей в один бандл.
Есть инструменты, которые анализируют граф зависимостей. С их помощью можно находить модули, которые не используются в проекте, циклические зависимости, также с их помощью можно отрендерить визуальную схему графа.
Dependency Cruiser поддерживает JavaScript (ESM), TypeScript, CoffeeScript, CommonJS, AMD. Для визуализации использует формат dot (GraphViz) github.com/sverweij/depen…
Madge поддерживает только JavaScript (AMD, CommonJS, and ES6 modules), помоимо GraphViz может визуализировать граф с помщью D3 npmjs.com/package/madge
Вот так выглядит часть графа зависимостей Rollup:
У себя под капотом AST используют линтеры. В eslint есть возможность создавать новые правила с помощью специальных выражений, которые матчатся на узлы AST-дерева. Это может быть полезно для того, чтобы фиксировать договорённости в команде на уровне линтера eslint.org/docs/developer…
Тут немного неправильно. Поддерживает D3 другой Dependo, но он уже не поддерживается 2 года npmjs.com/package/dependo
На базе Babel можно создавать собственные инструменты. Например, в Яндекс Маркете при написании e2e-тестов для поиска React-компонентов в DOM-дерерве используется reselector.
Reselector позволяет использовать компоненты в css-селекторах без добавления служебных классов, всё благодаря парсингу исходного кода в AST github.com/lttb/reselector
Парсер Babel используется в очень многих проектах. Все их можно посмотреть на вкладке "Dependents" на npm npmjs.com/package/@babel…
До монорепизации парсер Babel жил как отдельный проект — "Babylon" npmjs.com/package/babylon
Помимо @babel/parser есть и другие. Один из самых популярных — acorn.js, который тоже используется как основа многих проектов npmjs.com/package/acorn
У него интересная история появления. Его разработал Marijn Haverbeke, как часть проекта по созданию инструмента для умного автодополнения кода на JS — tern.js. Этот проект был проспонсирован сообществом в 2013 году indiegogo.com/projects/tern-…
Tern.js был зарелижен, но не выдержал конкуренцию с TypeScript и Flow. Кроме статической типизации они предоставляют более качественное автодополнение кода по сравнению с tern. В итоге acorn.js стал самостоятельным проектом github.com/acornjs
Ещё один популярный парсер — Esprima, разработанный Ariya Hidayat. Он лежал в основе первых версий eslint npmjs.com/package/esprima
С появлением разных парсеров встал вопрос того, чтобы проекты имели возможность без проблем менять парсер, работающий под капотом. Для решения этой проблемы была разработана спецификация ESTree github.com/estree/estree
Ещё одна категория инструментов — инструменты для написания кодмодов (codemodes). Кодмод — это скрипт, в котором описываются синтаксические трансформации для самых разных целей.
Наиболее популярный кейс использования кодмодов — перевод проекта на новую версию библиотеки, которая обновила свой интерфейс.
Написать кодмод можно, используя любой парсер, например, @babel/parser sitepen.com/blog/codemods-…
Но в Babel есть поддержка для написания кодомодов с помощью специального API. Вот пример такого кодмода, который сделали в Google в рамках проекта по созданию полифилла для BigInt github.com/GoogleChromeLa…
Наибольшей популярностью пользуются специальные инструменты для написания кодмодов: Schematics, jscodeshift.
Schematics — это инструмент экосистемы Angular. Помогает при изменении структуры проекта в том числе на уровне трансформации кода angular.io/guide/schemati…
Но наиболее популярен инструмент от Facebook — jscodeshift. Он поддерживает flow, typescript, jsx. github.com/facebook/jscod…
Вот моя подборка кодмодов для jscodeshift. Заглядывайте, если будете писать свой кодмод, чтобы посмотреть на примеры github.com/myshov/codemod…
Самый интересный кодмод — экспериментальный конвертор функциональных React-компонентов в функциональные Vue-компоненты github.com/myshov/codemod…
При написании кодмодов очень помогает astexplorer — веб-приложение, с помощью которого можно проинспектировать AST-дерево. В нём есть поддержка очень многих языков и парсеров astexplorer.net
Ещё парсеры используются инструментами для анализа кода. Например, для "разминификации" кода github.com/shapesecurity/…
Ещё стоит упомянуть recast — библиотека для недеструктивного изменения исходного кода и генерации сорс мапов. Используется под капотом очень многих проектов в том числе jscodeshift github.com/benjamn/recast
Если хотите поподробнее узнать про AST, рекомендую интересный доклад Кирилла Черкашина из Google "Working with JavaScript Abstract Syntax Trees" (название на английском, но доклад на русском) youtube.com/watch?v=MPoO2x…
Если вас заинтересовала тема кодмодов, рекомендую посмотреть мой доклад, где я в подробностях рассказываю, что это такое и как их писать youtube.com/watch?v=GGb_ib…
На этом тред хочу закончить. Надеюсь, что этот тред вам был полезен и интересен. Спасибо за внимание :)