check method

  1. @override
void check(
  1. DcqRegistry registry
)

Implementation

@override
void check(DcqRegistry registry) {
  final optionalParams = <int, List<FormalParameter>>{};
  final requiredPositionalCounts = <int, int>{};
  final callArgs = <int, List<ArgumentList>>{};

  registry.addFunctionDeclaration((node) {
    final element = node.declaredFragment?.element;
    if (element == null || !element.isPrivate) return;
    final paramList = node.functionExpression.parameters;
    if (paramList == null) return;
    final optional = <FormalParameter>[
      for (final p in paramList.parameters)
        if (p.isOptional) p,
    ];
    if (optional.isNotEmpty) {
      optionalParams[element.id] = optional;
      requiredPositionalCounts[element.id] = paramList.parameters
          .where((p) => p.isPositional && p.isRequired)
          .length;
    }
  });

  registry.addMethodDeclaration((node) {
    final element = node.declaredFragment?.element;
    if (element == null || !element.isPrivate) return;
    final paramList = node.parameters;
    if (paramList == null) return;
    final optional = <FormalParameter>[
      for (final p in paramList.parameters)
        if (p.isOptional) p,
    ];
    if (optional.isNotEmpty) {
      optionalParams[element.id] = optional;
      requiredPositionalCounts[element.id] = paramList.parameters
          .where((p) => p.isPositional && p.isRequired)
          .length;
    }
  });

  registry.addMethodInvocation((node) {
    final element = node.methodName.element;
    if (element is! ExecutableElement || !element.isPrivate) return;
    callArgs.putIfAbsent(element.id, () => []).add(node.argumentList);
  });

  registry.afterLibrary(() {
    for (final entry in optionalParams.entries) {
      final id = entry.key;
      final params = entry.value;
      final calls = callArgs[id];
      if (calls == null || calls.isEmpty) continue;

      for (final param in params) {
        final name = param.name?.lexeme;
        if (name == null) continue;

        final neverPassed = calls.every((argList) {
          if (param.isNamed) {
            return !argList.arguments.any(
              (a) => a is NamedExpression && a.name.label.name == name,
            );
          }
          // Positional optional — count positional args supplied.
          final positionalCount = argList.arguments
              .where((a) => a is! NamedExpression)
              .length;
          final reqCount = requiredPositionalCounts[id] ?? 0;
          final allOptional = optionalParams[id]!;
          final indexInOptional = allOptional.indexOf(param);
          // The absolute position of this param is reqCount + indexInOptional.
          return positionalCount <= reqCount + indexInOptional;
        });

        if (neverPassed) {
          reportAtNode(param);
        }
      }
    }
  });
}