check method
void
check(
- DcqRegistry registry
)
Implementation
@override
void check(DcqRegistry registry) {
final nullableParams = <int, List<_ParamInfo>>{};
final callArgs = <int, List<_CallInfo>>{};
void collectParams(int id, FormalParameterList? paramList) {
if (paramList == null) return;
final nullable = <_ParamInfo>[];
var positionalIdx = 0;
for (final p in paramList.parameters) {
final isNamed = p.isNamed;
final idx = isNamed ? -1 : positionalIdx;
if (!isNamed) positionalIdx++;
if (p.declaredFragment?.element.type.nullabilitySuffix ==
NullabilitySuffix.question) {
nullable.add(_ParamInfo(p, idx));
}
}
if (nullable.isNotEmpty) nullableParams[id] = nullable;
}
registry.addFunctionDeclaration((node) {
final element = node.declaredFragment?.element;
if (element == null || !element.isPrivate) return;
collectParams(element.id, node.functionExpression.parameters);
});
registry.addMethodDeclaration((node) {
final element = node.declaredFragment?.element;
if (element == null || !element.isPrivate) return;
collectParams(element.id, node.parameters);
});
registry.addMethodInvocation((node) {
final element = node.methodName.element;
if (element is! ExecutableElement || !element.isPrivate) return;
callArgs
.putIfAbsent(element.id, () => [])
.add(_CallInfo(node.argumentList));
});
registry.afterLibrary(() {
for (final entry in nullableParams.entries) {
final calls = callArgs[entry.key];
if (calls == null || calls.isEmpty) continue;
for (final info in entry.value) {
final name = info.param.name?.lexeme;
if (name == null) continue;
final neverNull = calls.every((call) {
final arg = call.findArg(
name,
info.param.isNamed,
info.positionalIndex,
);
// If arg is omitted (optional), treat as null.
if (arg == null) return info.param.isRequired;
return arg is! NullLiteral;
});
if (neverNull) {
reportAtNode(info.param);
}
}
}
});
}