🐥

【Flutter】ファイル間の依存を静的解析するAnalyzer Pluginを紹介

2022/01/15に公開
2

こんにちは。kawa です。

ほしいなと考えていた Flutter/Dart の静的解析のプラグインを作成したので紹介します。

伝えたいこと

  • コーディング規約で守っていくのは大変なので、import を制限する静的解析を作りました
  • GithubActions で実行、問題があれば PR にコメントを残す

なぜ自作したのか、AnalyzerPlugin について

コーディング規約は、チームでルールを作り誰が見ても理解できるコードを書くことを目的として導入されると思います。

一方でコーディング規約が守られているかを担保するために、コードレビューのコストが増加してしまうという課題が発生します。

コストが増加しコーディング規約が守られないと、目的が達成されずコードレビューだけが辛くなってしまうという悲しいことになってしまいます。

そうした状況を改善するため、今回は import を制限するミニマムな静的解析を作りました。

具体的な実装はこちらのリポジトリがとても参考になりました!

https://github.com/mj-hd/flutter_hooks_lint_plugin

作成した Lint について(import_lint)

import の静的解析を作りました
import_lint(pub.dev)で公開しています。

できること

analyzer:
  plugins:
    - import_lint

import_lint:
  rules:
    use_case_rule:
      target_file_path: "/**/use_case/*_use_case.dart"
      not_allow_imports: ["/**/use_case/*_use_case.dart"]
      exclude_imports: ["/**/use_case/base_use_case.dart"]

analysis_options.yamlに上記のような記述をすることで、UseCase から UseCase の参照を防ぎ、UseCase の継承元の BaseUseCase は除外することができます。

例えば、このようなファイルが存在する場合

- lib/use_case/one_use_case.dart
	import 'base_use_case.dart'
	class OneUseCase extends BaseUseCase{}
- lib/use_case/two_use_case.dart
	import 'base_use_case.dart'
	import 'one_use_case.dart'
	class OneUseCase extends BaseUseCase{}
- lib/use_case/base_use_case.dart
	abstract class BaseUseCase {}

IDE に警告と CLI での実行時に問題箇所を解析できます。

Analyzing...
   warning • lib/use_case/two_use_case.dart:1:8 • import 'one_use_case.dart'; • use_case_rule

 1 issues found.

使い方

  1. パッケージを追加
flutter pub add --dev import_lint
  1. analysis_options.yaml に import_lint のプラグイン情報を追加
analyzer:
  plugins:
    - import_lint

import_lint:
  rules:
    use_case_rule:
      target_file_path: "/**/use_case/*_use_case.dart"
      not_allow_imports: ["/**/use_case/*_use_case.dart"]
      exclude_imports: ["/**/use_case/base_use_case.dart"]

AnalyzerPlugin の機能で IDE に警告が表示されます。

  1. コマンドで解析結果を出力できます
flutter pub run import_lint

GithubActions で実行してコメントを投稿

このような yml を書くことで、analyze, import_lint, format を実行し、問題がある場合 PR にコメントできます。

.github/workflows/analyze.yml

on: [pull_request]

name: Analyze

jobs:
  build:
    name: Analyze
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - uses: at-wat/setup-gh-pr-comment@v0
      - uses: subosito/flutter-action@v1
        with:
          channel: "stable"
      - name: Install dependencies
        run: flutter pub get
      - name: analyze and format
        run: |
          is_error=false

          set +e
          analyze=$(flutter analyze)
          set -e

          if [ ! "`echo $analyze | grep 'No issues found'`" ]; then
              gh-pr-comment "analyze" "${analyze}"
              is_error=true
          fi

          import_lint=$(flutter pub run import_lint)
          if [ ! "`echo $import_lint | grep 'No issues found'`" ]; then
              gh-pr-comment "analyze import lint" "${import_lint}"
              is_error=true
          fi

          format=$(flutter format lib)
          if [ ! "`echo $format | grep '0 changed'`" ]; then
              gh-pr-comment "format" "${format}"
              is_error=true
          fi

          if "${is_error}"; then
            exit 1
          fi
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

さいごに

長くなりましたが、読んでいただきありがとうございます!
Issue や PR、お気持ちスター(⭐)で喜びます 😻

https://github.com/kawa1214/import-lint

https://pub.dev/packages/import_lint

Analyzer Plugin で欲しい Lint を自作する

Discussion

中條 剛(ちゅーやん)中條 剛(ちゅーやん)

パッケージの開発と公開、ありがとうございます!使ってみています。

コマンドでの違反の検出はできたのですが、VS Code 上に警告が出なかったので issue を作らせていただきました!時間のあるときにご確認いただけるとありがたいです。

https://github.com/kawa1214/import-lint/issues/9