run method

  1. @override
void run(
  1. CustomLintResolver resolver,
  2. DiagnosticReporter reporter,
  3. CustomLintContext context
)

Emits lints for a given file.

run will only be invoked with files respecting filesToAnalyze

Implementation

@override
void run(
  CustomLintResolver resolver,
  DiagnosticReporter reporter,
  CustomLintContext context,
) {
  if (isGeneratedFile(resolver.path)) return;
  if (!RigidConfig.forFile(resolver.path).isEnabled(code.name)) return;

  context.registry.addInstanceCreationExpression((node) {
    final type = node.staticType;
    if (type == null) return;

    // Is this a Column or scrollable?
    final isColumn = FlutterTypes.column.isExactlyType(type);
    final isScrollable = FlutterTypes.scrollableFamily.isAssignableFromType(
      type,
    );
    if (!isColumn && !isScrollable) return;

    // Check for shrinkWrap: true (ListView/GridView)
    if (_hasShrinkWrap(node)) return;

    // Check for mainAxisSize: MainAxisSize.min (Column/Row)
    if (isColumn && _hasMainAxisSizeMin(node)) return;

    // Walk up — is there a parent scrollable without a SizedBox boundary?
    var current = node.parent;
    while (current != null) {
      if (current is InstanceCreationExpression) {
        final parentType = current.staticType;
        if (parentType == null) break;

        // If we hit a SizedBox, constraints are applied — OK.
        if (FlutterTypes.sizedBox.isExactlyType(parentType)) return;

        // If we hit another scrollable, that's the problem.
        if (FlutterTypes.scrollableFamily.isAssignableFromType(parentType) ||
            FlutterTypes.column.isExactlyType(parentType)) {
          reporter.atNode(node.constructorName, code);
          return;
        }
      }
      current = current.parent;
    }
  });
}