🐥

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

4 min read

はじめました。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

ログインするとコメントできます