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>
diff --git a/pkg/scrape/example/annotation_arguments.dart b/pkg/scrape/example/annotation_arguments.dart
new file mode 100644
index 0000000..cf5da95
--- /dev/null
+++ b/pkg/scrape/example/annotation_arguments.dart
@@ -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());
+ }
+ }
+}
diff --git a/pkg/scrape/lib/src/histogram.dart b/pkg/scrape/lib/src/histogram.dart
index 74e35df..e27f137 100644
--- a/pkg/scrape/lib/src/histogram.dart
+++ b/pkg/scrape/lib/src/histogram.dart
@@ -86,14 +86,25 @@
}
}
- 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');
}
}