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,
) {
// Only run in test files
final String path = context.filePath;
if (!path.contains('_test.dart') &&
!path.contains('/test/') &&
!path.contains('\\test\\')) {
return;
}
context.addMethodInvocation((MethodInvocation node) {
final String methodName = node.methodName.name;
// Check for common test method names
if (methodName != 'test' && methodName != 'testWidgets') return;
final ArgumentList args = node.argumentList;
if (args.arguments.length < 2) return;
final Expression callback = args.arguments[1];
if (callback is! FunctionExpression) return;
final String bodySource = callback.body.toSource();
// Count mock patterns
final int mockCount = _mockPattern.allMatches(bodySource).length;
final int whenCount = 'when('.allMatches(bodySource).length;
final int verifyCount = 'verify('.allMatches(bodySource).length;
final int verifyNeverCount = 'verifyNever('.allMatches(bodySource).length;
// If using many mocks with verify chains, suggest fakes
if (mockCount >= 2 && (verifyCount + verifyNeverCount) >= 3) {
reporter.atNode(node.methodName, code);
}
// Also flag tests with complex when() chains but simple assertions
if (whenCount >= 3 && verifyCount == 0) {
// Many setup stubs but no interaction verification
// Suggests mocks are being used as data providers (should be fakes)
reporter.atNode(node.methodName, code);
}
});
}