<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jude Agboola</title>
    <description>The latest articles on Forem by Jude Agboola (@marvinjude).</description>
    <link>https://forem.com/marvinjude</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F154875%2F2f1b4e3b-825d-42f5-b5b6-b4a48f988bec.jpeg</url>
      <title>Forem: Jude Agboola</title>
      <link>https://forem.com/marvinjude</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/marvinjude"/>
    <language>en</language>
    <item>
      <title>Abstract Syntax Trees and Practical Applications in JavaScript</title>
      <dc:creator>Jude Agboola</dc:creator>
      <pubDate>Sat, 21 Oct 2023 07:03:15 +0000</pubDate>
      <link>https://forem.com/marvinjude/abstract-syntax-trees-and-practical-applications-in-javascript-4a3</link>
      <guid>https://forem.com/marvinjude/abstract-syntax-trees-and-practical-applications-in-javascript-4a3</guid>
      <description>&lt;p&gt;Abstract Syntax Tree (AST) sounds like one of those daunting computer science terms at first but it becomes more approachable once you grasp the basics. The goal of this post is to give you a gentle introduction to AST while exploring practical applications in JavaScript.&lt;/p&gt;

&lt;p&gt;If you are trying to understand the basics of AST and its practical application then this article is for you, No prior assumptions about your knowledge of AST are made here, as we'll take a straightforward approach to explain the concepts. &lt;/p&gt;

&lt;p&gt;Instead of delving into the various stages that a program goes through before execution, this article is dedicated to enhancing your grasp of ASTs and demonstrating their practical applications in your JavaScript development journey. We'll achieve this by delving into tools that heavily rely on ASTs.&lt;/p&gt;

&lt;p&gt;To effectively follow along, a foundational understanding of JavaScript is required. We will explore various JavaScript tools and engage in hands-on coding in the later sections of this post.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: If you've already developed &lt;a href="https://babeljs.io/" rel="noopener noreferrer"&gt;Babel&lt;/a&gt; or &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; plugins, this article may not be as beneficial for you, as you're likely already familiar with the majority of the content covered here.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an Abstract Syntax Tree (AST)
&lt;/h2&gt;

&lt;p&gt;An abstract syntax tree (AST) is a hierarchical data structure used in computer science and programming language theory to represent the syntactic structure of source code or expressions in a programming language. It is often used as an intermediate representation during the compilation or interpretation of code.&lt;/p&gt;

&lt;p&gt;That's a lot of words, right? Let's make it simple&lt;/p&gt;

&lt;p&gt;Every piece of source code you write, whether it's intended for interpretation or compilation, undergoes a process known as parsing. During this process, the code is transformed into an Abstract Syntax Tree (AST), which serves as a structured, hierarchical representation of the code's underlying structure.&lt;/p&gt;

&lt;p&gt;Having established that, let's look at some code and its corresponding AST:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feoaukx4oddrnkijlkcr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feoaukx4oddrnkijlkcr2.png" alt="Some JavaScript and its corresponding AST"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Head over to &lt;a href="https://astexplorer.net/#/gist/e2b13cfd7074c4e5fc2afed54cdb6e3a/6e8dab825553c0e738013826f03129e4a416cf76" rel="noopener noreferrer"&gt;astexplorer&lt;/a&gt; to get a clearer view&lt;/p&gt;

&lt;p&gt;From the AST on the right, you'll notice the tree-like structure, we start out with the root node of type &lt;code&gt;Module&lt;/code&gt; which represents the whole file, and in that, we have the &lt;code&gt;body&lt;/code&gt; which holds other nodes of type &lt;code&gt;ImportDeclaration&lt;/code&gt;, &lt;code&gt;VariableDeclaration&lt;/code&gt;, and &lt;code&gt;VariableDeclarator&lt;/code&gt; which clearly describes each part of the code. &lt;/p&gt;

