BenchMaker: collect used type parameters
Change-Id: If6c18e66eded0ebe73575cca28dd77e5ae374890
Reviewed-on: https://dart-review.googlesource.com/c/93950
Commit-Queue: Peter von der Ahé <ahe@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/test/fasta/types/kernel_type_parser.dart b/pkg/front_end/test/fasta/types/kernel_type_parser.dart
index 5bf1d1c..961bf3c 100644
--- a/pkg/front_end/test/fasta/types/kernel_type_parser.dart
+++ b/pkg/front_end/test/fasta/types/kernel_type_parser.dart
@@ -291,7 +291,7 @@
typeParameter
..bound = type
// The default type will be overridden below, but we need to set it
- // so [calculateBounds] can destinquish between explicit and implicit
+ // so [calculateBounds] can distinguish between explicit and implicit
// bounds.
..defaultType = type;
}
diff --git a/pkg/front_end/tool/_fasta/bench_maker.dart b/pkg/front_end/tool/_fasta/bench_maker.dart
index 6eab1c3..35ef460 100644
--- a/pkg/front_end/tool/_fasta/bench_maker.dart
+++ b/pkg/front_end/tool/_fasta/bench_maker.dart
@@ -36,7 +36,7 @@
class BenchMaker implements DartTypeVisitor1<void, StringBuffer> {
final List<Object> checks = <Object>[];
- final Map<Class, String> classNames = <Class, String>{};
+ final Map<TreeNode, String> nodeNames = <TreeNode, String>{};
final Set<String> usedNames = new Set<String>();
@@ -44,6 +44,8 @@
final List<String> classes = <String>[];
+ final List<TypeParameter> usedTypeParameters = <TypeParameter>[];
+
String serializeTypeChecks(List<Object> typeChecks) {
for (List<Object> list in typeChecks) {
writeTypeCheck(list[0], list[1], list[2]);
@@ -53,24 +55,66 @@
}
void writeTypeCheck(DartType s, DartType t, bool expected) {
- List<String> arguments = new List<String>(2);
- Map<String, dynamic> typeCheck = <String, dynamic>{
- "kind": expected ? "isSubtype" : "isNotSubtype",
- "arguments": arguments,
- };
+ assert(usedTypeParameters.isEmpty);
+ usedTypeParameters.clear();
StringBuffer sb = new StringBuffer();
s.accept1(this, sb);
- arguments[0] = "$sb";
+ String sString = "$sb";
sb.clear();
t.accept1(this, sb);
- arguments[1] = "$sb";
- checks.add(typeCheck);
+ String tString = "$sb";
+ List<Object> arguments = <Object>[sString, tString];
+ Set<TypeParameter> seenTypeParameters = new Set<TypeParameter>();
+ List<String> parameterStrings = <String>[];
+ while (usedTypeParameters.isNotEmpty) {
+ List<TypeParameter> typeParameters = usedTypeParameters.toList();
+ usedTypeParameters.clear();
+ for (TypeParameter parameter in typeParameters) {
+ if (seenTypeParameters.add(parameter)) {
+ sb.clear();
+ writeTypeParameter(parameter, sb);
+ parameterStrings.add("$sb");
+ }
+ }
+ }
+ if (parameterStrings.isNotEmpty) {
+ arguments.add(parameterStrings);
+ }
+ checks.add(<String, dynamic>{
+ "kind": expected ? "isSubtype" : "isNotSubtype",
+ "arguments": arguments,
+ });
+ }
+
+ void writeTypeParameter(TypeParameter parameter, StringBuffer sb) {
+ sb.write(computeName(parameter));
+ if (parameter.defaultType is! DynamicType ||
+ parameter.bound is DynamicType) {
+ sb.write(" extends ");
+ parameter.bound.accept1(this, sb);
+ }
+ }
+
+ void writeTypeParameters(
+ List<TypeParameter> typeParameters, StringBuffer sb) {
+ if (typeParameters.isNotEmpty) {
+ sb.write("<");
+ bool first = true;
+ for (TypeParameter p in typeParameters) {
+ if (!first) sb.write(", ");
+ writeTypeParameter(p, sb);
+ first = false;
+ }
+ sb.write(">");
+ }
}
void writeClasses() {
Set<Class> writtenClasses = new Set<Class>();
- for (Class cls in classNames.keys.toList()) {
- writeClass(cls, writtenClasses);
+ for (TreeNode node in nodeNames.keys.toList()) {
+ if (node is Class) {
+ writeClass(node, writtenClasses);
+ }
}
}
@@ -86,6 +130,7 @@
StringBuffer sb = new StringBuffer();
sb.write("class ");
sb.write(computeName(cls));
+ writeTypeParameters(cls.typeParameters, sb);
if (supertype != null) {
sb.write(" extends ");
supertype.asInterfaceType.accept1(this, sb);
@@ -120,23 +165,23 @@
classes.add("$sb");
}
- String computeName(Class cls) {
- String name = classNames[cls];
+ String computeName(TreeNode node) {
+ String name = nodeNames[node];
if (name != null) return name;
- Library library = cls.enclosingLibrary;
- if ("${library.importUri}" == "dart:core") {
- if (!usedNames.add(cls.name)) {
- throw "Class name conflict for $cls";
+ if (node is Class) {
+ Library library = node.enclosingLibrary;
+ if ("${library?.importUri}" == "dart:core") {
+ if (!usedNames.add(node.name)) {
+ throw "Class name conflict for $node";
+ }
+ return nodeNames[node] = node.name;
}
- return classNames[cls] = cls.name;
- } else {
- String name;
- while (!usedNames.add(name = names.current)) {
- names.moveNext();
- }
- names.moveNext();
- return classNames[cls] = name;
}
+ while (!usedNames.add(name = names.current)) {
+ names.moveNext();
+ }
+ names.moveNext();
+ return nodeNames[node] = name;
}
@override
@@ -185,18 +230,7 @@
@override
void visitFunctionType(FunctionType node, StringBuffer sb) {
- if (node.typeParameters.isNotEmpty) {
- sb.write("<");
- bool first = true;
- for (TypeParameter p in node.typeParameters) {
- if (!first) sb.write(", ");
- sb.write(p.name);
- sb.write(" extends ");
- p.bound.accept1(this, sb);
- first = false;
- }
- sb.write(">");
- }
+ writeTypeParameters(node.typeParameters, sb);
sb.write("(");
bool first = true;
for (int i = 0; i < node.requiredParameterCount; i++) {
@@ -238,10 +272,13 @@
@override
void visitTypeParameterType(TypeParameterType node, StringBuffer sb) {
- // TODO(ahe): We need to collect used type parameters. See
- // pkg/front_end/test/fasta/types/shared_type_tests.dart for how they can
- // be used in testing subtype checks.
- sb.write(node.parameter.name);
+ String name = computeName(node.parameter);
+ usedTypeParameters.add(node.parameter);
+ sb.write(name);
+ if (node.promotedBound != null) {
+ sb.write(" & ");
+ node.promotedBound.accept1(this, sb);
+ }
}
@override