runWithReporter method
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.addMethodDeclaration((MethodDeclaration node) {
final body = node.body;
// Check if async method
if (body is! BlockFunctionBody) return;
if (body.keyword?.lexeme != 'async') return;
// Check if in Bloc class
final parent = node.parent;
if (parent is! ClassDeclaration) return;
final extendsClause = parent.extendsClause;
if (extendsClause == null) return;
final superName = extendsClause.superclass.name.lexeme;
if (superName != 'Bloc' && superName != 'Cubit') return;
// Check if method has Emitter parameter (Bloc handler)
bool hasEmitter = false;
for (final param in node.parameters?.parameters ?? <FormalParameter>[]) {
final paramSource = param.toSource();
if (paramSource.contains('Emitter')) {
hasEmitter = true;
break;
}
}
if (!hasEmitter) return;
// Check if emit is called before await
final methodSource = body.toSource();
final awaitIndex = methodSource.indexOf('await ');
if (awaitIndex == -1) return;
final beforeAwait = methodSource.substring(0, awaitIndex);
// cspell:ignore inprogress
final hasLoadingEmit =
beforeAwait.contains('emit(') &&
(beforeAwait.toLowerCase().contains('loading') ||
beforeAwait.toLowerCase().contains('inprogress'));
if (!hasLoadingEmit) {
reporter.atNode(node);
}
});
}