&lt;p&gt;Here, I'm using the &lt;a href="https://swc.rs/docs/usage/core#parse" rel="noopener noreferrer"&gt;swc parser&lt;/a&gt; to turn my JavaScript code into an AST. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please note that the AST may be a little different when you use a different parser but the idea is the same, &lt;em&gt;A tree-like structure that represents the source code&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Remember that we earlier established that every source gets parsed into an AST at some point before it gets compiled or interpreted. For example, platforms like Nodejs and chromium-based browsers use &lt;a href="https://v8.dev/" rel="noopener noreferrer"&gt;Gooogle's V8 engine&lt;/a&gt; behind the scenes to run JavaScript and of course, some AST parsing is always involved before the interpreter kicks in. I looked &lt;a href="https://github.com/v8/v8/tree/main/src/ast" rel="noopener noreferrer"&gt;V8's source and I discovered it uses its own internal parser&lt;/a&gt; to achieve this.&lt;/p&gt;

&lt;p&gt;Why do we then have other JavaScript parsers like &lt;a href="https://www.npmjs.com/package/@babel/parser" rel="noopener noreferrer"&gt;&lt;code&gt;babel parser&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://swc.rs/docs/usage/core#parse" rel="noopener noreferrer"&gt;swc parser&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/acorn" rel="noopener noreferrer"&gt;&lt;code&gt;acorn&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://github.com/eslint/espree" rel="noopener noreferrer"&gt;espree&lt;/a&gt; and the likes since JavaScript engines have their own internal parsers? &lt;/p&gt;

&lt;p&gt;They exist to provide a baseline for other tools to work with. For example, Transpilers, Minifiers, Linters, Codemods, Language Processors, and Obfuscators, use a parser behind the scenes to parse your code into an AST before applying transformations or performing any analysis whatsoever. &lt;/p&gt;

&lt;p&gt;When it comes to the practical usage of Abstract Syntax Trees (ASTs), our primary emphasis in this article will be on two widely used applications: &lt;strong&gt;Transpilers&lt;/strong&gt; and &lt;strong&gt;Linters&lt;/strong&gt;, particularly within the context of JavaScript.&lt;/p&gt;

&lt;p&gt;Here, we will see how ASTs play a crucial role in these applications, enabling developers to transform and analyze code effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Transpililation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7u76vl15kuvsfbfcxk4p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7u76vl15kuvsfbfcxk4p.png" title="A transpiler" alt="A transpiler"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A transpiler, short for &lt;em&gt;"source-to-source compiler"&lt;/em&gt;, is a software tool that translates source code written in one programming language into equivalent source code in the same language. Transpilers are commonly used for various purposes, such as language compatibility, syntax conversion, and code optimization.&lt;/p&gt;

&lt;p&gt;A frequent scenario involves syntax conversion, especially when dealing with compatibility issues. Imagine we have an application, and some of our users are on older web browsers. If we've adopted new syntax features like the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing" rel="noopener noreferrer"&gt;Nullish coalescing operator (??)&lt;/a&gt;, this could render our app unusable for those users. To address this, we must transform our code into an older, compatible syntax before deploying it to production. This ensures that our app remains accessible and functional for users with older browsers.&lt;/p&gt;

&lt;p&gt;As depicted in the image above, the Transpiler begins by &lt;strong&gt;parsing&lt;/strong&gt; the code into an Abstract Syntax Tree (AST). Following this, it proceeds to &lt;strong&gt;transform&lt;/strong&gt; the AST as needed before finally &lt;strong&gt;generating&lt;/strong&gt; code based on the modified AST.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://babel.io" rel="noopener noreferrer"&gt;Babel&lt;/a&gt; is a very common JavaScript Transpiler in the ecosystem and you may have used it directly or indirectly. We'll talk about how it uses AST in detail as we proceed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Linting
&lt;/h2&gt;

&lt;p&gt;Another software tool that is quite heavy on AST is Linters. A linter automatically analyzes and checks source code for potential errors, style violations, and programming best practices, helping developers identify and correct issues in their code during development.&lt;/p&gt;

&lt;p&gt;Before a linter can perform static analysis on your source code, it begins by parsing the code into an Abstract Syntax Tree (AST). Once this parsing is complete, the linter then proceeds to traverse the AST to identify and address potential issues within the code. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://eslint.org" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; is a widely adopted Linter within the JavaScript community. It boasts a robust plugin system, a comprehensive library of plugins, editor extensions, and presets (which are groups of plugins) that you can easily integrate into your project. We'll be talking about Eslint in detail later in this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  AST in Transpliers (Babel)
&lt;/h2&gt;

