check method

  1. @override
void check(
  1. DcqRegistry registry
)

Implementation

@override
void check(DcqRegistry registry) {
  final stateBaseNames = <String>{};
  final candidates = <(ClassDeclaration, String)>[];

  registry.addClassDeclaration((node) {
    final superclass = node.extendsClause?.superclass.type;

    // Collect state base class names from Bloc type parameters.
    if (superclass is InterfaceType && isBloc(superclass)) {
      final typeArgs =
          node.extendsClause?.superclass.typeArguments?.arguments;
      if (typeArgs != null && typeArgs.length >= 2) {
        final stateType = typeArgs[1];
        if (stateType is NamedType) {
          stateBaseNames.add(stateType.name.lexeme);
        }
      }
    }

    // Collect candidate state subclasses missing @immutable.
    if (superclass is! InterfaceType) return;
    final superName = superclass.element.name ?? '';
    if (!superName.endsWith('State')) return;
    if (superName == 'State' ||
        superName == 'StatefulWidget' ||
        superName == 'InheritedWidget') {
      return;
    }

    final hasImmutable = node.metadata.any((a) {
      final name = a.name;
      if (name is SimpleIdentifier) return name.name == 'immutable';
      if (name is PrefixedIdentifier) {
        return name.identifier.name == 'immutable';
      }
      return false;
    });
    if (hasImmutable) return;

    candidates.add((node, superName));
  });

  registry.afterLibrary(() {
    if (stateBaseNames.isEmpty) return;
    for (final (classNode, superName) in candidates) {
      if (stateBaseNames.contains(superName)) {
        reportAtToken(classNode.namePart.typeName);
      }
    }
  });
}