run method

  1. @override
void run(
  1. CustomLintResolver resolver,
  2. DiagnosticReporter reporter,
  3. 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 images and icons that should have semantic labels
    final imageTypes = [
      'Image',
      'Icon',
      'SvgPicture', // from flutter_svg package
    ];

    if (!imageTypes.contains(typeName)) {
      return;
    }

    bool hasSemanticLabel = false;
    bool isExcludedFromSemantics = false;

    // Check if semanticLabel or excludeFromSemantics is provided
    for (final arg in node.argumentList.arguments) {
      if (arg is NamedExpression) {
        final paramName = arg.name.label.name;

        if (paramName == 'semanticLabel') {
          // Check if the value is not null or empty string
          final expr = arg.expression;
          if (expr is! NullLiteral) {
            if (expr is SimpleStringLiteral) {
              hasSemanticLabel = expr.value.isNotEmpty;
            } else {
              // Assume non-literal values are valid
              hasSemanticLabel = true;
            }
          }
        }

        if (paramName == 'excludeFromSemantics') {
          final expr = arg.expression;
          if (expr is BooleanLiteral && expr.value) {
            isExcludedFromSemantics = true;
          }
        }
      }
    }

    // Check for parent tooltip or ExcludeSemantics wrapper
    final hasTooltip = hasParentTooltip(node);
    final semanticInfo = getSemanticWrappingInfo(node);

    // Report if no semantic label, no tooltip, not excluded, not wrapped in ExcludeSemantics,
    // and not wrapped in Semantics with label
    if (!hasSemanticLabel &&
        !isExcludedFromSemantics &&
        !hasTooltip &&
        !semanticInfo.isExcluded &&
        !semanticInfo.hasSemantics) {
      reporter.atNode(node, code);
    }
  });
}