&lt;p&gt;Now that you've seen a couple of use cases for AST, we'll talk about Transpilers in detail. Specifically, we'd be using Babel and building a plugin.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://babel.io" rel="noopener noreferrer"&gt;Babel&lt;/a&gt; provides us with the toolchains to transpile our code, it has a CLI, a parser, and a plugin system, which means that you can write a &lt;strong&gt;plugin&lt;/strong&gt; that applies some transformation to your code. You can also ship that to &lt;a href="https://npmjs.com" rel="noopener noreferrer"&gt;npm&lt;/a&gt; so that anyone can install and use it.&lt;/p&gt;

&lt;p&gt;Code transpilation isn't specific to JavaScript, You can also add a level of transformation to your CSS source using tools like &lt;a href="https://postcss.org/" rel="noopener noreferrer"&gt;post-css&lt;/a&gt;. Most languages with a fairly mature ecosystem will probably have some tools to help with code transformation. &lt;/p&gt;

&lt;p&gt;Babel takes each of your files, generates an Abstract Syntax Tree (AST) based on your code, and passes this AST along with additional information to a Plugin. The Plugin can then apply the required transformations to the AST. After the transformations are complete, the resulting AST is converted back into code. &lt;strong&gt;It is important to note that without a plugin, Babel does absolutely nothing. You simply get the same code as output&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To go more practical on our knowledge of ASTs, we'll write a simple Babel plugin that removes &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/console/log" rel="noopener noreferrer"&gt;console logs&lt;/a&gt; from our code. Most JavaScript developers are guilty of littering their console.log while debugging. Our plugin will remove &lt;code&gt;console.log&lt;/code&gt; from our source code completely.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Most of the time, you'd want to use a &lt;a href="https://eslint.org/docs/latest/rules/no-console" rel="noopener noreferrer"&gt;linter to catch &lt;code&gt;console&lt;/code&gt; logs&lt;/a&gt; before you commit changes to your repository instead of just removing them at build time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Cloning Template
&lt;/h3&gt;

&lt;p&gt;As you may have noticed, this isn't a comprehensive &lt;em&gt;"How to Create a Babel Plugin"&lt;/em&gt; tutorial, so we won't spend too much time talking about how to Create a plugin. Instead, we'll begin with a template that I have exclusively designed for this article. This template is hosted in a &lt;a href="https://semaphoreci.com/blog/what-is-monorepo" rel="noopener noreferrer"&gt;monolithic repository&lt;/a&gt;, which simplifies the management of multiple packages within a single project. The template has two plugins in its &lt;a href="https://github.com/marvinjude/ast-and-practical-js-applications/tree/starter/plugins" rel="noopener noreferrer"&gt;plugin directory&lt;/a&gt;, one Babel plugin and another Eslint plugin. You can access the repository on &lt;a href="https://github.com/marvinjude/ast-and-practical-js-applications" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's start off by cloning the repository:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

https://github.com/marvinjude/ast-and-practical-js-applications.git


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Checkout to the &lt;code&gt;starter&lt;/code&gt; branch:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git checkout starter


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;This repository comprises two branches: &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;starter&lt;/code&gt;. The &lt;code&gt;starter&lt;/code&gt; branch serves as an empty template that we'll progressively build upfon throughout this article. On the other hand, the &lt;code&gt;main&lt;/code&gt; branch captures every modification we make to our &lt;code&gt;starter&lt;/code&gt; branch. Feel free to cross-reference the &lt;code&gt;main&lt;/code&gt; branch with your ongoing updates as necessary.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Installing Dependencies
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Before installing dependencies and eventually running the project, you must have &lt;a href="https://nodejs.org/en/download" rel="noopener noreferrer"&gt;node&lt;/a&gt; and &lt;a href="https://pnpm.io/installation" rel="noopener noreferrer"&gt;pnpm&lt;/a&gt; installed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To Install dependencies, run:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

