diff --git a/pkg/front_end/test/incremental_load_from_dill_suite.dart b/pkg/front_end/test/incremental_load_from_dill_suite.dart index 29e76fe820a..79b25aa0f4c 100644 --- a/pkg/front_end/test/incremental_load_from_dill_suite.dart +++ b/pkg/front_end/test/incremental_load_from_dill_suite.dart @@ -40,12 +40,14 @@ import 'package:front_end/src/fasta/incremental_compiler.dart' import 'package:front_end/src/fasta/incremental_serializer.dart' show IncrementalSerializer; +import 'package:front_end/src/fasta/kernel/kernel_api.dart'; import 'package:front_end/src/fasta/kernel/utils.dart' show ByteSink; import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder; import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter; +import 'package:kernel/class_hierarchy.dart'; import 'package:kernel/kernel.dart' show @@ -55,6 +57,7 @@ import 'package:kernel/kernel.dart' Field, Library, LibraryDependency, + Member, Name, Procedure; @@ -608,25 +611,8 @@ Future newWorldTest( } } - Uri uri = data.loadedFrom - .resolve(data.loadedFrom.pathSegments.last + ".world.$worldNum.expect"); - String expected; - File file = new File.fromUri(uri); - if (context.updateExpectations) { - file.writeAsStringSync(actualSerialized); - } - if (file.existsSync()) { - expected = file.readAsStringSync(); - } - if (context.updateExpectations) { - file.writeAsStringSync(actualSerialized); - } else if (expected != actualSerialized) { - String extra = ""; - if (expected == null) extra = "Expect file did not exist.\n"; - throw "${extra}Unexpected serialized representation. " - "Fix or update $uri to contain the below:\n\n" - "$actualSerialized"; - } + checkExpectFile(data, worldNum, context, actualSerialized); + checkClassHierarchy(compiler, component, data, worldNum, context); int nonSyntheticLibraries = countNonSyntheticLibraries(component); int nonSyntheticPlatformLibraries = @@ -848,6 +834,166 @@ Future newWorldTest( } } +void checkExpectFile( + TestData data, int worldNum, Context context, String actualSerialized) { + Uri uri = data.loadedFrom + .resolve(data.loadedFrom.pathSegments.last + ".world.$worldNum.expect"); + String expected; + File file = new File.fromUri(uri); + if (file.existsSync()) { + expected = file.readAsStringSync(); + } + if (expected != actualSerialized) { + if (context.updateExpectations) { + file.writeAsStringSync(actualSerialized); + } else { + String extra = ""; + if (expected == null) extra = "Expect file did not exist.\n"; + throw "${extra}Unexpected serialized representation. " + "Fix or update $uri to contain the below:\n\n" + "$actualSerialized"; + } + } +} + +/// Check that the class hierarchy is up-to-date with reality. +/// +/// This has the option to do expect files, but it's disabled by default +/// while we're trying to figure out if it's useful or not. +void checkClassHierarchy(TestIncrementalCompiler compiler, Component component, + TestData data, int worldNum, Context context, + {bool checkExpectFile: false}) { + ClassHierarchy classHierarchy = compiler.getClassHierarchy(); + if (classHierarchy is! ClosedWorldClassHierarchy) { + throw "Expected the class hierarchy to be ClosedWorldClassHierarchy " + "but it wasn't. It was ${classHierarchy.runtimeType}"; + } + List classHierarchyData = + (classHierarchy as ClosedWorldClassHierarchy).getTestingClassInfo(); + Map classHierarchyMap = + new Map(); + for (ForTestingClassInfo info in classHierarchyData) { + if (classHierarchyMap[info.classNode] != null) { + throw "Two entries for ${info.classNode}"; + } + classHierarchyMap[info.classNode] = info; + } + + StringBuffer sb = new StringBuffer(); + for (Library library in component.libraries) { + if (library.importUri.scheme == "dart") continue; + sb.writeln("Library ${library.importUri}"); + for (Class c in library.classes) { + sb.writeln(" - Class ${c.name}"); + ForTestingClassInfo info = classHierarchyMap[c]; + if (info == null) { + throw "Didn't find any class hierarchy info for $c"; + } + if (info.lazyDeclaredGettersAndCalls != null) { + sb.writeln(" - lazyDeclaredGettersAndCalls:"); + for (Member member in info.lazyDeclaredGettersAndCalls) { + sb.writeln(" - ${member.name.name}"); + } + + // Expect these to be the same as in the class. + Set members = info.lazyDeclaredGettersAndCalls.toSet(); + for (Field f in c.fields) { + if (f.isStatic) continue; + if (!f.hasImplicitGetter) continue; + if (!members.remove(f)) { + throw "Didn't find ${f.name.name} in lazyDeclaredGettersAndCalls " + "for ${c.name} in ${library.importUri}"; + } + } + for (Procedure p in c.procedures) { + if (p.isStatic) continue; + if (p.isSetter) continue; + if (!members.remove(p)) { + throw "Didn't find ${p.name.name} in lazyDeclaredGettersAndCalls " + "for ${c.name} in ${library.importUri}"; + } + } + if (members.isNotEmpty) { + throw "Still have ${members.map((m) => m.name.name)} left " + "for ${c.name} in ${library.importUri}"; + } + } + if (info.lazyDeclaredSetters != null) { + sb.writeln(" - lazyDeclaredSetters:"); + for (Member member in info.lazyDeclaredSetters) { + sb.writeln(" - ${member.name.name}"); + } + + // Expect these to be the same as in the class. + Set members = info.lazyDeclaredSetters.toSet(); + for (Field f in c.fields) { + if (f.isStatic) continue; + if (!f.hasImplicitSetter) continue; + if (!members.remove(f)) { + throw "Didn't find $f in lazyDeclaredSetters for $c"; + } + } + for (Procedure p in c.procedures) { + if (p.isStatic) continue; + if (!p.isSetter) continue; + if (!members.remove(p)) { + throw "Didn't find $p in lazyDeclaredSetters for $c"; + } + } + if (members.isNotEmpty) { + throw "Still have ${members.map((m) => m.name.name)} left " + "for ${c.name} in ${library.importUri}"; + } + } + if (info.lazyImplementedGettersAndCalls != null) { + sb.writeln(" - lazyImplementedGettersAndCalls:"); + for (Member member in info.lazyImplementedGettersAndCalls) { + sb.writeln(" - ${member.name.name}"); + } + } + if (info.lazyImplementedSetters != null) { + sb.writeln(" - lazyImplementedSetters:"); + for (Member member in info.lazyImplementedSetters) { + sb.writeln(" - ${member.name.name}"); + } + } + if (info.lazyInterfaceGettersAndCalls != null) { + sb.writeln(" - lazyInterfaceGettersAndCalls:"); + for (Member member in info.lazyInterfaceGettersAndCalls) { + sb.writeln(" - ${member.name.name}"); + } + } + if (info.lazyInterfaceSetters != null) { + sb.writeln(" - lazyInterfaceSetters:"); + for (Member member in info.lazyInterfaceSetters) { + sb.writeln(" - ${member.name.name}"); + } + } + } + } + if (checkExpectFile) { + String actualClassHierarchy = sb.toString(); + Uri uri = data.loadedFrom.resolve(data.loadedFrom.pathSegments.last + + ".world.$worldNum.class_hierarchy.expect"); + String expected; + File file = new File.fromUri(uri); + if (file.existsSync()) { + expected = file.readAsStringSync(); + } + if (expected != actualClassHierarchy) { + if (context.updateExpectations) { + file.writeAsStringSync(actualClassHierarchy); + } else { + String extra = ""; + if (expected == null) extra = "Expect file did not exist.\n"; + throw "${extra}Unexpected serialized representation. " + "Fix or update $uri to contain the below:\n\n" + "$actualClassHierarchy"; + } + } + } +} + void checkErrorsAndWarnings( Set prevFormattedErrors, Set formattedErrors, @@ -899,14 +1045,14 @@ List checkIncrementalSerialization( throw "Incremental serialization didn't remove any libraries!"; } if (librariesAfter < librariesBefore && sink.builder.isEmpty) { - throw "Incremental serialization din't output any bytes, " + throw "Incremental serialization didn't output any bytes, " "but did remove libraries"; } else if (librariesAfter == librariesBefore && !sink.builder.isEmpty) { throw "Incremental serialization did output bytes, " "but didn't remove libraries"; } if (librariesAfter < librariesBefore) { - // If we actually did incremenally serialize anything, check the output! + // If we actually did incrementally serialize anything, check the output! BinaryPrinter printer = new BinaryPrinter(sink); printer.writeComponentFile(c); List bytes = sink.builder.takeBytes(); @@ -1389,10 +1535,10 @@ class TestIncrementalCompiler extends IncrementalCompiler { void doSimulateTransformer(Component c) { for (Library lib in c.libraries) { if (lib.fields - .where((f) => f.name.name == "lalala_SimulateTransformer") + .where((f) => f.name.name == "unique_SimulateTransformer") .toList() .isNotEmpty) continue; - Name fieldName = new Name("lalala_SimulateTransformer"); + Name fieldName = new Name("unique_SimulateTransformer"); Field field = new Field(fieldName, isFinal: true, reference: lib.reference.canonicalName @@ -1401,10 +1547,10 @@ void doSimulateTransformer(Component c) { lib.addMember(field); for (Class c in lib.classes) { if (c.fields - .where((f) => f.name.name == "lalala_SimulateTransformer") + .where((f) => f.name.name == "unique_SimulateTransformer") .toList() .isNotEmpty) continue; - fieldName = new Name("lalala_SimulateTransformer"); + fieldName = new Name("unique_SimulateTransformer"); field = new Field(fieldName, isFinal: true, reference: c.reference.canonicalName diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt index 8a6399285c1..b2ce7b9e26a 100644 --- a/pkg/front_end/test/spell_checking_list_tests.txt +++ b/pkg/front_end/test/spell_checking_list_tests.txt @@ -57,6 +57,7 @@ boo bootstrap bots bowtie +brand brave brown builddir @@ -111,6 +112,7 @@ dartfile dashes day db +debugger decrease decrements def @@ -190,6 +192,7 @@ func futures gallery gamma +gave gc gen generators @@ -201,6 +204,7 @@ gulp gunk hackish harness +helper2 hest heuristics hi @@ -276,6 +280,8 @@ moo mx mysdk negatable +newest +newworld ninja nonexisting noo @@ -359,6 +365,8 @@ shipped shortest shot signalled +slight +smoke somehow spans spell @@ -434,6 +442,7 @@ whitelist whitelisting wins workflow +worlds ws x's xxx diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml index a98a4f57fc4..16093f7856f 100644 --- a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml +++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml @@ -35,10 +35,10 @@ worlds: expectedContent: org-dartlang-test:///main.dart: - Procedure main - - Field lalala_SimulateTransformer + - Field unique_SimulateTransformer package:foo/foo.dart: - Field foo - - Field lalala_SimulateTransformer + - Field unique_SimulateTransformer neededDillLibraries: - package:foo/foo.dart - entry: main.dart @@ -61,7 +61,7 @@ worlds: expectedContent: org-dartlang-test:///main.dart: - Procedure main - - Field lalala_SimulateTransformer + - Field unique_SimulateTransformer package:foo/foo.dart: - Field foo2 - - Field lalala_SimulateTransformer + - Field unique_SimulateTransformer diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml.world.1.expect index 71e4ef19fa4..6ece7a5f766 100644 --- a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml.world.1.expect +++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml.world.1.expect @@ -2,13 +2,13 @@ main = ; library from "package:foo/foo.dart" as foo { static field dart.core::bool* foo = true; - final field dynamic lalala_SimulateTransformer /* from null */; + final field dynamic unique_SimulateTransformer /* from null */; } library from "org-dartlang-test:///main.dart" as main { import "package:foo/foo.dart"; - final field dynamic lalala_SimulateTransformer /* from null */; + final field dynamic unique_SimulateTransformer /* from null */; static method main() → dynamic { dart.core::print(foo::foo); } diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml.world.2.expect index e13a156e841..90090ad4817 100644 --- a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml.world.2.expect +++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml.world.2.expect @@ -2,13 +2,13 @@ main = ; library from "package:foo/foo.dart" as foo { static field dart.core::bool* foo2 = true; - final field dynamic lalala_SimulateTransformer /* from null */; + final field dynamic unique_SimulateTransformer /* from null */; } library from "org-dartlang-test:///main.dart" as main { import "package:foo/foo.dart"; - final field dynamic lalala_SimulateTransformer /* from null */; + final field dynamic unique_SimulateTransformer /* from null */; static method main() → dynamic { dart.core::print(foo::foo2); } diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/status.status b/pkg/front_end/testcases/incremental_initialize_from_dill/status.status index a7bcd3bf061..9ac8e039d50 100644 --- a/pkg/front_end/testcases/incremental_initialize_from_dill/status.status +++ b/pkg/front_end/testcases/incremental_initialize_from_dill/status.status @@ -4,6 +4,9 @@ # Status file for the test suite ../test/incremental_load_from_dill_test.dart. +ffi_01: Crash # Class hierarchy is out of date. +ffi_02: Crash # Class hierarchy is out of date. + no_outline_change_1: Crash # Doesn't work on DillLibraryBuilders. no_outline_change_2: Crash # Doesn't work on DillLibraryBuilders. no_outline_change_6: Crash # Doesn't work on DillLibraryBuilders. diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json index afa117c9143..5032126645b 100644 --- a/pkg/front_end/testing.json +++ b/pkg/front_end/testing.json @@ -284,8 +284,6 @@ "test/fasta/super_mixins_test\\.dart$", "test/fasta/types/subtypes_benchmark\\.dart$", "test/fasta/unlinked_scope_test\\.dart$", - "test/incremental_load_from_dill_suite\\.dart$", - "test/incremental_load_from_invalid_dill_test\\.dart$", "test/memory_file_system_test\\.dart$", "test/scanner_fasta_test\\.dart$", "test/scanner_test\\.dart$", diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart index 977cd45c34c..61e8b79bb15 100644 --- a/pkg/kernel/lib/class_hierarchy.dart +++ b/pkg/kernel/lib/class_hierarchy.dart @@ -451,6 +451,14 @@ class ClosedWorldClassHierarchy implements ClassHierarchy { final Map _infoMap = new LinkedHashMap(); + List getTestingClassInfo() { + List result = new List(); + for (_ClassInfo info in _infoMap.values) { + result.add(new ForTestingClassInfo._(info)); + } + return result; + } + _ClassInfo infoFor(Class c) { _ClassInfo info = _infoMap[c]; info?.used = true; @@ -1444,6 +1452,25 @@ int _intervalListSize(Uint32List intervalList) { return size; } +class ForTestingClassInfo { + final Class classNode; + final List lazyDeclaredGettersAndCalls; + final List lazyDeclaredSetters; + final List lazyImplementedGettersAndCalls; + final List lazyImplementedSetters; + final List lazyInterfaceGettersAndCalls; + final List lazyInterfaceSetters; + + ForTestingClassInfo._(_ClassInfo c) + : classNode = c.classNode, + lazyDeclaredGettersAndCalls = c.lazyDeclaredGettersAndCalls, + lazyDeclaredSetters = c.lazyDeclaredSetters, + lazyImplementedGettersAndCalls = c.lazyImplementedGettersAndCalls, + lazyImplementedSetters = c.lazyImplementedSetters, + lazyInterfaceGettersAndCalls = c.lazyInterfaceGettersAndCalls, + lazyInterfaceSetters = c.lazyInterfaceSetters; +} + class _ClassInfo { bool used = false; final Class classNode;