Eslint introduction

ESLint is an open source JavaScript code checking tool created by Nicholas C. Zakas in June 2013. Code review is a static analysis that is often used to find problematic patterns or code and is not dependent on specific coding styles. Most programming languages have code checks, and compilers typically have built-in checks.

JavaScript is a dynamic, weakly typed language that is prone to error in development. Because there is no compiler, it is often necessary to debug during execution to find JavaScript code errors. Things like ESLint allow programmers to find problems while coding rather than during execution.

The original purpose of ESLint was to allow programmers to create their own detection rules. All rules in ESLint are designed to be pluggable. ESLint has some rules built in to make it easier for people to use, although you can customize the rules as you go along. All rules are disabled by default.

ESLint is written in Node.js.

Eslint configuration

Configuration mode
  1. The.eslintrc.* configuration file is generally used for configuration. If placed in the root directory of the project, it will be applied to the entire project. If the project subdirectory also contains. Eslintrc files, the check of files in the subdirectory will ignore the configuration in the root directory and directly adopt the configuration in the subdirectory. This enables different check rules to be applied in different directories, which is more flexible. ESLint looks for.eslintrc.* files step by step and will stop looking up when it finds.eslintrc.* files with a “root”: true configuration item.
  2. Do this in the eslintConfig field in package.json.
Specific Configuration rules

Using a project as an example, esLint can be configured and used:

