Upgrade to Pro — share decks privately, control downloads, hide ads and more …

プロジェクトコードをキレイキレイしよう!暗黙的な参照を読み解く静的解析

 プロジェクトコードをキレイキレイしよう!暗黙的な参照を読み解く静的解析

Flutterアプリには、単純な参照検索では捉えられない利用関係が数多く存在します。Widgetのoverride、RiverpodやFreezedによるコード生成、ルーティング用アノテーション、integration_test、Widgetbookのstory、プラグインの自動登録などが挙げられます。これらを考慮せずに未使用コードを判定すると、実際に必要なコードまで削除候補として報告してしまいます。

本セッションでは、Dart / Flutter の Dead Codeを検出する OSS Package 「kareki」の開発を通じて得た知見をもとに、Flutterの「暗黙的な参照」を静的解析でどのように扱えるかを解説します。

Avatar for Takuma Osada

Takuma Osada

October 28, 2026

More Decks by Takuma Osada

Other Decks in Programming

Transcript

  1. WINTICKET GitHub ID: ostk 入 9 6 0 0 9

    6 0 0 馬 ・ 己 X ID: ostk 田 自 長 3 21
  2. cccc ESLint SonarJS Dart / Flutter DCL DCM Knip ciach

    DCL jscpd DCM 一 入 手 ・ 方 用 ・ jev-lint ・ 見 文 7 Web DCM
  3. cccc ESLint Dart / Flutter SonarJS DCL DCM Knip ciach

    DCL jscpd DCM jev-lint Knip 見 ・ jev-lint 入 手 ・ 方 ・ 用 ・ DCL ・ 見 文 8 Web DCM
  4. DCL Dart / Flutter analysis_options.yaml cccc Dart 見 ・ 1

    pub.dev/packages/dart_code_linter github.com/moznion/cccc 足 1 9 . . Dart Code Linter
  5. DCL lib/can_edit.dart analysis_options.yaml bool canEdit(String? userId, String? ownerId) { if

    (userId != null) { if (ownerId != null) { if (userId == ownerId) return true; } } return false; } dart_code_linter: $ dart run dart_code_linter:metrics analyze lib \ --reporter=console-verbose \ --set-exit-on-violation-level=warning metrics: cyclomatic-complexity: 10 maximum-nesting-level: 2 canEdit 3 2 DCL WARNING 2 1 dcl.apps.bancolombia.com/docs/metrics 0 1 1 . . Dart Code Linter
  6. DCL lib/can_edit.dart bool canEdit(String? userId, String? ownerId) { if (userId

    == null) return false; if (ownerId == null) return false; if (userId != ownerId) return false; return true; } 1 CI 行 1 大 大 dcl.apps.bancolombia.com/docs/metrics 1 1 44 31 1 . . Dart Code Linter 0
  7. lint Type Safe AI Jev Jev jev-lint GitHub repository mizchi/jev-lint

    lint ・ ・ 見 用 食 食 矛 食 高 言 2 github.com/mizchi/jev-lint 2 1 自 1 . . jev-lint
  8. src/find_order.ts null // 見つからなければ null を返す function findOrder(id: string): Order

    { const order = orders.get(id); if (!order) { throw new Error("order missing"); } Dart / Flutter return order; } 見 矛 見 用 文 一 2 自 github.com/mizchi/jev-lint 3 1 1 . . jev-lint
  9. AST rule.yml kind follows - all: - any: - kind:

    function_declaration - follows: any: - kind: comment pattern: $DOC typescript/comment-describes-declaration 一 言 2 github.com/mizchi/jev-lint 4 1 見 1 . . jev-lint 範 $DOC
  10. rule.yml ask: >The comment above this code claims something that

    is not true of the code. rule.yml threshold: 0.63 severity: warning 0.63 warning AST 言 言 矛 自 自 2 github.com/mizchi/jev-lint 5 1 1 . . jev-lint
  11. Knip JS / TS knip.dev import export 見 ・ 用

    見 用 用 3 口 knip.dev/overview/getting-started 6 1 入 1 . . Knip
  12. src/main.ts import src/main.ts src/page.ts src/legacy.ts 2 用 矢 口 入

    口 口 入 入 3 口 knip.dev/explanations/entry-files 口 src/service.ts src/legacy_helper.ts legacy_helper.ts 7 1 入 入 1 . . Knip
  13. lib/save.dart force void save({bool force = false}) { print(force); }

    void main() { final void Function() callback = save; register(callback); } 見 9 6 0 0 github.com/ostk register force bin/main.dart 9 1 2.1. /kareki
  14. lib/save.dart Function.apply void save({bool force = false}) { print(force); }

    lib/register.dart void register(void Function() callback) { Function.apply(callback, [], {#force: true}); } 9 6 0 0 行 github.com/ostk 0 2 2.1. /kareki force: true true void Function()
  15. lib/callbacks.dart void save({bool force = false}) { print(force); } void

    Function()? pending; void register(void Function() callback) { pending = callback; } void main() { register(save); pending?.call(); } 9 6 0 0 github.com/ostk 1 2 2.2. /kareki force force
  16. lib/save.dart save void save({bool force = false}) { print(force); }

    bin/main.dart void main() { register(() => save()); pending?.call(); } 方 9 6 0 0 github.com/ostk 2 2 2.2. /kareki save() force
  17. Pub workspaces monorepo Dart / Flutter @riverpod pub package Assets

    見 0 用 1 用 用 ・ 用 自 ・ /kareki 足 9 6 0 0 生 3 言 github.com/ostk 3 2 2 . . Dart / Flutter l n
  18. Pub workspaces monorepo Dart / Flutter @riverpod GitHub repository Assets

    ostk0069/kareki l n kareki 見 用 用 用 用 自 足 0 1 /kareki ・ 9 6 0 0 生 3 言 github.com/ostk 4 2 2 . . Dart / Flutter
  19. unused_element unused_file pubspec.yaml unused_pub_dependency test_only_used unused_parameter unused_parameter_optional L n gen-l

    Assets/Fonts asset 言 色 0 1 ・ 用 ・ ・ .github.io/kareki/comparison 用 0 1 9 6 力 0 0 3 言 0 1 ostk 5 2 生 2 . . kareki n ARB FlutterGen unused_l n unused_asset
  20. kareki ciach public private public enum public Dart pub public

    l n Baseline Baseline kareki 2026 10 DCL Dart Code Linter 比 比 方 言 言 月 ・ ・ ・ 言 .github.io/kareki/comparison/#feature-comparison 言 比 0 1 9 6 用 用 用 用 用 用 0 口 0 入 ostk 6 比 2 2.3. DCL dependency_ validator Dart
  21. PR DCL jev-lint / AI Agent PR kareki workspace 示

    行 小 用 ・ 用 用 人 ・ 高 ・ 行 行 dcl.apps.bancolombia.com/docs/cli/analyze 8 人 2 3.1. AI PR
  22. AI ( PR AI 入 行 /kareki 手 9 6

    0 ・ 0 小 用 見 人 ・ 2 入 用 人 github.com/ostk 9 3 手 小 2 . . AI )
  23. DCL jev-lint AI 食 自 ・ ・ ・ PR ・

    用 手 足 ・ 行 ・ AI 0 3 kareki
  24. 1 3

  25. jscpd / ESLint / complexity DCM / CLI SonarJS ciach

    github.com/moznion/cccc eslint.org/docs/latest/rules/complexity github.com/SonarSource/eslint-plugin-sonarjs jscpd 言 足 github.com/kucherenko/jscpd 2 3 cccc github.com/kucherenko/jscpd dcm.dev/docs/cli github.com/leancodepl/ciach
  26. jev-lint Knip DCL / jev-lint / DCL / Metrics Knip

    / DCL / Analyze CLI Knip / Getting Started DCL / Cyclomatic Complexity Knip / How Knip works DCL / Maximum Nesting Level Knip / Entry Files DCL / Knip / Plugins jev-lint / README Knip / Monorepos & Workspaces pub.dev/packages/dart_code_linter github.com/mizchi/jev-lint dcl.apps.bancolombia.com/docs/metrics knip.dev dcl.apps.bancolombia.com/docs/cli/analyze knip.dev/overview/getting-started dcl.apps.bancolombia.com/docs/metrics/cyclomatic-complexity dcl.apps.bancolombia.com/docs/metrics/maximum-nesting-level dcl.apps.bancolombia.com/img/logo.svg ・ ・ github.com/mizchi/jev-lint 矛 knip.dev/explanations/entry-files knip.dev/features/monorepos-and-workspaces jev-lint / 足 knip.dev/explanations/how-knip-works knip.dev/explanations/plugins github.com/mizchi/jev-lint 3 3 DCL
  27. kareki / github.com/ostk kareki / github.com/ostk kareki kareki / /kareki

    ostk /kareki github.com/ostk kareki / github.com/ostk /kareki kareki / README jev-lint / Hooks CI github.com/mizchi/jev-lint 用 ・ /kareki ・ 9 9 9 9 9 ・ 9 6 6 6 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 比 用 比 9 6 0 github.com/ostk /kareki 用 kareki / 足 /kareki Dart / Pub workspaces github.com/ostk 0 .github.io/kareki/comparison kareki / dart.dev/tools/pub/workspaces 4 3 Flutter