[Advanced front-end] What is AST? What is ESLint? How to quickly publish a custom ESLint plugin?

What is AST

AST is called Virtual Syntax Tree (Abstract Syntax Tree), which expresses the grammatical structure of a programming language in the form of a tree. Each node on the tree represents a structure in the source code. The reason why grammar is "abstract" is that the grammar here does not represent every detail that appears in real grammar.

To put it bluntly: This is how you can dissect all the details on your body to describe your body.

Note: Abstract syntax tree does not simply mean that it exists on the front end. In fact, all languages ​​​​can be abstracted into syntax trees. It is just the result of syntax analysis.

For example, this python code:
Insert image description here
AST parsing:
Insert image description here

AST online visualization website

https://astexplorer.net/

Using this website, we can clearly see the AST structure of various languages.

How code converts AST

Here we only focus on how to convert JavaScript into AST. You can use two plug- ins acornandrecast

  • acorn
    acron code is relatively streamlined, and both webpack and eslint rely on acorn

Basic use of acorn

import * as acorn from 'acorn';  //引入
const code = 'xxx';				//解析代码块
const ast = acorn.parse(code, options)			//解析

options are defined as follows

If you have studied Ts, you should know very well what the following parameters are talking about. Simply put, except ecmaVersion, which is a required parameter, the other parameters are optional. ecmaVersion represents which version of es your code belongs to. If it is 6, Then the es5 code does not support parsing.

ecmaVersion ECMA version, default is es7

locations defaults to false. When set to true, the node will carry a loc object to represent the current start and end row numbers.

onComment callback function, which will be triggered whenever the code executes to a comment, and can get the current comment content

interface Options {
    
    
    ecmaVersion: 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 'latest'
    sourceType?: 'script' | 'module'
    onInsertedSemicolon?: (lastTokEnd: number, lastTokEndLoc?: Position) => void
    onTrailingComma?: (lastTokEnd: number, lastTokEndLoc?: Position) => void
    allowReserved?: boolean | 'never'
    allowReturnOutsideFunction?: boolean
    allowImportExportEverywhere?: boolean
    allowAwaitOutsideFunction?: boolean
    allowSuperOutsideMethod?: boolean
    allowHashBang?: boolean
    locations?: boolean
    onToken?: ((token: Token) => any) | Token[]
    onComment?: ((
      isBlock: boolean, text: string, start: number, end: number, startLoc?: Position,
      endLoc?: Position
    ) => void) | Comment[]
    ranges?: boolean
    program?: Node
    sourceFile?: string
    directSourceFile?: string
    preserveParens?: boolean
  }

reduction

import * as astring from 'astring'; //引入
 
const code = astring.generate(ast);		//ast
  • recast

Recast is similar.

recast.parse(code) //解析
recast.print(ast).code  //还原

What is ESLint

ESLint is a code detection tool used to identify ECMAScript and give reports according to rules . Use it to avoid low-level errors and unify the code style. If an eslint code check is performed every time before the code is submitted, the service will not crash due to errors such as a field being undefined or null, and the quality of the project code can be effectively controlled.

In many respects, it is similar to JSLint and JSHint, with a few exceptions:

  • ESLint uses Espree to parse JavaScript
  • ESLint uses AST to analyze patterns in code
  • ESLint is fully pluggable. Each rule is a plugin and you can add more rules at runtime.

Therefore, you need to understand the relevant knowledge of AST before introducing ESLint.

ESLint parsing principle

Insert image description here

  • Parsing: Parse source code into AST
  • Traverse: Traverse each selector twice
  • Callback: Trigger callback based on rules
  • Generation: modify AST and generate code

How to make an ESLint plugin

The official welcomes developers to participate in the production of ESLint plug-ins. For this reason, the official provides a scaffolding to facilitate developers to quickly develop plug-ins - yeoman

How to contribute to ESLint plug-insHow
to make plug-ins

Install yeoman

npm install -g yo generator-eslint

Create plugin

yo eslint:plugin

Insert image description here

Create rules

Insert image description here

Directory Structure

Insert image description here

Implement warning console.error() method

1. Modify the lib/rules/no-console-error.js file

/**
 * @fileoverview no console.error() in your code
 * @author yjian
 */