module.exports = {
    parser: 'babel-eslint'// parser Specifies the parser. The default is espree. Babel-eslint is a wrapper around Babel Parser. This wrapper makes Babel Parser work in harmony with ESLint. ParserOptions: {sourceType: 'module', // Set to"script"(Default) or"module"(ES6). EcmaFeatures: {// This is an object that represents additional language features you want to use: JSX:trueJSX}} extends: ['eslint:recommended'], // Using esLint's recommended rules as base configuration, you can override plugins in rules: ['html'.'vue'.'prettier'.'import'], // vue is short for eslint-plugin-vue, which allows ESLint to recognize the script code rules: {// 0 or off indicate that the rule is disabled and errors are ignored; 1 or WARN indicates that a warning will be given if an error occurs (it will not cause the program to exit); 2 or error indicates that an error will be reported if an error occurs (causing the program to exit with an exit code of 1)'no-console': 'off'.'prefer-const': 'error'.'prettier/prettier': 'warn'.'prefer-arrow-callback': 'warn'.'no-debugger': process.env.NODE_ENV === 'production'? 2:0}, globals: {// Allows the global location variable to be used in code:true.setTimeout: true}};Copy the code

For details, see eslint.cn/docs/user-g… Specific eslint: it support rules: cn.eslint.org/docs/rules/

“Extends” in addition to introduction, recommend rules can also introduce other custom rules in the form of files, and then on the basis of these custom rules with rules to define specific rules, which cover “extends” introduced in the rules.

{
    "extends": [
        "./node_modules/coding-standard/eslintDefaults.js",
        // Override eslintDefaults.js
        "./node_modules/coding-standard/.eslintrc-es6",
        // Override .eslintrc-es6
        "./node_modules/coding-standard/.eslintrc-jsx",]."rules": {
        // Override any settings from the "parent" configuration
        "eqeqeq": "warn"}}Copy the code

In addition to specifying rules in the configuration file, you can also specify rules in the code file. Rules configured with comments in the code file override the rules in the configuration file, that is, they have a higher priority. We usually use eslint-disable-next-line

Ignore the check

You can do this by creating an.eslintignore file in the project directory and configuring it to ignore checks for files. Note that esLint ignores checking for /node_modules/** by default, whether or not you have configured it in.eslintignore. This can also be configured in the eslintIgnore field of the package.json file.

Eslint checks the principle

To implement static analysis, you need to build your own precompile phase to parse the code.

Let’s start by looking at the three stages in which most compilers work:

Parsing: Parsing raw code into a more abstract expression, usually an abstract syntax tree, or AST. Transform: Converts parsed code expressions into a new format that meets expectations by modifying them. Code generation: Generates the transformed expression into new object code.

For ESLint, rule verification occurs when the JavaScript code is parsed into the AST and then iterated through the AST. Eslint uses Espree to generate an AST. The specific generation method is here. We can use the AST Explorer to see the AST generated after the code is parsed.

Rules Working Principle

Let’s take a look at writing rules in the ESLint source code. Rules source code for esLint exists under lib/rules. Each rules is a Node module that exports a meta object and a create function from module.exports.

module.exports = {
    meta: {
        type: "suggestion",

        docs: {
            description: "disallow unnecessary semicolons",
            category: "Possible Errors",
            recommended: true,
            url: "https://eslint.org/docs/rules/no-extra-semi"
        },
        fixable: "code",
        schema: [] // no options
    },
    create: function(context) {
        return {
            // callback functions}; }};Copy the code

Meta represents the metadata of the rule, such as the category of the rule, the document, the accepted parameter schema, and so on.

Create returns an object that defines the methods that need to be executed during the AST traversal to access the corresponding node, and so on. Functions take a context object as an argument, which contains methods such as context.report(), which can report errors or warnings, and context.getsourcecode (), which can getSourceCode, to simplify rule writing.

function checkLastSegment (node) {
    // report problem for function if last code path segment is reachable
}

module.exports = {
    meta: { ... },
    create: function(context) {
        // declare the state of the rule
        return {
            ReturnStatement: function(node) {// Execute} when the AST traverses the ReturnStatement node from top to bottom, and // execute the AST from bottom to topfunctionExpression node:"FunctionExpression:exit": checkLastSegment,
            "ArrowFunctionExpression:exit": checkLastSegment,
            onCodePathStart: function(codePath, node) {// execute at the beginning of parsing codePath}, onCodePathEnd:function(codePath, node) {// execute at the end of parsing codePath}}; }};Copy the code

The AST traverses the node twice in the order of “top to bottom” and then “bottom to top”. By default, the corresponding access function is executed in the next row. If it needs to be executed in an ascending process, exit needs to be added.

The principle is explained here in the official documentation. A detailed code path analysis is here.

How to write a rule

Now that you know how rules work, you can customize a rule. Each rule requires three files named after the rule:

  • In the lib/rules directory: a source file (for example, no-extra-semi.js)

  • In the tests/lib/rules directory: a test file (for example, no-extra-semi.js)

  • In the docs/rules directory: a Markdown document file (for example, no-extra-semi)

Next we’ll write a simple rule such as disallowing block-level comments. Eslint will report an error when block-level comments are used in code.

Rules file:

// lib/rules/no-block-comments.js
module.exports = {
  meta: {
    docs: {
      description: 'Block level comments are disabled',
      category: 'Stylistic Issues',
      recommended: true}}, create (context) {// get source code constsourceCode = context.getSourceCode()

    return {
      Program() {// Get all the comments in the source code const comments =sourceCode.getAllComments()

        const blockComments = comments.filter(({ type}) = >type= = ='Block')

        blockComments.length && context.report({
          node: node,
          message: 'No block comments'})}}}}Copy the code

Rules test file:

// tests/lib/rules/no-block-comments.js
const RuleTester = require("eslint").RuleTester;
const rule = require(".. /.. /.. /lib/rules/no-block-comments");

const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2018 } }); // You do have to tell eslint what js you're using ruleTester.run("no-block-comments", rule, { valid: ["var a = 1; console.log(a)"], invalid: [ { code: "var a = 1; /* block comments */ console.log(a)", errors: [ { messageId: "blockComments", line: 1, nodeType: "Block" } ] } ] });Copy the code

The working with Rules document on the official website provides a detailed description of how to write rules.

How to use custom rules

Written rules need to be published to NPM as an ESlint-plugin and downloaded in the project to be used. The NPM of the code in the example is here.

Configuration in the project:

// .eslintrc.js
module.exports = {
    ...
    "plugins": [
        "eslint-plugin-no-block-comments"// Publish NPM package name, omit eslint-plugin],"rules": {// Enable rules and their respective error levels'no-console': 'off'."no-block-comments/no-block-comments": 2 // Reference the no-block-comments rule in the no-block-comments plugin}};Copy the code

You can then examine the code. For example, I want to check the following code:

// src/index.js const a = 1; /* Here are block-level comments */ console.log(a);Copy the code

On the command line, execute eslint SRC and you can see the error.

Refer to the article

ESlint website

Discusses how ESLint works

Develop ESLint rules