Add script to scrape metadata annotation arguments.

Change-Id: Icbe5c84cfa5cb2fe376679b267452d6dcfe61ac8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/206582
Reviewed-by: Jake Macdonald <jakemac@google.com>
Commit-Queue: Bob Nystrom <rnystrom@google.com>
This commit is contained in:
Robert Nystrom 2021-07-12 23:41:32 +00:00 committed by commit-bot@chromium.org
parent 378ab67916
commit dcec42f0b5
2 changed files with 94 additions and 2 deletions

View file

@ -0,0 +1,81 @@
// Copyright (c) 2021, 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';
void main(List<String> arguments) {
Scrape()
..addHistogram('Has argument list?')
..addHistogram('Arguments', order: SortOrder.numeric)
..addHistogram('Argument type')
..addHistogram('Argument identifier')
..addHistogram('Annotation')
..addVisitor(() => AnnotationVisitor())
..runCommandLine(arguments);
}
class AnnotationVisitor extends ScrapeVisitor {
@override
void visitAnnotation(Annotation node) {
record('Annotation', node.name.name);
var arguments = node.arguments;
if (arguments != null) {
record('Has argument list?', 'yes');
record('Arguments', arguments.arguments.length);
arguments.arguments.forEach(_recordArgument);
} else {
record('Has argument list?', 'no');
}
super.visitAnnotation(node);
}
void _recordArgument(AstNode? node) {
if (node is NamedExpression) {
_recordArgument(node.expression);
} else if (node is IfElement) {
_recordArgument(node.thenElement);
_recordArgument(node.elseElement);
} else if (node is ForElement) {
_recordArgument(node.body);
} else if (node is SpreadElement) {
_recordArgument(node.expression);
} else if (node is MapLiteralEntry) {
_recordArgument(node.key);
_recordArgument(node.value);
} else if (node is SimpleIdentifier || node is PrefixedIdentifier) {
record('Argument identifier', node.toString());
record('Argument type', 'identifier');
} else if (node is PrefixExpression) {
record('Argument type', 'unary operator');
} else if (node is BinaryExpression) {
record('Argument type', 'binary operator');
} else if (node is BooleanLiteral) {
record('Argument type', 'bool');
} else if (node is DoubleLiteral) {
record('Argument type', 'double');
} else if (node is IntegerLiteral) {
record('Argument type', 'int');
} else if (node is ListLiteral) {
record('Argument type', 'list');
node.elements.forEach(_recordArgument);
} else if (node is MethodInvocation) {
record('Argument type', 'method call');
} else if (node is NullLiteral) {
record('Argument type', 'null');
} else if (node is SetOrMapLiteral) {
record('Argument type', 'set or map');
node.elements.forEach(_recordArgument);
} else if (node is StringLiteral) {
record('Argument type', 'string');
} else if (node is SymbolLiteral) {
record('Argument type', 'symbol');
} else if (node == null) {
// Do nothing. Only happens for null else elements.
} else {
record('Argument type', node.runtimeType.toString());
}
}
}

View file

@ -86,14 +86,25 @@ class Histogram {
}
}
if (skipped > 0) print('And $skipped more less than 0.1%...');
if (skipped > 0) print('And $skipped more...');
// If we're counting numeric keys, show other statistics too.
if (_order == SortOrder.numeric && keys.isNotEmpty) {
var sum = keys.fold<int>(
0, (result, key) => result + (key as int) * _counts[key]!);
var average = sum / total;
var median = _counts[keys[keys.length ~/ 2]];
// Find the median key where half the total count is below it.
var count = 0;
var median = -1;
for (var key in keys) {
count += _counts[key]!;
if (count >= total ~/ 2) {
median = key as int;
break;
}
}
print('Sum $sum, average ${average.toStringAsFixed(3)}, median $median');
}
}