pnpm install


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Template and Files
&lt;/h3&gt;

&lt;p&gt;As earlier mentioned, Our template is a monolithic repository managed by pnpm. The &lt;code&gt;plugins&lt;/code&gt; directory contains two packages that we'll be working on; &lt;code&gt;babel-plugin-remove-console&lt;/code&gt; and &lt;code&gt;eslint-plugin-emojify-array&lt;/code&gt;. I've also installed both packages in our project's root as you can see in &lt;a href="https://github.com/marvinjude/ast-and-practical-js-applications/blob/starter/package.json" rel="noopener noreferrer"&gt;package.json&lt;/a&gt; using the &lt;a href="https://pnpm.io/workspaces#workspace-protocol-workspace" rel="noopener noreferrer"&gt;pnpm's workspace protocol&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We have a handful of files and folders in our project, but we'll be focusing on a few of them in this section:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src&lt;/code&gt;&lt;/strong&gt; - source files to be transplied&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;plugins&lt;/code&gt;&lt;/strong&gt; - contains the plugins that we'll mostly be working on&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;.babelrc.js&lt;/code&gt;&lt;/strong&gt; - Babel configuration file where we specified the plugin(s) to be used(more details below)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;pnpm-workspace.yaml&lt;/code&gt;&lt;/strong&gt; - pnpm workspace configuration file where we specified what directory to store our packages&lt;/p&gt;
&lt;h3&gt;
  
  
  Configuring Babel
&lt;/h3&gt;