"use strict";

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
    
    
  meta: {
    
    
    type: 'problem', // `problem`, `suggestion`, or `layout`
    docs: {
    
      //文档描述
      description: "no console.error() in your code",
      recommended: false,
      url: null, // URL to the documentation page for this rule
    },
    fixable: null, // Or `code` or `whitespace`
    schema: [], // Add a schema if the rule has options
    // 报错信息描述
    messages: {
    
    
      avoidMethod: "'{
    
    {name}}' function of console is forbidden in code",
    },
  },

  create(context) {
    
    
    return {
    
    
      // 'MemberExpression'  这个就是AST的节点选择器,在遍历AST时,如果命中该选择器,就会触发回调
      // 关于选择器的名称,我们可以事先在 https://astexplorer.net/ 中找到目标解析器然后将其作为key即可
      //  这里的选择器会在AST"自上至下"过程中触发,如果希望是"自下至上"过程中触发,需要加':exit'即MemberExpression:exit
      'MemberExpression': (node) => {
    
    
        // 如果在AST遍历中满足以下条件,就用 context.report() 进行对外警告⚠️
        if (node.property.name === 'error' && node.object.name === 'console') {
    
    
            context.report({
    
    
                node,
                messageId: 'avoidMethod', //错误类型
                data: {
    
    
                    name: node.property.name,  //这里的name会传递到上面的messages中的name,类似于vue的双向绑定
                },
            });
        }
      },
    };
  },
};

2. Export rules lib/rules/index

/**
 * @fileoverview 自定义eslint规则
 * @author yjian
 */
"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Plugin Definition
//------------------------------------------------------------------------------


// import all rules in lib/rules
module.exports = {
    
    
  rules: {
    
    
  	  // 项目在使用时,对应的规则名称
      'no-console-error': require('./rules/no-console-error'),
  },
  configs: {
    
    
      recommended: {
    
    
          rules: {
    
    
              'demo/no-console-error': 2, // 可以省略 eslint-plugin 前缀
          },
      },
  },
}

3. Unit test./tests/lib/rules/no-console-error.js

/**
 * @fileoverview 不允许使用 console.time()
 * @author lzx
 */
"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const rule = require("../../../lib/rules/no-console-time"),
  RuleTester = require("eslint").RuleTester;


//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

const ruleTester = new RuleTester();
ruleTester.run("no-console-error", rule, {
    
    
  valid: [
    // give me some code that won't trigger a warning
  ],

  invalid: [
    {
    
    
      code: "console.error('test');",
      errors: [{
    
     message: "Fill me in.", type: "Me too" }],
    },
  ],
});

4.Finally execute the test

npm run test

npm publish

How to register

https://www.npmjs.com/

Log in to the official website, enter your username, email and password. After completing the email verification, the registration is successful. The process requires a ladder.

How to log in

Enter the command: a ladder is needed, and the npm address needs to be modified

npm login

After the input is successful, you will be prompted to enter your username, password and email address. You also need to verify that the login is successful. You
can use npm whoamithe command to check whether the login is successful. If successful, the username will pop up.

Note: When entering the password, the command line may be empty, which is normal, just make sure the password is correct to enter the next step

release

npm publish

Insert image description here
You can view it at the link below,
Insert image description here

https://www.npmjs.com/settings/username/packages

application

Install eslint

npm i eslint --save-dev

Install eslint plugin

npm install eslint-plugin-noconsole --save-dev

Initial configuration

npx eslint --init

Configuration

{
    
    
    "plugins": [
    	// 这是此前使用yo eslint:plugin 生成自定义插件的ID
        "diylint"
    ],
    extends: ["plugin:ecdemo/recommended"],
}

question

If the following error occurs when you use the npm login command, it means that your npm mirror address is not the original address and needs to be replaced

Unexpected token < in JSON at position 0 while parsing near '<html>

solution:

npm set registry https://registry.npmjs.org/

It is recommended to use nrmit to manage the mirror source address, please see the instructions below!

nrm

nrm (npm registry manager) is the mirror source management tool of npm, which can conveniently switch the mirror source through nrm.

Nvm is a tool that can easily switch node versions, similar to nrm

download

npm install -g nrm

View available image sources

// 显示当前可使用的镜像源列表
nrm ls
* npm -------- https://registry.npmjs.org/
  yarn ------- https://registry.yarnpkg.com/
  cnpm ------- http://r.cnpmjs.org/
  taobao ----- https://registry.npm.taobao.org/
  nj --------- https://registry.nodejitsu.com/
  npmMirror -- https://skimdb.npmjs.com/registry/
  edunpm ----- http://registry.enpmjs.org/

Switch mirror source

nrm use taobao

Finish

Presumably, you should have a rough idea of ​​how Babel converts es6 syntax to es5, and how ESLint does rule verification. If you want to understand further, you also need to understand how the code and AST are transformed into each other.

Reference article

How to register an npm account

Introduction to ESLint

https://blog.csdn.net/qq_33396780/article/details/129935377

https://blog.csdn.net/KlausLily/article/details/124486883

https://blog.csdn.net/WTUDAN/article/details/127383560

Guess you like

Origin blog.csdn.net/m0_46983722/article/details/131551828