Closed11

Eslintの独自ルールをリポジトリに追加したい

nus3nus3

ゴール

大層にeslint pluginを作るとかではなく今のリポジトリに追加でeslintのルールを作りたい
そしてできればルールはtypescriptで書きたい

nus3nus3

公式のドキュメント読んでく
https://eslint.org/docs/developer-guide/working-with-rules

nus3nus3

Runtime Rulesなるものがあるのでこれでいけそうな気はしてる

  1. Place all of your runtime rules in the same directory (e.g., eslint_rules).
  2. Create a configuration file and specify your rule ID error level under the rules key. Your rule will not run unless it has a value of "warn" or "error" in the configuration file.
  3. Run the command line interface using the --rulesdir option to specify the location of your runtime rules.
nus3nus3

@typescript-eslint/experimental-utilsを使って定義したruleが動いたのは確認できたけども--rulesdirで実行されない

tsファイルで書いたruleだから一度ビルドしないといけないんかなぁ・・

nus3nus3

typescriptで書いてjsにコンパイルしたら動いたのでざっくりまとめ

  • @typescript-eslint/experimental-utilsいれる
  • 任意のディレクトリにruleをかく
  • astにどんな値や種類があるかはAST explorerでみる
  • ruleのテストかく(@typescript-eslint/experimental-utils使って)
  • ts→jsにコンパイルする
  • eslint-plugin-rulesdirいれる(hack: なんかメンテされてなさそうなので自作のが良さそう)
  • eslint-plugin-rulesdirでpluginとしてeslintのruleに追加する
nus3nus3

実装例

import { TSESLint } from '@typescript-eslint/experimental-utils'

const cleanArch: TSESLint.RuleModule<'test', []> = {
  meta: {
    type: 'suggestion',
    messages: {
      test: 'test',
    },
    schema: [],
  },
  create: (context) => {
    return {
      ImportDeclaration(node) {
        if (node.source.value === 'core/domains/models/business-group') {
          // eslint-disable-next-line
          console.log(context.getFilename())
          context.report({
            node,
            messageId: 'test',
          })
        }
      },
    }
  },
}

module.exports = cleanArch

nus3nus3
.eslintrc.js
// TODO: eslint-plugin-rulesdirはメンテされてないっぽいので自作したい
const rulesDirPlugin = require('eslint-plugin-rulesdir')
rulesDirPlugin.RULES_DIR = 'eslint-rules/dist'

module.exports = {
  parser: '@typescript-eslint/parser',
  settings: {
  },
  parserOptions: {
  },
  plugins: [
    'rulesdir',
  ],
  extends: [
  ],
  env: {
  },
  rules: {
    'rulesdir/clean-arch': 'error',
  },
}


nus3nus3

--debugオプションでlint実行時のデバッグ情報が見れる

nus3nus3

ruleの内容を吐き出したいときはmessageにいれるとデバッグできる
metamessagescreatedataのとこ

import { TSESLint } from '@typescript-eslint/experimental-utils'

const cleanArch: TSESLint.RuleModule<'test', []> = {
  meta: {
    type: 'suggestion',
    messages: {
      test: '{{ foo }}',
    },
    schema: [],
  },
  create: (context) => {
    return {
      ImportDeclaration(node) {
        if (node.source.value === 'core/domains/models/business-group') {
          context.report({
            node,
            messageId: 'test',
            data: {
              foo: context.getFilename(),
            },
          })
        }
      },
    }
  },
}

module.exports = cleanArch

nus3nus3

context.getFilename()は絶対パスを出力してくれる
/Users/foo/dev/project-name/src/core/adapters/adapter-name/index.ts

このスクラップは2021/05/14にクローズされました