From fcc6f2c5614ed34660ace9b0cf2d2ad980e149d3 Mon Sep 17 00:00:00 2001 From: Tim Blasi Date: Wed, 7 Oct 2015 10:03:50 -0700 Subject: [PATCH] refactor(dart/transform): Generate `inputs` setters in `TemplateCompiler` step Move generation of setters for `inputs` from `BindGenerator` into `TemplateCompiler`. --- .../transform/bind_generator/generator.dart | 33 +------------ .../src/transform/bind_generator/visitor.dart | 30 ------------ .../reflection/processor.dart | 13 +++-- .../transform/bind_generator/all_tests.dart | 22 --------- .../template_compiler/all_tests.dart | 37 +++++++++++++- .../component_inputs_files/bar.ng_deps.dart | 18 +++++++ .../component_inputs_files/bar.ng_meta.json | 32 +++++++++++++ .../expected/bar.ng_deps.dart | 22 +++++++++ .../directive_inputs_files}/bar.ng_deps.dart | 0 .../directive_inputs_files/bar.ng_meta.json | 25 ++++++++++ .../expected/bar.ng_deps.dart | 0 .../expected/soup.ng_deps.dart | 15 +++--- .../soup.ng_deps.dart | 15 +++--- .../soup.ng_meta.json | 48 +++++++++++++++++++ 14 files changed, 207 insertions(+), 103 deletions(-) delete mode 100644 modules_dart/transform/lib/src/transform/bind_generator/visitor.dart create mode 100644 modules_dart/transform/test/transform/template_compiler/component_inputs_files/bar.ng_deps.dart create mode 100644 modules_dart/transform/test/transform/template_compiler/component_inputs_files/bar.ng_meta.json create mode 100644 modules_dart/transform/test/transform/template_compiler/component_inputs_files/expected/bar.ng_deps.dart rename modules_dart/transform/test/transform/{bind_generator/basic_bind_files => template_compiler/directive_inputs_files}/bar.ng_deps.dart (100%) create mode 100644 modules_dart/transform/test/transform/template_compiler/directive_inputs_files/bar.ng_meta.json rename modules_dart/transform/test/transform/{bind_generator/basic_bind_files => template_compiler/directive_inputs_files}/expected/bar.ng_deps.dart (100%) rename modules_dart/transform/test/transform/{bind_generator/duplicate_bind_name_files => template_compiler/duplicate_input_name_files}/expected/soup.ng_deps.dart (55%) rename modules_dart/transform/test/transform/{bind_generator/duplicate_bind_name_files => template_compiler/duplicate_input_name_files}/soup.ng_deps.dart (52%) create mode 100644 modules_dart/transform/test/transform/template_compiler/duplicate_input_name_files/soup.ng_meta.json diff --git a/modules_dart/transform/lib/src/transform/bind_generator/generator.dart b/modules_dart/transform/lib/src/transform/bind_generator/generator.dart index df9285ac39..d0a374dea6 100644 --- a/modules_dart/transform/lib/src/transform/bind_generator/generator.dart +++ b/modules_dart/transform/lib/src/transform/bind_generator/generator.dart @@ -8,8 +8,6 @@ import 'package:angular2/src/transform/common/ng_deps.dart'; import 'package:angular2/src/transform/common/property_utils.dart' as prop; import 'package:barback/barback.dart'; -import 'visitor.dart'; - class _ExtractQueryFieldsFromAnnotation extends Object with RecursiveAstVisitor { final ConstantEvaluator _evaluator = new ConstantEvaluator(); @@ -73,7 +71,7 @@ Future createNgSettersAndGetters( NgDeps ngDeps = await NgDeps.parse(reader, entryPoint); String code = ngDeps.code; - var setters = _generateSetters(_createInputPropertiesMap(ngDeps)); + var setters = []; ngDeps.registeredTypes.forEach((t) { final fromAnnotation = new _ExtractQueryFieldsFromAnnotation(); @@ -116,32 +114,3 @@ List _generateSetters(Map bindMap) { }); return setters; } - -/// Collapses all `inputs` in {@link ngDeps} into a map where the keys are -/// the bind inputs and the values are either the one and only type -/// binding to that property or the empty string. -Map _createInputPropertiesMap(NgDeps ngDeps) { - var visitor = new ExtractNamedExpressionVisitor('inputs'); - var bindMap = {}; - ngDeps.registeredTypes.forEach((RegisteredType t) { - visitor.bindConfig.clear(); - t.annotations.accept(visitor); - visitor.bindConfig.forEach((String config) { - // See comments for `Directive` in annotations_impl/annotations.ts for - // details on how `inputs` is specified. - var prop; - var idx = config.indexOf(':'); - if (idx > 0) { - prop = config.substring(0, idx).trim(); - } else { - prop = config; - } - if (bindMap.containsKey(prop)) { - bindMap[prop] = ''; - } else { - bindMap[prop] = '${t.typeName}'; - } - }); - }); - return bindMap; -} diff --git a/modules_dart/transform/lib/src/transform/bind_generator/visitor.dart b/modules_dart/transform/lib/src/transform/bind_generator/visitor.dart deleted file mode 100644 index 7145cbfa92..0000000000 --- a/modules_dart/transform/lib/src/transform/bind_generator/visitor.dart +++ /dev/null @@ -1,30 +0,0 @@ -library angular2.transform.bind_generator.visitor; - -import 'package:analyzer/analyzer.dart'; -import 'package:angular2/src/transform/common/logging.dart'; - -/// Visitor responsible for crawling the "annotations" value in a -/// `registerType` call and pulling out the properties of any "bind" -/// values found. -class ExtractNamedExpressionVisitor extends Object - with RecursiveAstVisitor { - final ConstantEvaluator _evaluator = new ConstantEvaluator(); - final List bindConfig = []; - final String nameToExtract; - - ExtractNamedExpressionVisitor(this.nameToExtract); - - @override - Object visitNamedExpression(NamedExpression node) { - if ('${node.name.label}' == nameToExtract) { - var evaluated = node.expression.accept(_evaluator); - if (evaluated is List) { - bindConfig.addAll(evaluated); - } else { - logger.error('`$nameToExtract` currently only supports List values'); - } - return null; - } - return super.visitNamedExpression(node); - } -} diff --git a/modules_dart/transform/lib/src/transform/template_compiler/reflection/processor.dart b/modules_dart/transform/lib/src/transform/template_compiler/reflection/processor.dart index e1ba2f4d7e..48c8bcaceb 100644 --- a/modules_dart/transform/lib/src/transform/template_compiler/reflection/processor.dart +++ b/modules_dart/transform/lib/src/transform/template_compiler/reflection/processor.dart @@ -15,8 +15,15 @@ class Processor implements CodegenModel { final Set methodNames = new Set(); void process(CompileDirectiveMetadata meta) { - meta.outputs.keys.forEach((eventName) { - getterNames.add(new ReflectiveAccessor(eventName)); - }); + if (meta.outputs != null) { + meta.outputs.keys.forEach((eventName) { + getterNames.add(new ReflectiveAccessor(eventName)); + }); + } + if (meta.inputs != null) { + meta.inputs.keys.forEach((inputName) { + setterNames.add(new ReflectiveAccessor(inputName)); + }); + } } } diff --git a/modules_dart/transform/test/transform/bind_generator/all_tests.dart b/modules_dart/transform/test/transform/bind_generator/all_tests.dart index a098401a70..ce4166c0ed 100644 --- a/modules_dart/transform/test/transform/bind_generator/all_tests.dart +++ b/modules_dart/transform/test/transform/bind_generator/all_tests.dart @@ -14,28 +14,6 @@ main() => allTests(); void allTests() { var reader = new TestAssetReader(); - it('should generate a setter for an `inputs` property in an annotation.', - () async { - var inputPath = 'basic_bind_files/bar.ng_deps.dart'; - var expected = _readFile('basic_bind_files/expected/bar.ng_deps.dart'); - - var output = formatter - .format(await createNgSettersAndGetters(reader, _assetId(inputPath))); - expect(output).toEqual(expected); - }); - - it( - 'should generate a single setter when multiple annotations bind to the ' - 'same `inputs` property.', () async { - var inputPath = 'duplicate_bind_name_files/soup.ng_deps.dart'; - var expected = - _readFile('duplicate_bind_name_files/expected/soup.ng_deps.dart'); - - var output = formatter - .format(await createNgSettersAndGetters(reader, _assetId(inputPath))); - expect(output).toEqual(expected); - }); - it('should generate setters for queries defined in the class annotation.', () async { var inputPath = 'queries_class_annotation_files/bar.ng_deps.dart'; diff --git a/modules_dart/transform/test/transform/template_compiler/all_tests.dart b/modules_dart/transform/test/transform/template_compiler/all_tests.dart index 30a71fa88d..8650f04197 100644 --- a/modules_dart/transform/test/transform/template_compiler/all_tests.dart +++ b/modules_dart/transform/test/transform/template_compiler/all_tests.dart @@ -159,7 +159,7 @@ void noChangeDetectorTests() { _formatThenExpectEquals(output, expected); }); - it('should generate getters for Component#events.', () async { + it('should generate getters for Component#outputs.', () async { var inputPath = 'template_compiler/event_files/hello.ng_deps.dart'; var expected = readFile('template_compiler/event_files/expected/hello.ng_deps.dart'); @@ -169,7 +169,7 @@ void noChangeDetectorTests() { _formatThenExpectEquals(output, expected); }); - it('should generate getters for Directive#events.', () async { + it('should generate getters for Directive#outputs.', () async { var inputPath = 'template_compiler/directive_event_files/hello.ng_deps.dart'; var expected = readFile( @@ -180,6 +180,39 @@ void noChangeDetectorTests() { _formatThenExpectEquals(output, expected); }); + it('should generate setters for Component#inputs.', () async { + var inputPath = 'template_compiler/component_inputs_files/bar.ng_deps.dart'; + var expected = readFile( + 'template_compiler/component_inputs_files/expected/bar.ng_deps.dart'); + var output = await process(new AssetId('a', inputPath)); + _formatThenExpectEquals(output, expected); + output = await process(new AssetId('a', inputPath)); + _formatThenExpectEquals(output, expected); + }); + + it('should generate setters for Directive#inputs.', () async { + var inputPath = 'template_compiler/directive_inputs_files/bar.ng_deps.dart'; + var expected = readFile( + 'template_compiler/directive_inputs_files/expected/bar.ng_deps.dart'); + var output = await process(new AssetId('a', inputPath)); + _formatThenExpectEquals(output, expected); + output = await process(new AssetId('a', inputPath)); + _formatThenExpectEquals(output, expected); + }); + + it( + 'should generate a single setter for two `Directive`s ' + 'with the same inputs.', () async { + var inputPath = + 'template_compiler/duplicate_input_name_files/soup.ng_deps.dart'; + var expected = readFile( + 'template_compiler/duplicate_input_name_files/expected/soup.ng_deps.dart'); + var output = await process(new AssetId('a', inputPath)); + _formatThenExpectEquals(output, expected); + output = await process(new AssetId('a', inputPath)); + _formatThenExpectEquals(output, expected); + }); + // TODO(kegluenq): Before committing, should this test be removed or just // modified to check something different, maybe the created template code? xit('should generate all expected getters, setters, & methods.', () async { diff --git a/modules_dart/transform/test/transform/template_compiler/component_inputs_files/bar.ng_deps.dart b/modules_dart/transform/test/transform/template_compiler/component_inputs_files/bar.ng_deps.dart new file mode 100644 index 0000000000..299ef847b9 --- /dev/null +++ b/modules_dart/transform/test/transform/template_compiler/component_inputs_files/bar.ng_deps.dart @@ -0,0 +1,18 @@ +library bar.ng_deps.dart; + +import 'bar.dart'; +import 'package:angular2/src/core/metadata.dart'; + +var _visited = false; +void initReflector(reflector) { + if (_visited) return; + _visited = true; + reflector + ..registerType( + ToolTip, + new ReflectionInfo(const [ + const Component( + selector: '[tool-tip]', inputs: const ['text: tool-tip']), + const View(template: '
Tooltip
') + ], const [], () => new ToolTip())); +} diff --git a/modules_dart/transform/test/transform/template_compiler/component_inputs_files/bar.ng_meta.json b/modules_dart/transform/test/transform/template_compiler/component_inputs_files/bar.ng_meta.json new file mode 100644 index 0000000000..55f8e76cef --- /dev/null +++ b/modules_dart/transform/test/transform/template_compiler/component_inputs_files/bar.ng_meta.json @@ -0,0 +1,32 @@ +{ + "ToolTip": + { + "kind": "type", + "value": { + "isComponent": true, + "dynamicLoadable": true, + "selector":"[tool-tip]", + "exportAs": null, + "type": { + "id": 1, + "name": "ToolTip", + "moduleUrl": "asset:template_compiler/lib/basic_inputs_files/bar.dart" + }, + "changeDetection": 5, + "inputs": {"text": "tool-tip"}, + "outputs": {}, + "hostListeners": {}, + "hostProperties": {}, + "hostAttributes": {}, + "lifecycleHooks": [], + "template": { + "encapsulation": 0, + "template": "
Tooltip
", + "templateUrl": null, + "styles": null, + "styleUrls": null, + "ngContentSelectors": null + } + } + } +} diff --git a/modules_dart/transform/test/transform/template_compiler/component_inputs_files/expected/bar.ng_deps.dart b/modules_dart/transform/test/transform/template_compiler/component_inputs_files/expected/bar.ng_deps.dart new file mode 100644 index 0000000000..dbdb448922 --- /dev/null +++ b/modules_dart/transform/test/transform/template_compiler/component_inputs_files/expected/bar.ng_deps.dart @@ -0,0 +1,22 @@ +library bar.ng_deps.dart; + +import 'bar.template.dart' as _templates; + +import 'bar.dart'; +import 'package:angular2/src/core/metadata.dart'; + +var _visited = false; +void initReflector(reflector) { + if (_visited) return; + _visited = true; + reflector + ..registerType( + ToolTip, + new ReflectionInfo(const [ + const Component( + selector: '[tool-tip]', inputs: const ['text: tool-tip']), + const View(template: '
Tooltip
'), + _templates.HostToolTipTemplate + ], const [], () => new ToolTip())) + ..registerSetters({'text': (o, v) => o.text = v}); +} diff --git a/modules_dart/transform/test/transform/bind_generator/basic_bind_files/bar.ng_deps.dart b/modules_dart/transform/test/transform/template_compiler/directive_inputs_files/bar.ng_deps.dart similarity index 100% rename from modules_dart/transform/test/transform/bind_generator/basic_bind_files/bar.ng_deps.dart rename to modules_dart/transform/test/transform/template_compiler/directive_inputs_files/bar.ng_deps.dart diff --git a/modules_dart/transform/test/transform/template_compiler/directive_inputs_files/bar.ng_meta.json b/modules_dart/transform/test/transform/template_compiler/directive_inputs_files/bar.ng_meta.json new file mode 100644 index 0000000000..1c32bf5c45 --- /dev/null +++ b/modules_dart/transform/test/transform/template_compiler/directive_inputs_files/bar.ng_meta.json @@ -0,0 +1,25 @@ +{ + "ToolTip": + { + "kind": "type", + "value": { + "isComponent": false, + "dynamicLoadable": true, + "selector":"[tool-tip]", + "exportAs": null, + "type": { + "id": 1, + "name": "ToolTip", + "moduleUrl": "asset:template_compiler/lib/basic_inputs_files/bar.dart" + }, + "changeDetection": 5, + "inputs": {"text": "tool-tip"}, + "outputs": {}, + "hostListeners": {}, + "hostProperties": {}, + "hostAttributes": {}, + "lifecycleHooks": [], + "template": null + } + } +} diff --git a/modules_dart/transform/test/transform/bind_generator/basic_bind_files/expected/bar.ng_deps.dart b/modules_dart/transform/test/transform/template_compiler/directive_inputs_files/expected/bar.ng_deps.dart similarity index 100% rename from modules_dart/transform/test/transform/bind_generator/basic_bind_files/expected/bar.ng_deps.dart rename to modules_dart/transform/test/transform/template_compiler/directive_inputs_files/expected/bar.ng_deps.dart diff --git a/modules_dart/transform/test/transform/bind_generator/duplicate_bind_name_files/expected/soup.ng_deps.dart b/modules_dart/transform/test/transform/template_compiler/duplicate_input_name_files/expected/soup.ng_deps.dart similarity index 55% rename from modules_dart/transform/test/transform/bind_generator/duplicate_bind_name_files/expected/soup.ng_deps.dart rename to modules_dart/transform/test/transform/template_compiler/duplicate_input_name_files/expected/soup.ng_deps.dart index 0b60d2d027..172a118d28 100644 --- a/modules_dart/transform/test/transform/bind_generator/duplicate_bind_name_files/expected/soup.ng_deps.dart +++ b/modules_dart/transform/test/transform/template_compiler/duplicate_input_name_files/expected/soup.ng_deps.dart @@ -9,16 +9,17 @@ void initReflector(reflector) { _visited = true; reflector ..registerType( - SoupComponent, + SoupDirective, new ReflectionInfo(const [ - const Component( - componentServices: const [SaladComponent], + const Directive( + selector: 'soup', + componentServices: const [SaladDirective], inputs: const ['menu']) - ], const [], () => new SoupComponent())) + ], const [], () => new SoupDirective())) ..registerType( - SaladComponent, + SaladDirective, new ReflectionInfo(const [ - const Component(inputs: const ['menu']) - ], const [], () => new SaladComponent())) + const Directive(selector: 'salad', inputs: const ['menu']) + ], const [], () => new SaladDirective())) ..registerSetters({'menu': (o, v) => o.menu = v}); } diff --git a/modules_dart/transform/test/transform/bind_generator/duplicate_bind_name_files/soup.ng_deps.dart b/modules_dart/transform/test/transform/template_compiler/duplicate_input_name_files/soup.ng_deps.dart similarity index 52% rename from modules_dart/transform/test/transform/bind_generator/duplicate_bind_name_files/soup.ng_deps.dart rename to modules_dart/transform/test/transform/template_compiler/duplicate_input_name_files/soup.ng_deps.dart index 9a406f6a15..221bbceef4 100644 --- a/modules_dart/transform/test/transform/bind_generator/duplicate_bind_name_files/soup.ng_deps.dart +++ b/modules_dart/transform/test/transform/template_compiler/duplicate_input_name_files/soup.ng_deps.dart @@ -9,15 +9,16 @@ void initReflector(reflector) { _visited = true; reflector ..registerType( - SoupComponent, + SoupDirective, new ReflectionInfo(const [ - const Component( - componentServices: const [SaladComponent], + const Directive( + selector: 'soup', + componentServices: const [SaladDirective], inputs: const ['menu']) - ], const [], () => new SoupComponent())) + ], const [], () => new SoupDirective())) ..registerType( - SaladComponent, + SaladDirective, new ReflectionInfo(const [ - const Component(inputs: const ['menu']) - ], const [], () => new SaladComponent())); + const Directive(selector: 'salad', inputs: const ['menu']) + ], const [], () => new SaladDirective())); } diff --git a/modules_dart/transform/test/transform/template_compiler/duplicate_input_name_files/soup.ng_meta.json b/modules_dart/transform/test/transform/template_compiler/duplicate_input_name_files/soup.ng_meta.json new file mode 100644 index 0000000000..37e4b8116e --- /dev/null +++ b/modules_dart/transform/test/transform/template_compiler/duplicate_input_name_files/soup.ng_meta.json @@ -0,0 +1,48 @@ +{ + "SoupDirective": + { + "kind": "type", + "value": { + "isComponent": false, + "dynamicLoadable": true, + "selector":"soup", + "exportAs": null, + "type": { + "id": 1, + "name": "SoupDirective", + "moduleUrl": "asset:template_compiler/test/duplicate_input_name_files/soup.dart" + }, + "changeDetection": 5, + "inputs": {"menu": "menu"}, + "outputs": {}, + "hostListeners": {}, + "hostProperties": {}, + "hostAttributes": {}, + "lifecycleHooks": [], + "template": null + } + }, + "SaladDirective": + { + "kind": "type", + "value": { + "isComponent": false, + "dynamicLoadable": true, + "selector":"salad", + "exportAs": null, + "type": { + "id": 1, + "name": "SaladDirective", + "moduleUrl": "asset:template_compiler/test/duplicate_input_name_files/soup.dart" + }, + "changeDetection": 5, + "inputs": {"menu": "menu"}, + "outputs": {}, + "hostListeners": {}, + "hostProperties": {}, + "hostAttributes": {}, + "lifecycleHooks": [], + "template": null + } + } +}