| // Copyright (c) 2019, 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. |
| |
| /// Test to ensure that desugaring APIs used by clients like dart2js are |
| /// always up to date. |
| /// |
| /// Desugaring APIs are methods that inspect the kernel output to find |
| /// structures that are assumed to always be generated by the CFE. If the CFE |
| /// changes its invariants, the desugaring APIs will change together to hide |
| /// these changes from clients. |
| |
| import 'dart:io'; |
| |
| import 'package:async_helper/async_helper.dart'; |
| import 'package:expect/expect.dart'; |
| import 'package:front_end/src/api_unstable/dart2js.dart' as api; |
| import 'package:front_end/src/compute_platform_binaries_location.dart'; |
| import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent; |
| import 'package:front_end/src/testing/compiler_common.dart'; |
| import 'package:kernel/ast.dart' as ir; |
| import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder; |
| |
| Future<void> main() async { |
| await asyncTest(() async { |
| await testRedirectingFactoryDirect(); |
| await testRedirectingFactorySerialized(); |
| await testRedirectingFactoryPatchFile(); |
| }); |
| } |
| |
| Future<void> testRedirectingFactoryDirect() async { |
| var component = await compileUnit(['a.dart'], {'a.dart': aSource}); |
| checkIsRedirectingFactory(component!, 'a.dart', 'A', 'foo'); |
| checkIsRedirectingFactory(component, 'core', 'Uri', 'file'); |
| } |
| |
| Future<void> testRedirectingFactorySerialized() async { |
| var component = await compileUnit(['a.dart'], {'a.dart': aSource}); |
| var bytes = serializeComponent(component!); |
| component = new ir.Component(); |
| new BinaryBuilder(bytes).readComponent(component); |
| checkIsRedirectingFactory(component, 'a.dart', 'A', 'foo'); |
| checkIsRedirectingFactory(component, 'core', 'Uri', 'file'); |
| } |
| |
| // regression test: redirecting factories from patch files don't have the |
| // redirecting-factory flag stored in kernel. |
| Future<void> testRedirectingFactoryPatchFile() async { |
| var componentUri = |
| computePlatformBinariesLocation().resolve('dart2js_platform.dill'); |
| var component = new ir.Component(); |
| new BinaryBuilder(new File.fromUri(componentUri).readAsBytesSync()) |
| .readComponent(component); |
| checkIsRedirectingFactory(component, 'collection', 'HashMap', 'identity'); |
| } |
| |
| void checkIsRedirectingFactory(ir.Component component, String uriPath, |
| String className, String constructorName) { |
| var lib = |
| component.libraries.firstWhere((l) => l.importUri.path.endsWith(uriPath)); |
| var cls = lib.classes.firstWhere((c) => c.name == className); |
| ir.Procedure member = cls.members |
| .firstWhere((m) => m.name.text == constructorName) as ir.Procedure; |
| Expect.isTrue( |
| member.kind == ir.ProcedureKind.Factory, "$member is not a factory"); |
| Expect.isTrue(api.isRedirectingFactory(member)); |
| Expect.isTrue(member.isRedirectingFactory); |
| } |
| |
| const aSource = ''' |
| class A { |
| factory A.foo(int x) = _B; |
| } |
| |
| class _B implements A { |
| _B(int x); |
| } |
| '''; |