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 interactive widgets
final interactiveWidgets = [
'IconButton',
'GestureDetector',
'InkWell',
'InkResponse',
];
if (!interactiveWidgets.contains(typeName)) {
return;
}
// For GestureDetector, InkWell, InkResponse: only check if they have interactive callbacks
// IconButton is always considered interactive
if (typeName != 'IconButton' && !hasInteractiveCallbacks(node)) {
return;
}
// Check for tooltip parameter (directly on the widget)
bool hasTooltip = false;
for (final arg in node.argumentList.arguments) {
if (arg is NamedExpression && arg.name.label.name == 'tooltip') {
hasTooltip = hasNonEmptyStringValue(arg.expression);
if (hasTooltip) break;
}
}
// For IconButton, also check if the icon has a semanticLabel
if (!hasTooltip && typeName == 'IconButton') {
for (final arg in node.argumentList.arguments) {
if (arg is NamedExpression && arg.name.label.name == 'icon') {
final iconExpression = arg.expression;
if (iconExpression is InstanceCreationExpression) {
// Check if Icon has semanticLabel parameter
for (final iconArg in iconExpression.argumentList.arguments) {
if (iconArg is NamedExpression &&
iconArg.name.label.name == 'semanticLabel') {
hasTooltip = hasNonEmptyStringValue(iconArg.expression);
if (hasTooltip) break;
}
}
}
if (hasTooltip) break;
}
}
}
// Check for parent tooltip or Semantics wrapper
if (!hasTooltip) {
hasTooltip = hasParentTooltip(node);
}
final semanticInfo = getSemanticWrappingInfo(node);
// Report if no tooltip and not wrapped in Semantics with label
if (!hasTooltip && !semanticInfo.hasSemantics) {
reporter.atNode(node, code);
}
});
}