&lt;p&gt;Babel relies on a configuration file that allows us to customize the plugins, presets, and other settings used during the Babel transpilation process. The primary configuration file is typically named &lt;code&gt;.babelrc.js&lt;/code&gt;, although other formats are also supported (you can learn more about configuring Babel &lt;a href="https://babeljs.io/docs/config-files" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;There's a &lt;code&gt;.babelrc.js&lt;/code&gt; file in the root of our project where we've correctly configured Babel to use our plugin.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📂 .babelrc.js&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;babel-plugin-remove-console&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Writing a Babel plugin
&lt;/h3&gt;

&lt;p&gt;Before we dive into writing the plugin, let's examine a code snippet that utilizes &lt;code&gt;console.log&lt;/code&gt; and take a closer look at its corresponding Abstract Syntax Tree (AST). This should provide us with valuable insights on how to approach the development of our plugin.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fromiwels5750oxwdjlb3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fromiwels5750oxwdjlb3.png" alt="console.log AST"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check it out on &lt;a href="https://astexplorer.net/#/gist/5c991e865d1cfb7f2b5db255eb57d185/962ec0e153978e5587dd4cb544b6014fafb1695b" rel="noopener noreferrer"&gt;astexplorer&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One great feature of astexplorer is its ability to allow you to interactively explore the Tree by clicking on or selecting code, which then automatically focuses on the corresponding AST node. For instance, when you work with a function call, like &lt;code&gt;console.log&lt;/code&gt;, you'll notice that it's represented as a &lt;code&gt;CallExpression&lt;/code&gt;. In our task, we aim to eliminate &lt;code&gt;CallExpression&lt;/code&gt; nodes specifically for those that involve &lt;code&gt;console.log&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Our Babel plugin, named &lt;code&gt;babel-plugin-remove-console&lt;/code&gt; is housed within the &lt;code&gt;plugins&lt;/code&gt; directory. It's a standard JavaScript package, and its entry point can be found at &lt;code&gt;lib/index.js&lt;/code&gt; which is the core component of our plugin. When Babel processes your code, it invokes the function exported from this entry point and applies the specified transformations. It's time to write our plugin function! (make sure to update the file below on your local branch)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📂 &lt;code&gt;plugins/babel-plugin-remove-console/lib/index.js&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remove-console&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nc"&gt;CallExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;callee&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isMemberExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callee&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
          &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isIdentifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;console&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
          &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isIdentifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;log&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;What do we have going on here?&lt;/p&gt;

&lt;p&gt;First, Babel calls the plugin function with &lt;code&gt;api&lt;/code&gt; and &lt;code&gt;pluginOptions&lt;/code&gt;. Let's see what those are:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;api&lt;/code&gt;: This is the primary object provided to the plugin, and it grants the plugin access to various Babel methods, utilities, and information about the code being transformed. It contains properties like &lt;code&gt;types&lt;/code&gt; which has a bunch of utility methods like &lt;code&gt;isMemberExpression&lt;/code&gt; on it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;options&lt;/code&gt;: This is an optional parameter representing the configuration options passed to the plugin. The structure and content of the options object depend on how the plugin is configured in your Babel setup. These options allow you to customize the behaviour of the plugin based on your specific requirements.&lt;/p&gt;

&lt;p&gt;Notice that our plugin function returns an object. The object is expected to match &lt;a href="https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/babel-core/index.d.ts#L24-L31" rel="noopener noreferrer"&gt;this shape&lt;/a&gt;. &lt;code&gt;visitor&lt;/code&gt; is the most important property in the returned object, the name is derived from the &lt;a href="https://en.wikipedia.org/wiki/Visitor_pattern" rel="noopener noreferrer"&gt;Visitor Pattern&lt;/a&gt; — a software design pattern. &lt;code&gt;visitor&lt;/code&gt; is used by Babel to specify the part of the AST to be targeted for modification. With this pattern, we don't have to manually write a tree traversal to walk through the generated AST, we simply specify the node type and the transformation to be applied.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;visitor&lt;/code&gt; can consist of keys that correspond to specific node types in the AST, and the values associated with these keys are functions that define the behaviour of the plugin when it encounters nodes of those types. These functions are called with a &lt;code&gt;path&lt;/code&gt; argument representing the current node in the AST, and they determine what modifications, if any, should be made to the code.&lt;/p&gt;

&lt;p&gt;For example, if we could apply the same idea to a house so we can close the door to all the rooms, it would look something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

  &lt;span class="nx"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Room&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
      &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doorMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;closed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In our case, we're &lt;strong&gt;visiting&lt;/strong&gt; every &lt;code&gt;CallExpression&lt;/code&gt; and removing it if meets some conditions. &lt;/p&gt;

&lt;h3&gt;
  
  
  Running Babel
&lt;/h3&gt;

&lt;p&gt;Now that we've written a plugin, let's run Babel to the effect of the plugin.&lt;/p&gt;

&lt;p&gt;First, let us populate the files in our &lt;code&gt;src&lt;/code&gt; directory with some code that contains &lt;code&gt;console.log&lt;/code&gt;. Here's an example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John W. Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Babel is installed in the root of our project, so we can run Babel using the command &lt;code&gt;babel src --out-dir dist&lt;/code&gt;. For simplicity, I've added it to the &lt;code&gt;build&lt;/code&gt; script in &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

pnpm build


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, we should have all files in the &lt;code&gt;src&lt;/code&gt; directory in &lt;code&gt;dist&lt;/code&gt; with all &lt;code&gt;console.log&lt;/code&gt; calls removed. yay! &lt;/p&gt;

&lt;p&gt;Keep in mind that this is an example plugin and may not handle some edge cases correctly so you may not use it on your codebase. You should use &lt;a href="https://babeljs.io/docs/babel-plugin-transform-remove-console" rel="noopener noreferrer"&gt;babel-plugin-transform-remove-console&lt;/a&gt; instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  What other plugins can you write?
&lt;/h3&gt;

&lt;p&gt;Babel has all you need to move from writing a simple plugin that removes &lt;code&gt;console.log&lt;/code&gt; to writing much more &lt;a href="https://babeljs.io/docs/babel-plugin-transform-class-properties" rel="noopener noreferrer"&gt;complex&lt;/a&gt; &lt;a href="https://babeljs.io/docs/babel-plugin-transform-runtime" rel="noopener noreferrer"&gt;plugins&lt;/a&gt;. Most times you may not need to write your own plugin since Babel has a huge plugin library, both official and unofficial. &lt;/p&gt;

&lt;p&gt;Babel plugins are everywhere. From being used to &lt;a href="https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/utils/babel/babel-plugin-remove-api.ts" rel="noopener noreferrer"&gt;remove unwanted exports from files in Gatsby&lt;/a&gt; to being used to &lt;a href="https://github.com/vercel/next.js/blob/7d8cf1f9f3d682cf15145ca97d81838c3c5ec54e/packages/next/src/build/babel/plugins/next-page-disallow-re-export-all-exports.ts" rel="noopener noreferrer"&gt;disallow users from doing re-exports in Nextjs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more information about building Babel plugins, check the &lt;a href="https://github.com/kentcdodds/babel-plugin-handbook" rel="noopener noreferrer"&gt;Kent's Babel Handbook&lt;/a&gt; or this awesome &lt;a href="https://github.com/jamiebuilds/babel-handbook" rel="noopener noreferrer"&gt;Babel handbook by Jamie.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  AST in Linters - ESLint
&lt;/h2&gt;

&lt;p&gt;Linters are indispensable tools for upholding coding standards across your codebase. Whether you aim to eradicate semicolons, champion tabs over spaces, or delve into more intricate scenarios, Linters have got you covered.&lt;/p&gt;

&lt;p&gt;They empower you to maintain code quality, adhere to best practices, and ensure consistency throughout your projects. From simple conventions to much more intricate ones, Linters play a crucial role in enhancing your codebase's integrity.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fun fact!&lt;/em&gt; There has always been a &lt;a href="https://t.co/FgGOgNH68x" rel="noopener noreferrer"&gt;debate about whether to use tabs or spaces&lt;/a&gt; online. While Linters won't necessarily settle the debate, they can help teams enforce the standard they eventually agree on — hopefully, they get to agree :)&lt;/p&gt;

