From dc6e7eb19b4ab0a68f6b0eddc42b2302ac9cd51c Mon Sep 17 00:00:00 2001 From: Tim Blasi Date: Wed, 3 Jun 2015 14:22:24 -0700 Subject: [PATCH] feat(dart/transform): Record Type interfaces To support interface-based lifecycle methods (#2220), we need to be able to query for the `interface`s a class supports. Record implemented interfaces to allow mirror-less querying at runtime. Closes #2204 --- .../common/directive_metadata_reader.dart | 3 +-- .../transform/directive_processor/rewriter.dart | 9 +++++++++ .../lifecycle.ng_deps.dart | 15 +++++++++++++-- .../directive_processor/all_tests.dart | 9 +++++++++ .../expected/soup.ng_deps.dart | 17 +++++++++++++++++ .../interface_chain_files/soup.dart | 12 ++++++++++++ .../interfaces_files/expected/soup.ng_deps.dart | 17 +++++++++++++++++ .../interfaces_files/soup.dart | 6 ++++++ .../superclass_files/expected/soup.ng_deps.dart | 16 ++++++++++++++++ .../superclass_files/soup.dart | 10 ++++++++++ 10 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 modules/angular2/test/transform/directive_processor/interface_chain_files/expected/soup.ng_deps.dart create mode 100644 modules/angular2/test/transform/directive_processor/interface_chain_files/soup.dart create mode 100644 modules/angular2/test/transform/directive_processor/interfaces_files/expected/soup.ng_deps.dart create mode 100644 modules/angular2/test/transform/directive_processor/interfaces_files/soup.dart create mode 100644 modules/angular2/test/transform/directive_processor/superclass_files/expected/soup.ng_deps.dart create mode 100644 modules/angular2/test/transform/directive_processor/superclass_files/soup.dart diff --git a/modules/angular2/src/transform/common/directive_metadata_reader.dart b/modules/angular2/src/transform/common/directive_metadata_reader.dart index a747da1f96..e40495d118 100644 --- a/modules/angular2/src/transform/common/directive_metadata_reader.dart +++ b/modules/angular2/src/transform/common/directive_metadata_reader.dart @@ -66,8 +66,7 @@ class _DirectiveMetadataVisitor extends Object callOnChange: false, callOnCheck: false, callOnInit: false, - callOnAllChangesDone: false - ); + callOnAllChangesDone: false); } @override diff --git a/modules/angular2/src/transform/directive_processor/rewriter.dart b/modules/angular2/src/transform/directive_processor/rewriter.dart index f52031a68a..990175be00 100644 --- a/modules/angular2/src/transform/directive_processor/rewriter.dart +++ b/modules/angular2/src/transform/directive_processor/rewriter.dart @@ -192,6 +192,15 @@ class CreateNgDepsVisitor extends Object with SimpleAstVisitor { } writer.print(''', 'annotations': '''); node.accept(_metaVisitor); + if (node.implementsClause != null && + node.implementsClause.interfaces != null && + node.implementsClause.interfaces.isNotEmpty) { + writer.print(''', 'interfaces': const ['''); + node.implementsClause.interfaces.forEach((interface) { + writer.print('${interface.name}'); + }); + writer.print(']'); + } writer.print('})'); return null; } diff --git a/modules/angular2/test/transform/directive_metadata_extractor/directive_metadata_files/lifecycle.ng_deps.dart b/modules/angular2/test/transform/directive_metadata_extractor/directive_metadata_files/lifecycle.ng_deps.dart index 91165f53e7..1c38c2774d 100644 --- a/modules/angular2/test/transform/directive_metadata_extractor/directive_metadata_files/lifecycle.ng_deps.dart +++ b/modules/angular2/test/transform/directive_metadata_extractor/directive_metadata_files/lifecycle.ng_deps.dart @@ -2,7 +2,17 @@ library examples.hello_world.index_common_dart.ng_deps.dart; import 'hello.dart'; import 'package:angular2/angular2.dart' - show bootstrap, Component, Directive, View, NgElement, onChange, onDestroy, onInit, onCheck, onAllChangesDone; + show + bootstrap, + Component, + Directive, + View, + NgElement, + onChange, + onDestroy, + onInit, + onCheck, + onAllChangesDone; var _visited = false; void initReflector(reflector) { @@ -13,7 +23,8 @@ void initReflector(reflector) { 'factory': () => new HelloCmp(), 'parameters': const [const []], 'annotations': const [ - const Component(lifecycle: [onChange, onDestroy, onInit, onCheck, onAllChangesDone]) + const Component( + lifecycle: [onChange, onDestroy, onInit, onCheck, onAllChangesDone]) ] }); } diff --git a/modules/angular2/test/transform/directive_processor/all_tests.dart b/modules/angular2/test/transform/directive_processor/all_tests.dart index cfc1347700..89b987d7bf 100644 --- a/modules/angular2/test/transform/directive_processor/all_tests.dart +++ b/modules/angular2/test/transform/directive_processor/all_tests.dart @@ -42,6 +42,15 @@ void allTests() { _testNgDeps('should inline `templateUrl`s expressed as adjacent strings.', 'split_url_expression_files/hello.dart'); + + _testNgDeps('should report implemented types as `interfaces`.', + 'interfaces_files/soup.dart'); + + _testNgDeps('should not include transitively implemented types.', + 'interface_chain_files/soup.dart'); + + _testNgDeps('should not include superclasses in `interfaces`.', + 'superclass_files/soup.dart'); } void _testNgDeps(String name, String inputPath, diff --git a/modules/angular2/test/transform/directive_processor/interface_chain_files/expected/soup.ng_deps.dart b/modules/angular2/test/transform/directive_processor/interface_chain_files/expected/soup.ng_deps.dart new file mode 100644 index 0000000000..b6247f4757 --- /dev/null +++ b/modules/angular2/test/transform/directive_processor/interface_chain_files/expected/soup.ng_deps.dart @@ -0,0 +1,17 @@ +library dinner.soup.ng_deps.dart; + +import 'soup.dart'; +import 'package:angular2/src/core/annotations_impl/annotations.dart'; + +var _visited = false; +void initReflector(reflector) { + if (_visited) return; + _visited = true; + reflector + ..registerType(ChangingSoupComponent, { + 'factory': () => new ChangingSoupComponent(), + 'parameters': const [], + 'annotations': const [const Component(selector: '[soup]')], + 'interfaces': const [PrimaryInterface] + }); +} diff --git a/modules/angular2/test/transform/directive_processor/interface_chain_files/soup.dart b/modules/angular2/test/transform/directive_processor/interface_chain_files/soup.dart new file mode 100644 index 0000000000..55de1a4cd4 --- /dev/null +++ b/modules/angular2/test/transform/directive_processor/interface_chain_files/soup.dart @@ -0,0 +1,12 @@ +library dinner.soup; + +import 'package:angular2/src/core/annotations_impl/annotations.dart'; + +@Component(selector: '[soup]') +class ChangingSoupComponent implements PrimaryInterface {} + +class TernaryInterface {} + +class SecondaryInterface implements TernaryInterface {} + +class PrimaryInterface implements SecondaryInterface {} diff --git a/modules/angular2/test/transform/directive_processor/interfaces_files/expected/soup.ng_deps.dart b/modules/angular2/test/transform/directive_processor/interfaces_files/expected/soup.ng_deps.dart new file mode 100644 index 0000000000..3e8cd95092 --- /dev/null +++ b/modules/angular2/test/transform/directive_processor/interfaces_files/expected/soup.ng_deps.dart @@ -0,0 +1,17 @@ +library dinner.soup.ng_deps.dart; + +import 'soup.dart'; +import 'package:angular2/src/core/annotations_impl/annotations.dart'; + +var _visited = false; +void initReflector(reflector) { + if (_visited) return; + _visited = true; + reflector + ..registerType(ChangingSoupComponent, { + 'factory': () => new ChangingSoupComponent(), + 'parameters': const [], + 'annotations': const [const Component(selector: '[soup]')], + 'interfaces': const [OnChange] + }); +} diff --git a/modules/angular2/test/transform/directive_processor/interfaces_files/soup.dart b/modules/angular2/test/transform/directive_processor/interfaces_files/soup.dart new file mode 100644 index 0000000000..0365174837 --- /dev/null +++ b/modules/angular2/test/transform/directive_processor/interfaces_files/soup.dart @@ -0,0 +1,6 @@ +library dinner.soup; + +import 'package:angular2/src/core/annotations_impl/annotations.dart'; + +@Component(selector: '[soup]') +class ChangingSoupComponent implements OnChange {} diff --git a/modules/angular2/test/transform/directive_processor/superclass_files/expected/soup.ng_deps.dart b/modules/angular2/test/transform/directive_processor/superclass_files/expected/soup.ng_deps.dart new file mode 100644 index 0000000000..377813bb16 --- /dev/null +++ b/modules/angular2/test/transform/directive_processor/superclass_files/expected/soup.ng_deps.dart @@ -0,0 +1,16 @@ +library dinner.soup.ng_deps.dart; + +import 'soup.dart'; +import 'package:angular2/src/core/annotations_impl/annotations.dart'; + +var _visited = false; +void initReflector(reflector) { + if (_visited) return; + _visited = true; + reflector + ..registerType(ChangingSoupComponent, { + 'factory': () => new ChangingSoupComponent(), + 'parameters': const [], + 'annotations': const [const Component(selector: '[soup]')] + }); +} diff --git a/modules/angular2/test/transform/directive_processor/superclass_files/soup.dart b/modules/angular2/test/transform/directive_processor/superclass_files/soup.dart new file mode 100644 index 0000000000..ff4a921e12 --- /dev/null +++ b/modules/angular2/test/transform/directive_processor/superclass_files/soup.dart @@ -0,0 +1,10 @@ +library dinner.soup; + +import 'package:angular2/src/core/annotations_impl/annotations.dart'; + +@Component(selector: '[soup]') +class ChangingSoupComponent extends Super {} + +class Iface {} + +class Super implements Iface {}