Description
Skip to TL;DR to skip the premise.
Here's some Dart 2 fun:
void parseArgs(List<String> args) {
// ...
}
void main() {
var args = ['command', '--a', '--b', '--c', '--d'];
parseArgs(args.skip(1));
}
The fun, of course, is that there is no static analysis warning for this code, but it might fail at runtime, because an Iterable was passed where a List was expected. Because we do fun implicit casts (#31410), its allowed statically. If, however, we add something like --no-implicit-cast-in-function-arguments
, this code above would not be allowed.
I think, in general, authors of Dart code write too many methods which expect a List as a parameter where an Iterable would work fine. Cleaning up method signatures to expect Iterable arguments will help understand and prevent implicit casts.
TL;DR
I want a lint rule that examines functions with List
(or Queue
or Set
...) parameters, and reports when such a parameter should be an Iterable
instead.
Examples
void fn1(List<String> list) => list.forEach((s) => print(s));
void fn2(List<String> list) {
if (list.isEmpty) return;
print(list.length);
for (var s in list) print(s);
}
Neither fn1
nor fn2
use any List-specific APIs. Nor is list
passed to other functions, which might expect List
arguments. Their signatures should be more lenient, and accept Iterable<String>
.
void fn3(List<String> list) {
fn4(list);
fn5(list);
}
void fn4(Iterable<String> list) => print(list);
void fn5(dynamic list) => print(list);
Here, fn3
does pass list
to other functions, but their signatures expect Iterable
or dynamic
, so we're all good there.
To be conservative against false positives, we can report on more restrictive situations than this... like if its expensive/tricky to see signatures of all methods where list
is passed.
Risk of False Positives
I'm not sure... maybe people write APIs that spell out "I expect a List!" because of performance stuff, like... "I call .length
all the time on this thing, so don't pass an Iterable which has an expensive .length
call" (I'm not sure if that's true, just an example).