run method
void
run(
- CustomLintResolver resolver,
- DiagnosticReporter reporter,
- CustomLintContext context
Emits lints for a given file.
run will only be invoked with files respecting filesToAnalyze
Implementation
@override
void run(
CustomLintResolver resolver,
DiagnosticReporter reporter,
CustomLintContext context,
) {
context.registry.addInstanceCreationExpression((node) {
final type = node.staticType;
if (type == null) {
return;
}
final typeName = type.element?.name;
// Check for common Flutter button widgets
final buttonTypes = [
'ElevatedButton',
'TextButton',
'OutlinedButton',
'IconButton',
'FloatingActionButton',
'CupertinoButton',
];
if (!buttonTypes.contains(typeName)) {
return;
}
// Look for onPressed or onTap arguments
final arguments = node.argumentList.arguments;
for (final arg in arguments) {
if (arg is NamedExpression) {
final paramName = arg.name.label.name;
if (paramName == 'onPressed' || paramName == 'onTap') {
final expression = arg.expression;
// Check if it's explicitly null
if (expression is NullLiteral) {
// Null is acceptable for disabled state
continue;
}
// Check for empty function bodies: () {}
// AST-based check for no-op callbacks
if (expression is FunctionExpression) {
final body = expression.body;
// Check for empty block body: () {}
if (body is BlockFunctionBody && body.block.statements.isEmpty) {
reporter.atNode(node, code);
}
// Check for empty function body: () ;
else if (body is EmptyFunctionBody) {
reporter.atNode(node, code);
}
// Check for expression body: () => null
else if (body is ExpressionFunctionBody) {
final expr = body.expression;
if (expr is NullLiteral) {
reporter.atNode(node, code);
}
}
}
}
}
}
});
}