LoginSignup
4
2

【Flutter】custom_lint:buildメソッド内部でのref.readは避けよう

Posted at

こちらは以下の続きになります。

背景

Riverpodを用いる際、stateの参照を行う場合にref.readやref.watchを用いることができますが、ref.readの場合思い通りにリビルドされなかったりとバグの要因にもなり得るためbuildメソッド内部ではref.watchで統一したいところです。
そのため、ref.readで変数定義はしないような制約を設けました。

// This is the entrypoint of our custom linter
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';

/// メソッド呼び出し時にWidgetRefクラスのreadメソッドが呼ばれているかをチェックする

class NoRefReadVariableDeclarationInBuildMethod extends DartLintRule {
  const NoRefReadVariableDeclarationInBuildMethod() : super(code: _code);

  static const _code = LintCode(
    name: 'no_ref_read_variable_declaration_in_build_method',
    problemMessage: 'buildメソッド内部での変数定義時にref.readは使用しないでください',
    errorSeverity: ErrorSeverity.ERROR,
  );

  @override
  void run(
    CustomLintResolver resolver,
    ErrorReporter reporter,
    CustomLintContext context,
  ) {
    context.registry.addMethodInvocation((node) {
      if (_isWidgetRefReadMethodInBuildMethod(node, resolver)) {
        reporter.reportErrorForNode(_code, node);
      }
    });
  }

  bool _isWidgetRefReadMethodInBuildMethod(
    AstNode node,
    CustomLintResolver resolver,
  ) {
    final buildMethod = node.thisOrAncestorOfType<MethodDeclaration>();
    if (buildMethod == null || buildMethod.name.lexeme != 'build') {
      return false;
    }

    if (node is MethodInvocation) {
      final target = node.target;
      final methodName = node.methodName.name;
      if (target is SimpleIdentifier &&
          target.name == 'ref' &&
          methodName == 'read') {
        final parent = node.parent;
        if (parent is VariableDeclaration && parent.initializer == node) {
          return true;
        }
      }
    }

    return false;
  }
}

ただ力技が否めないのでもう少しいい方法があればコメントいただきたいです!

クラス定義をしたら、忘れず前回の記事にあるgetLintRulesにも追加しておきましょう。

PluginBase createPlugin() => _MyCustomLinter();

class _MyCustomLinter extends PluginBase {
  @override
  List<LintRule> getLintRules(CustomLintConfigs configs) => [
        // 各lintルールを定義したクラスを配置していく
        const NoRefReadVariableDeclarationInBuildMethod(),
      ];
}
4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2