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) {
// Skip getters, setters, operators
if (node.isGetter || node.isSetter || node.isOperator) return;
// Skip methods with parameters
final FormalParameterList? params = node.parameters;
if (params == null) return;
if (params.parameters.isNotEmpty) return;
// Skip async methods
if (node.body.isAsynchronous) return;
// Skip void return type
final TypeAnnotation? returnType = node.returnType;
if (returnType is NamedType && returnType.name.lexeme == 'void') return;
// Check if body is a simple expression return
final FunctionBody body = node.body;
if (body is ExpressionFunctionBody) {
// Simple expression body - likely should be a getter
final String name = node.name.lexeme;
// Skip methods starting with common action prefixes
if (!name.startsWith('get') &&
!name.startsWith('fetch') &&
!name.startsWith('load') &&
!name.startsWith('create') &&
!name.startsWith('build') &&
!name.startsWith('compute') &&
!name.startsWith('calculate')) {
return;
}
reporter.atToken(node.name, code);
} else if (body is BlockFunctionBody) {
// Check if it's a single return statement
final Block block = body.block;
if (block.statements.length == 1) {
final Statement stmt = block.statements.first;
if (stmt is ReturnStatement && stmt.expression != null) {
final String name = node.name.lexeme;
if (name.startsWith('get') && name.length > 3) {
reporter.atToken(node.name, code);
}
}
}
}
});
}