check method
void
check(
- DcqRegistry registry
)
Implementation
@override
void check(DcqRegistry registry) {
final eventBaseNames = <String>{};
// Map of class name -> superclass name for all classes with extends.
final classSuperMap = <String, String>{};
final handledEvents = <String>{};
ClassDeclaration? blocNode;
registry.addClassDeclaration((node) {
final superclass = node.extendsClause?.superclass.type;
if (superclass is InterfaceType && isBloc(superclass)) {
blocNode = node;
// Collect event base class name from Bloc type parameters.
final typeArgs =
node.extendsClause?.superclass.typeArguments?.arguments;
if (typeArgs != null && typeArgs.isNotEmpty) {
final eventType = typeArgs.first;
if (eventType is NamedType) {
eventBaseNames.add(eventType.name.lexeme);
}
}
}
// Record class -> superclass mapping for later resolution.
final superName = node.extendsClause?.superclass.name.lexeme;
if (superName != null) {
classSuperMap[node.namePart.typeName.lexeme] = superName;
}
});
registry.addMethodInvocation((node) {
if (node.methodName.name != 'on') return;
final typeArgs = node.typeArguments?.arguments;
if (typeArgs == null || typeArgs.isEmpty) return;
final firstArg = typeArgs.first;
if (firstArg is NamedType) {
handledEvents.add(firstArg.name.lexeme);
}
});
registry.afterLibrary(() {
if (blocNode == null) return;
// Resolve event subclasses transitively: walk the inheritance chain
// so multi-level hierarchies (e.g. AppEvent > DataEvent > LoadDataEvent)
// are fully discovered.
final eventClasses = <String>{};
final queue = eventBaseNames.toList();
while (queue.isNotEmpty) {
final parent = queue.removeLast();
for (final entry in classSuperMap.entries) {
if (entry.value == parent && eventClasses.add(entry.key)) {
queue.add(entry.key);
}
}
}
// Only leaf event classes (those with no subclasses) need handlers.
final nonLeaf = classSuperMap.values.toSet();
final leafEvents = eventClasses.difference(nonLeaf);
final unhandled = leafEvents.difference(handledEvents);
if (unhandled.isNotEmpty) {
reportAtToken(blocNode!.namePart.typeName);
}
});
}