Custom ESLint rules #3/5: creating a new rule
Tags: javascript, eslint
Published: 2023-12-11 17:45:26

---
title: Custom ESLint rules #3/5: creating a new rule
published: true
date: 2023-12-08 06:00:10 UTC
tags: javascript, eslint
canonical_url: https://bite-sized.hashnode.dev/custom-eslint-rules-35-creating-a-new-rule
---

To save our teammates from eating pineapple pizza, we decided to create a custom ESLint plugin with a dedicated rule. In the previous _bite_, we set up a sample monorepo and now it's time to create our rule!

### How to write a custom ESLint rule

At this point, we need to define our custom ESLint ruleset. We will focus on `eslint-plugin-pizza` folder.

We have to decide our rule name. According to [naming conventions](https://archive.eslint.org/docs/developer-guide/working-with-rules#rule-naming-conventions), we should use something like `no-pineapple-pizza`. Let's go for it and create all the relevant files.

```bash
yummy-pizza $ touch packages/eslint-plugin-pizza/rules/no-pineapple-pizza.js packages/eslint-plugin-pizza/index.js

```

This is what we have:

```text
yummy-pizza/
 packages/
   eslint-plugin-pizza/
     rules/
       no-pineapple-pizza.js
     package.json
     index.js
   app/
     src/
     package.json
 package.json

```

- `rules/no-pineapple-pizza.js` is our rule

- `index.js` is where our rules are exported

It is time to write our rule! To create it, my suggestion is to take advantage of the [Abstract Syntax Tree Explorer](https://astexplorer.net/) tool and understand what is the best way to match our pineapple code. Also, we need to provide some metadata to our rule. For the detailed list of metadata to use, refer to the [official docs](https://eslint.org/docs/latest/extend/custom-rules#rule-structure).

In our example, we want to match the `eatPineapplePizza` function. If we feed AST Explorer with a sample code, it will tell us how to build our rule. Place the cursor upon the incriminated text and see what is highlighted on the right-hand side. For a way more detailed guide on how to use AST, you can check [this blog post](https://andrewmcg.dev/blog/ast-and-eslint) that I found extremely helpful.

![AST example](https://cdn.hashnode.com/res/hashnode/image/upload/v1700046112434/014f72fe-e096-4747-8004-bc30d40d6531.png)

So after playing a bit with it, I ended up with the following code:

```javascript
// yummy-pizza/packages/eslint-plugin-pizza/rule/no-pineapple-pizza.js

const rule = {
  meta: {
    type: "problem", // our rule is detecting an error
    fixable: "code", // our rule can be automatically fixed
    docs: {
      description: "Don't eat pineapple pizza.", // short rule description
      category: "Pizza ruleset",
    },
  },
  create: function (context) {
    return {
      // this code is generated using AST
      CallExpression(node) {
        if (
          node.callee.type === "Identifier" &&
          node.callee.name === "eatPineapplePizza"
        ) {
          context.report({
            node,
            // message to display to pineapple pizza eaters
            message:
              "A notification was sent to the Italian police. They're coming. Pineapple pizza is illegal, please eat pizza Margherita instead",
            fix(fixer) {
            // we provide an automatic fix: replace 'usePineapplePizza' with 'usePizzaMargherita'
              return fixer.replaceText(node.callee, "eatPizzaMargherita");
            },
          });
        }
      },
    };
  },
};

export default rule;

```

Finally, edit `index.js` file to export the new rule.

```javascript
// yummy-pizza/packages/eslint-plugin-pizza/index.js

import noPineapplePizzaRule from "./rules/no-pineapple-pizza"

const plugin = {
  rules: {
    "no-pineapple-pizza": noPineapplePizzaRule,
  },
};

export default plugin;

```

Our rule is ready!

In the next _bite_, we'll learn how to test it to ensure it works properly.

### References

- [ESLint rules naming conventions](https://archive.eslint.org/docs/developer-guide/working-with-rules#rule-naming-conventions)

- [ESLint rule structure](https://eslint.org/docs/latest/extend/custom-rules#rule-structure)

- [A very useful blog post about AST](https://andrewmcg.dev/blog/ast-and-eslint)