&lt;p&gt;ESLint is a great Linter! It has a plugin system where each plugin can define a &lt;em&gt;set of rules&lt;/em&gt;. Behind the scenes, each rule operates &lt;strong&gt;on your code's AST&lt;/strong&gt; to flag possible violations. ESLint also allows you to configure these rules to specify if violating them leads to an error or warning which we can specify in an ESLint config.&lt;/p&gt;

&lt;h3&gt;
  
  
  ESLint config
&lt;/h3&gt;

&lt;p&gt;ESLint relies on a configuration file that allows us to define plugins and rules to be used and their configuration. We can also use &lt;a href="https://eslint.org/docs/latest/use/configure/configuration-files#configuration-file-formats" rel="noopener noreferrer"&gt;different file formats&lt;/a&gt; like &lt;code&gt;YAML&lt;/code&gt; and &lt;code&gt;JSON&lt;/code&gt;. Here, we'll use the &lt;code&gt;.js&lt;/code&gt; format. We have a &lt;code&gt;.eslintrc.js&lt;/code&gt; file at the root of our project and it looks like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📂 .eslintrc.js&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;parserOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;ecmaVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;latest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;sourceType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;emojify-array&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;emojify-array/padded-emoji-array&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;emoji&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🔥🔥&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here, we have a minimal configuration, just enough to get things working. Each key serves a specific purpose. Let's see what each one does:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;env&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;env&lt;/code&gt; key specifies the environments where your JavaScript code will run. In this configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;"node: true"&lt;/code&gt; indicates that Node.js specific global variables are enabled.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"browser: true"&lt;/code&gt; indicates that browser-specific global variables are enabled.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;parserOptions&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;parserOptions&lt;/code&gt; key is used to configure options related to JavaScript parsing and ECMAScript version. In this configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ecmaVersion: "latest"&lt;/code&gt; specifies that the latest ECMAScript version should be used, allowing you to use the most recent JavaScript features.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sourceType: "module"&lt;/code&gt; indicates that the code is in ECMAScript modules (ES6 modules).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;plugins&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;plugins&lt;/code&gt; key lists the ESLint plugins you want to use. Plugins provide additional rules and features. Here, we're using the plugin "emojify-array", which we'll write in the next section.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;rules&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;rules&lt;/code&gt; key defines ESLint rules and their configurations(severity level and options). ESLint plugins can have multiple rules, so we're picking the &lt;code&gt;padded-emoji-array&lt;/code&gt; rule from our plugin and passing a severity level and some options.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing an ESLint plugin
&lt;/h3&gt;

