AST를 한눈에 볼 수 있는 간단한 ESLint 플러그인 만들기

9312 단어
JavaScript 세계에서 ESLint는 가장 인기 있는 린터입니다.
이 기사에서는 ESLint 플러그인을 생성하여 ESLint가 코드를 분석하는 방법을 설명합니다.

ESLint는 어떻게 작동합니까?



작동 방식을 이미 알고 있을 수 있습니다.
하지만 먼저 ESLint가 어떻게 작동하는지 보여드리겠습니다.

이와 같은 프로젝트가 있다고 가정해 보겠습니다. 그리고 ESLint는 npm을 통해 설치되었습니다.

├──.eslintrc.json // ESLint configuration
├── node_modules
├── package-lock.json
├── package.json
└── src
    └── index.js


ESLint를 다음과 같이 src/index.js 사용할 수 있습니다.

npx eslint src


결과적으로 오류가 표시되었습니다.

/Users/xxx/foo/src/index.js
  1:7  error  'foo' is assigned a value but never used  no-unused-vars


이것은 src/index.js 안의 코드입니다.

const foo = () => "baz"

foo가 정의되어 있지만 어디에서나 호출되지 않습니다. 그래서 오류가 발생했습니다.

이것이 ESLint의 기본 사용법입니다.
다음 섹션에서는 ESLint가 이러한 오류를 감지하는 방법을 보기 위해 플러그인을 만들 것입니다.

플러그인이란?



플러그인을 사용하는 목적은 추가 규칙을 추가하는 것입니다.
ESLint에는 많은 규칙이 있습니다. 위에서 본 no-unused-vars 규칙 중 하나입니다.
하지만 공식 룰에 없는 추가 룰을 적용하고 싶다면 플러그인을 만들어 추가하면 된다. (다른 여러 방법이 있습니다)

그러나 ESLint가 소스 코드를 분석하여 소스 코드가 규칙에 맞는지 여부를 확인하는 방법은 무엇입니까?

AST(추상 구문 트리)



ESLint는 AST(Abstract Syntax Tree)를 사용하여 JavaScript 코드를 분석합니다. AST는 무엇입니까?

AST는 소스 코드 구조를 나타냅니다. 예를 들어 const hoge = 0;의 AST는 이렇습니다. (AST Explorer 으로 AST를 쉽게 보실 수 있습니다.)

{
  "type": "File",
  "start": 0,
  "end": 16,
  "loc": {
    "start": {
      "line": 1,
      "column": 0
    },
    "end": {
      "line": 2,
      "column": 0
    }
  },
  "errors": [],
  "program": {
    "type": "Program",
    "start": 0,
    "end": 16,
    "loc": {
      "start": {
        "line": 1,
        "column": 0
      },
      "end": {
        "line": 2,
        "column": 0
      }
    },
    "sourceType": "module",
    "interpreter": null,
    "body": [
      {
        "type": "VariableDeclaration",
        "start": 0,
        "end": 15,
        "loc": {
          "start": {
            "line": 1,
            "column": 0
          },
          "end": {
            "line": 1,
            "column": 15
          }
        },
        "declarations": [
          {
            "type": "VariableDeclarator",
            "start": 6,
            "end": 14,
            "loc": {
              "start": {
                "line": 1,
                "column": 6
              },
              "end": {
                "line": 1,
                "column": 14
              }
            },
            "id": {
              "type": "Identifier",
              "start": 6,
              "end": 10,
              "loc": {
                "start": {
                  "line": 1,
                  "column": 6
                },
                "end": {
                  "line": 1,
                  "column": 10
                },
                "identifierName": "hoge"
              },
              "name": "hoge"
            },
            "init": {
              "type": "NumericLiteral",
              "start": 13,
              "end": 14,
              "loc": {
                "start": {
                  "line": 1,
                  "column": 13
                },
                "end": {
                  "line": 1,
                  "column": 14
                }
              },
              "extra": {
                "rawValue": 0,
                "raw": "0"
              },
              "value": 0
            }
          }
        ],
        "kind": "const"
      }
    ],
    "directives": []
  },
  "comments": []
}


AST를 이용하면 소스 코드에 대한 자세한 정보를 얻을 수 있습니다. 일반 텍스트를 분석하는 것보다 소스 코드를 분석하는 것이 편리합니다.

플러그인 만들기



플러그인을 만들었습니다.
https://github.com/osuke/eslint-plugin-later-becomes-never

그리고 구조는 이렇게 간단합니다.

├── lib
│   └── index.js
├── package.json


이 플러그인은 주석 블록에서 TODO 문자열을 찾고 이에 대해 불평합니다.

프로젝트에 아래 코드가 있다고 가정해 보겠습니다.

// Todo: will change variable name later
let hoge = 0;


ESLint는 다음과 같은 오류를 표시합니다.

/Users/xxx/eslint-test/src/index.js
   1:1  error  Later becomes never  later-becomes-never/no-todo

no-todo 플러그인에서 가져온 규칙 later-becomes-never을 볼 수 있습니다.

플러그인에 대한 규칙을 정의하려면 AST를 사용해야 합니다.
규칙의 정의는 lib/index.js 에 있습니다.

module.exports = {
  rules: {
    "no-todo": {
      create: function (context) {
        return {
          Program: (node) => {
            node.comments.forEach((comment) => {
              if (comment.value.toLowerCase().indexOf("todo") !== -1) {
                context.report({
                  loc: comment.loc,
                  message: "Later becomes never",
                });
              }
            });
          },
        };
      },
    },
  },
};


파일에는 "no-todo"라는 규칙이 정의되어 있습니다. 노드를 사용하여 AST를 조작할 수 있습니다. AST를 사용하여 소스 코드에서 주석을 추출합니다. (7행)

그 후 각 댓글에 todo 문자열이 있는지 확인했습니다. (8행)
있는 경우 오류 메시지가 표시됩니다(Line9 - 12).

플러그인 사용



아래 JavaScript에 대한 플러그인과 함께 ESLint를 사용합시다. Line 1에 오류가 있다고 가정합니다. 3행은 그렇지 않습니다.

// Todo: will change variable name later
let hoge = 0;
// doit


이것은 결과입니다. 효과가있다 :)

/Users/xxx/eslint-test/index.js
  1:1  error  Later becomes never  later-becomes-never/no-todo
✖ 1 problem (1 error, 0 warnings)

좋은 웹페이지 즐겨찾기