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.addClassDeclaration((ClassDeclaration node) {
    // Only check private StatelessWidget classes
    if (!node.nameToken.lexeme.startsWith('_')) return;

    final ExtendsClause? extendsClause = node.extendsClause;
    if (extendsClause == null) return;

    final String? superclassName = extendsClause.superclass.element?.name;
    if (superclassName != 'StatelessWidget') return;

    // Check if it has only the build method (no fields, no other methods)
    final List<ClassMember> members = node.bodyMembers.toList();

    bool hasFields = false;
    bool hasOtherMethods = false;
    MethodDeclaration? buildMethod;

    for (final ClassMember member in members) {
      if (member is FieldDeclaration) {
        hasFields = true;
        break;
      }
      if (member is MethodDeclaration) {
        if (member.name.lexeme == 'build') {
          buildMethod = member;
        } else {
          // Has other methods beyond build - too complex to be a simple method
          hasOtherMethods = true;
        }
      }
      if (member is ConstructorDeclaration) {
        // Has a constructor with logic - keep as class
        if (member.body is! EmptyFunctionBody) {
          hasOtherMethods = true;
        }
      }
    }

    // Skip if has fields (needs to be a class for state)
    if (hasFields) return;

    // Skip if has other methods (too complex)
    if (hasOtherMethods) return;

    // Skip if no build method found
    if (buildMethod == null) return;

    // Check build method size
    final FunctionBody body = buildMethod.body;
    final root = node.root;
    if (root is! CompilationUnit) return;
    final int startLine = root.lineInfo.getLocation(body.offset).lineNumber;
    final int endLine = root.lineInfo.getLocation(body.end).lineNumber;
    final int lineCount = endLine - startLine + 1;

    if (lineCount <= _maxBuildLines) {
      reporter.atToken(node.nameToken, code);
    }
  });
}