Writing your own ESLint Plugins

What is ESLint?

ESLint is an open source JavaScript linter that is used to find code that doesn't adhere to style guidelines or uses problematic patterns.

ESLint is built with extensibility in mind to allow developers to write their own rules.

Why write your own rules?

  • Your engineering team might have a preference that isn't relevant outside of your company.

  • All projects should have clearly defined coding conventions that are automatically enforced.

  • ESLint can be used to avoid certain bugs.

How?

Setting up an ESLint project is surprisingly easy.

For the purpose of this blog post, we're going to write a very simple rule that prevents usage of lodash's isNull method.

Firstly, ensure that you have Yeoman & ESLint generator installed

npm install -g yo generator-eslint  

After that, run the following command in the folder where you want your plugin to live

yo eslint:plugin  

This command walks you through the process of creating your plugin & will create the necessary plumbing. Think of the plugin as a container for your rules.

The next step is to actually create your first ESLint rule.

yo eslint:rule  

The yeoman generator creates three directories for us docs, lib & tests.

  1. docs/rules/no-lodash-isnull.md - This is the file where the documentation for the rule will live.

  2. lib/rules/no-lodash-isnull.js - This is where the logic for the rule will live.

  3. tests/lib/rules/no-lodash-isnull.js - This is where the tests for the rule will live.

This directory structure is consistent with the philosophy of the ESLint project. Here's an excerpt from ESLint's website about their philosophy:

Values documentation and clear communication

Is as transparent as possible

Believes in the importance of testing

Writing tests

Open the test file & fill in the following information:

Add a valid test case. For this use-case, the valid test any code that is checking for null without relying on lodash

"var testVar; testVar === null"

For the invalid test, add an error message & type.

{
    message: "Use native JavaScript to check for null",
    type: "MemberExpression"
}

After making these changes, my test file looks like this

const rule = require("../../../lib/rules/no-lodash-isnull");  
const RuleTester = require("eslint").RuleTester;

const ruleTester = new RuleTester();  
const errorObject = {  
    message: "Use native JavaScript to check for null",
    type: "MemberExpression"
};

ruleTester.run("no-lodash-isnull", rule, {  
    valid: [
        "var testVar; testVar === null",
    ],

    invalid: [
        {
            code: "_.isNull(5)",
            errors: [ errorObject ]
        }
    ]
});

And if you run the tests at this stage, you should see the test failing.

AST Explorer

ESLint rules work against a generated AST & "fire" when they encounter a part of that AST in violation of the rule being enforced. The best way to explore ASTs & write our rule is by using astexplorer

The above screenshot is from astexplorer & it highlights some key things.

Ensure that you set the parser to "espree". Also, click on transform & select "ESLint v4". After you do this you should have 4 panes on your screen. The screenshot describes the purpose of each pane.

Notice that in the ESLint pane there is some code for us already. That sample code is targeting all nodes in the AST tree where the type is TemplateLiteral. I recommend you play around with this tool for a while to develop an understanding of how eslint rules work.

After a little bit of exploration, I've identified that I can target _.isNull with the following code

MemberExpression(node) {  
            if (node.object.name === "_" && node.property.name === "isNull") {
              context.report({
                node,
                message: "Use native JavaScript to check for null",
              });
            }
          }

Paste this code into lib/rules/no-lodash-isnull.js & re-run the tests again. There you have it, we have our very own ESLint rule!

Ship it!

Just publish the plugin to npm & you're all set!

One of my favorite things about using the Yeoman generator is that the documentation it generates. To incorporate this plugin into your project simply follow the instructions in README.md.

Autofixing?

The only problem with our plugin is that it will require somebody to manually fix all the violations that are found in your project.

Check out Part 2 of this series to learn about auto fixing code using ESLint

Author: Watandeep Sekhon
Software Developer