&lt;p&gt;Let's take our knowledge about Abstract Syntax Trees one step higher by writing an ESLint plugin. This time, we're writing something really fun:)&lt;/p&gt;

&lt;p&gt;Our plugin will define a rule that forces arrays to start and end with an emoji. We'll also make the emoji configurable so that anyone using our plugin can configure the emoji to be used.&lt;/p&gt;

&lt;p&gt;The plugin is in the &lt;code&gt;plugins/eslint-plugin-emojify-array&lt;/code&gt; directory. In the plugin's entry point (&lt;code&gt;/lib/index.js&lt;/code&gt;), we can define all the rules that our plugin exposes in a &lt;code&gt;rule&lt;/code&gt; object. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;padded-emoji-array&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./rules/padded-emoji-array&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, we'll create the rule module referenced above in &lt;code&gt;rules/padded-emoji-array.js&lt;/code&gt;.  This rule is responsible for ensuring that arrays start and end with an emoji, and it provides an optional configuration to customize the emoji used.&lt;/p&gt;

&lt;p&gt;The rule module must export an object with a &lt;code&gt;create&lt;/code&gt; function, You can also define the rule's metadata and schema with &lt;code&gt;meta&lt;/code&gt; and &lt;code&gt;schema&lt;/code&gt; respectively:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/eslint/index.d.ts#L492" rel="noopener noreferrer"&gt;&lt;code&gt;create&lt;/code&gt;&lt;/a&gt; Function:&lt;/strong&gt; Defines the rule's behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/eslint/index.d.ts#L698-L750" rel="noopener noreferrer"&gt;&lt;code&gt;meta&lt;/code&gt;&lt;/a&gt; Object:&lt;/strong&gt; Provides metadata, including description and recommendations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/eslint/index.d.ts#L729" rel="noopener noreferrer"&gt;&lt;code&gt;schema&lt;/code&gt;&lt;/a&gt; Object:&lt;/strong&gt; Configures and validates options for the rule.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our rule module is defined below:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📂 &lt;code&gt;plugins/eslint-plugin-emojify-array/lib/rules/padded-emoji-array.js&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Make sure arrays start and end with an emoji&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;recommended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;fixable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;code&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;emoji&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;optionsObject&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emoji&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;optionsObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emoji&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🔥&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;containsEmoji&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emojiPattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[\p&lt;/span&gt;&lt;span class="sr"&gt;{Emoji}&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/gu&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;emojiPattern&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nc"&gt;ArrayExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;startAndEndContainsEmoji&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
          &lt;span class="nf"&gt;containsEmoji&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
          &lt;span class="nf"&gt;containsEmoji&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;startAndEndContainsEmoji&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Array should start and end with an emoji&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nf"&gt;fix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
              &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

              &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fixes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="nx"&gt;fixer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertTextBefore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firstElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`"&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;emoji&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;", `&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="nx"&gt;fixer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertTextAfter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`, "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;emoji&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="p"&gt;];&lt;/span&gt;

              &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fixes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let's go straight to the key part of this module, the &lt;code&gt;create&lt;/code&gt; function! The following steps are performed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We access the provided options to configure the emoji that should be used (or use a default emoji, "🔥" if none is provided).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A function named &lt;code&gt;containsEmoji&lt;/code&gt; checks if the first and last value of the array contains an emoji using a regular expression pattern. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;ArrayExpression&lt;/code&gt; node type is targeted in the code's AST. We check whether the first and last elements of the array contain emojis. If they don't, ESLint reports an issue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We have a &lt;code&gt;fix&lt;/code&gt; function so that ESLint can automatically fix the issue by adding the emojis to the array when ESLint is run with the &lt;code&gt;--fix&lt;/code&gt; flag.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Harnessing the power of &lt;strong&gt;Abstract Syntax Trees&lt;/strong&gt;, ESLint can serve as your watchful guardian to help dectect potential issues within your codebase. It caters to a spectrum of use cases, ranging from straightforward checks like the one we've just explored to more practical and intricate scenarios, such as &lt;a href="https://github.com/vercel/next.js/blob/7d8cf1f9f3d682cf15145ca97d81838c3c5ec54e/packages/eslint-plugin-next/src/rules/no-async-client-component.ts" rel="noopener noreferrer"&gt;prohibiting client components from utilizing asynchronous functions in Next.js&lt;/a&gt; or enforcing &lt;a href="https://legacy.reactjs.org/docs/hooks-rules.html" rel="noopener noreferrer"&gt;the rules of Hooks&lt;/a&gt; in a ReactJS project using &lt;a href="https://www.npmjs.com/package/eslint-plugin-react-hooks" rel="noopener noreferrer"&gt;eslint-plugin-react-hooks&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Running ESLint
&lt;/h3&gt;

&lt;p&gt;In this section, we'll run ESLint againt our code in two ways. First, we want to list of potential errors and warning and next, we want to fix them. I've defined two scripts in &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;lint&lt;/code&gt; and &lt;code&gt;lint:fix&lt;/code&gt; you should check &lt;code&gt;package.json&lt;/code&gt; to see the actual command behind the scripts.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lint&lt;/code&gt; - Calls ESLint on our &lt;code&gt;src&lt;/code&gt; directory which then shows us all possible warnings and errors in our files.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lint:fix&lt;/code&gt; - Fix errors using our &lt;code&gt;src&lt;/code&gt; directory using the &lt;code&gt;fix&lt;/code&gt; function defined in our ESLint rule.&lt;/p&gt;

&lt;p&gt;In one of the files in the &lt;code&gt;src&lt;/code&gt; directory, I'd add an array without an emoji at the start and end then I'll run the &lt;code&gt;lint&lt;/code&gt; script. The command should exit with an exit code of &lt;code&gt;1&lt;/code&gt; after listing all errors and warnings:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgdk2pd88nz71d0sxa5xg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgdk2pd88nz71d0sxa5xg.png" alt="Eslint error in Command line"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since our Eslint rule defines a &lt;code&gt;fix&lt;/code&gt; function, we can run &lt;code&gt;lint:fix&lt;/code&gt; to fix the error above:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F13soc04myoopip2drenp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F13soc04myoopip2drenp.gif" alt="fix lint errors eslint"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Eslint Editor Extensions
&lt;/h3&gt;

&lt;p&gt;Aside from the standard output you get when you run ESLint, you can also take the experience further by &lt;a href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint" rel="noopener noreferrer"&gt;installing the Eslint Extention&lt;/a&gt; on your editor. With the extension installed, you'd get errors, warnings and &lt;a href="https://eslint.org/docs/latest/extend/custom-rules#providing-suggestions" rel="noopener noreferrer"&gt;suggestions&lt;/a&gt; right in the editor. In our case, we should get a warning like so: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvefaqsqmele133w828xy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvefaqsqmele133w828xy.png" alt="Eslint error in editor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, Abstract Syntax Trees (AST) may initially seem daunting, but it becomes more approachable once you grasp the basics. This post aimed to provide a gentle introduction to AST while exploring its practical applications in JavaScript&lt;/p&gt;

&lt;p&gt;Whether you are a newcomer to the concept of AST or already have some familiarity with it, I hope this article has shed light on its significance and use cases. While our examples mainly revolved around JavaScript and related tooling, it's worth noting that AST concepts can be applied to various programming languages.&lt;/p&gt;

&lt;p&gt;Amongst many other practical utilizations of ASTs, we've focused on two common applications: Transpilers and Linters. &lt;/p&gt;

&lt;p&gt;The world of ASTs is vast, and while we touched on a few applications, there's much more to explore. You can expand your knowledge of what we've learned so far by figuring out what problems you can solve using these tools.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/kentcdodds/babel-plugin-handbook" rel="noopener noreferrer"&gt;babel plugin handbook&lt;/a&gt; by Kent C. Dodds&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/jamiebuilds/the-super-tiny-compiler" rel="noopener noreferrer"&gt;The super tiny compiler&lt;/a&gt; by Jamie&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>computerscience</category>
      <category>datastructures</category>
      <category>babel</category>
    </item>
  </channel>
</rss>
