blob: af39416b6ae1d53b7035b3c95bc6f2a2d79691cd [file] [log] [blame]
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/ast/ast.dart';
import 'package:scrape/scrape.dart';
/// Looks at expressions that could likely be converted to spread operators and
/// measures their length. "Likely" means calls to `addAll()` where the
/// receiver is a list or map literal.
void main(List<String> arguments) {
..addHistogram('Lengths', order: SortOrder.numeric)
..addVisitor(() => SpreadVisitor())
class SpreadVisitor extends ScrapeVisitor {
void visitCascadeExpression(CascadeExpression node) {
for (var section in node.cascadeSections) {
if (section is MethodInvocation) {
_countCall(node, section.methodName,, section.argumentList);
void visitMethodInvocation(MethodInvocation node) {
_countCall(node, node.methodName,, node.argumentList);
void _countCall(Expression node, SimpleIdentifier name, Expression? target,
ArgumentList args) {
if ( != 'addAll') return;
// See if the target is a collection literal.
while (target is MethodInvocation) {
target =;
if (target is ListLiteral || target is SetOrMapLiteral) {
if (args.arguments.length == 1) {
var arg = args.arguments[0];
record('Arguments', arg.toString());
record('Lengths', arg.length);