runWithReporter method

  1. @override
void runWithReporter(
  1. SaropaDiagnosticReporter reporter,
  2. SaropaContext context
)
override

Override this method to implement your lint rule.

Use context to register callbacks for AST node types:

context.addMethodInvocation((node) {
  if (condition) {
    reporter.atNode(node);
  }
});

Implementation

@override
void runWithReporter(
  SaropaDiagnosticReporter reporter,
  SaropaContext context,
) {
  context.addInstanceCreationExpression((InstanceCreationExpression node) {
    final String typeName = node.constructorName.type.name.lexeme;
    if (typeName != 'FutureBuilder') return;

    // Check future argument
    for (final Expression arg in node.argumentList.arguments) {
      if (arg is NamedExpression && arg.name.label.name == 'future') {
        final Expression value = arg.expression;

        // Flag method invocations that create a new Future each rebuild.
        // Exempt the cache-method pattern: a private method whose name
        // references a specific Future? field on the same class (not just
        // any class with any Future? field).
        if (value is MethodInvocation) {
          if (!_isCacheMethodCall(value)) {
            reporter.atNode(value);
          }
        }

        // Flag inline function expressions — always creates a new closure.
        if (value is FunctionExpression) {
          reporter.atNode(value);
        }

        // Flag Future constructors except Future.value() and Future.error()
        // which are deterministic with no I/O and safe to call in build.
        if (value is InstanceCreationExpression) {
          final typeName = value.constructorName.type.name.lexeme;
          if (typeName == 'Future') {
            final ctorName = value.constructorName.name?.name;
            if (ctorName == 'value' || ctorName == 'error') return;
          }
          reporter.atNode(value);
        }
      }
    }
  });
}