check method
void
check(
- 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);
}
}
}
});
}