fix(dart/transform): Parse directives agnostic of annotation order
Now that we can specify `directives` in either `@View` or `@Component`, we will try to parse from both. Previously, we would trash any `directives` parsed in the first annotation upon encountering the second annotation. This ensures that we maintain that list of `directives` regardless of annotation ordering.
This commit is contained in:
parent
f5159389b3
commit
efddc9069c
|
@ -172,6 +172,7 @@ class _CompileDataCreator {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visitor responsible for processing the `annotations` property of a
|
/// Visitor responsible for processing the `annotations` property of a
|
||||||
/// [RegisterType] object, extracting the `directives` dependencies, and adding
|
/// [RegisterType] object, extracting the `directives` dependencies, and adding
|
||||||
/// their associated [CompileDirectiveMetadata] to the `directives` of a
|
/// their associated [CompileDirectiveMetadata] to the `directives` of a
|
||||||
|
@ -198,8 +199,14 @@ class _DirectiveDependenciesVisitor extends Object
|
||||||
@override
|
@override
|
||||||
Object visitInstanceCreationExpression(InstanceCreationExpression node) {
|
Object visitInstanceCreationExpression(InstanceCreationExpression node) {
|
||||||
if (_isViewAnnotation(node) || _isComponentAnnotation(node)) {
|
if (_isViewAnnotation(node) || _isComponentAnnotation(node)) {
|
||||||
compileData = new NormalizedComponentWithViewDirectives(
|
if (compileData == null) {
|
||||||
null, <CompileDirectiveMetadata>[]);
|
compileData = new NormalizedComponentWithViewDirectives(
|
||||||
|
null, <CompileDirectiveMetadata>[]);
|
||||||
|
} else {
|
||||||
|
// This is set above, after the visitor is finished. If this value is
|
||||||
|
// non-null it indicates that we forgot to call `reset()`.
|
||||||
|
assert(compileData.component == null);
|
||||||
|
}
|
||||||
node.visitChildren(this);
|
node.visitChildren(this);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -212,7 +219,7 @@ class _DirectiveDependenciesVisitor extends Object
|
||||||
if (node.name is! Label || node.name.label is! SimpleIdentifier) {
|
if (node.name is! Label || node.name.label is! SimpleIdentifier) {
|
||||||
logger.error(
|
logger.error(
|
||||||
'Angular 2 currently only supports simple identifiers in directives.'
|
'Angular 2 currently only supports simple identifiers in directives.'
|
||||||
' Source: ${node}');
|
' Source: ${node}');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ('${node.name.label}' == 'directives') {
|
if ('${node.name.label}' == 'directives') {
|
||||||
|
@ -244,7 +251,7 @@ class _DirectiveDependenciesVisitor extends Object
|
||||||
} else {
|
} else {
|
||||||
logger.error(
|
logger.error(
|
||||||
'Angular 2 currently only supports simple and prefixed identifiers '
|
'Angular 2 currently only supports simple and prefixed identifiers '
|
||||||
'as values for "directives". Source: $node');
|
'as values for "directives". Source: $node');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ngMeta.types.containsKey(name)) {
|
if (ngMeta.types.containsKey(name)) {
|
||||||
|
|
|
@ -61,12 +61,23 @@ void changeDetectorTests() {
|
||||||
'template_compiler/directive_aliases_files/hello2.ng_deps.dart';
|
'template_compiler/directive_aliases_files/hello2.ng_deps.dart';
|
||||||
// Except for the directive argument in the View annotation, the generated
|
// Except for the directive argument in the View annotation, the generated
|
||||||
// change detectors are identical.
|
// change detectors are identical.
|
||||||
|
var output1 = (await process(new AssetId('a', input1Path))).templatesCode;
|
||||||
|
var output2 = (await process(new AssetId('a', input2Path))).templatesCode;
|
||||||
|
_formatThenExpectEquals(output1, output2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle `directives` regardless of annotation ordering', () async {
|
||||||
|
// Input 2 is the same as input1, but has the @View annotation listed first.
|
||||||
|
var input1Path = 'template_compiler/annotation_ordering_files/'
|
||||||
|
'component_first.ng_deps.dart';
|
||||||
|
var input2Path = 'template_compiler/annotation_ordering_files/'
|
||||||
|
'view_first.ng_deps.dart';
|
||||||
|
// Except for the type name, the generated change detectors are identical.
|
||||||
var output1 = (await process(new AssetId('a', input1Path)))
|
var output1 = (await process(new AssetId('a', input1Path)))
|
||||||
.ngDepsCode
|
.templatesCode
|
||||||
.replaceFirst(
|
.replaceAll('ComponentFirst', 'ViewFirst')
|
||||||
'directives: const [alias1]', 'directives: const [GoodbyeCmp]')
|
.replaceAll('component_first', 'view_first');
|
||||||
.replaceFirst('hello1', 'hello2');
|
var output2 = (await process(new AssetId('a', input2Path))).templatesCode;
|
||||||
var output2 = (await process(new AssetId('a', input2Path))).ngDepsCode;
|
|
||||||
_formatThenExpectEquals(output1, output2);
|
_formatThenExpectEquals(output1, output2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
library test.src.transform.template_compiler.annotation_ordering_files.component_first.ng_deps.dart;
|
||||||
|
|
||||||
|
import 'component_first.dart';
|
||||||
|
import 'package:angular2/angular2.dart'
|
||||||
|
show Component, Directive, View, NgElement;
|
||||||
|
import 'package:angular2/src/directives/ng_for.dart';
|
||||||
|
export 'component_first.dart';
|
||||||
|
|
||||||
|
var _visited = false;
|
||||||
|
void initReflector(reflector) {
|
||||||
|
if (_visited) return;
|
||||||
|
_visited = true;
|
||||||
|
reflector
|
||||||
|
..registerType(
|
||||||
|
ComponentFirst,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'hello-app'),
|
||||||
|
const View(
|
||||||
|
template: '<li *ng-for="#thing of things"><div>test</div></li>',
|
||||||
|
directives: const [NgFor])
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new ComponentFirst()));
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"ComponentFirst":
|
||||||
|
{
|
||||||
|
"kind": "type",
|
||||||
|
"value": {
|
||||||
|
"isComponent": true,
|
||||||
|
"dynamicLoadable": true,
|
||||||
|
"selector":"hello-app",
|
||||||
|
"exportAs": null,
|
||||||
|
"type": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "ComponentFirst",
|
||||||
|
"moduleUrl": "asset:angular2/test/transform/template_compiler/ng_for_files/hello.dart"
|
||||||
|
},
|
||||||
|
"changeDetection": 5,
|
||||||
|
"inputs": {},
|
||||||
|
"outputs": {},
|
||||||
|
"hostListeners": {},
|
||||||
|
"hostProperties": {},
|
||||||
|
"hostAttributes": {},
|
||||||
|
"lifecycleHooks": [],
|
||||||
|
"template": {
|
||||||
|
"encapsulation": 0,
|
||||||
|
"template": "<li *ng-for=\"#thing of things\"><div>test</div></li>",
|
||||||
|
"templateUrl": null,
|
||||||
|
"styles": null,
|
||||||
|
"styleUrls": null,
|
||||||
|
"ngContentSelectors": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
library test.src.transform.template_compiler.annotation_ordering_files.view_first.ng_deps.dart;
|
||||||
|
|
||||||
|
import 'view_first.dart';
|
||||||
|
import 'package:angular2/angular2.dart'
|
||||||
|
show Component, Directive, View, NgElement;
|
||||||
|
import 'package:angular2/src/directives/ng_for.dart';
|
||||||
|
export 'view_first.dart';
|
||||||
|
|
||||||
|
var _visited = false;
|
||||||
|
void initReflector(reflector) {
|
||||||
|
if (_visited) return;
|
||||||
|
_visited = true;
|
||||||
|
reflector
|
||||||
|
..registerType(
|
||||||
|
ViewFirst,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const View(
|
||||||
|
template: '<li *ng-for="#thing of things"><div>test</div></li>',
|
||||||
|
directives: const [NgFor]),
|
||||||
|
const Component(selector: 'hello-app')
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new ViewFirst()));
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"ViewFirst":
|
||||||
|
{
|
||||||
|
"kind": "type",
|
||||||
|
"value": {
|
||||||
|
"isComponent": true,
|
||||||
|
"dynamicLoadable": true,
|
||||||
|
"selector":"hello-app",
|
||||||
|
"exportAs": null,
|
||||||
|
"type": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "ViewFirst",
|
||||||
|
"moduleUrl": "asset:angular2/test/transform/template_compiler/ng_for_files/hello.dart"
|
||||||
|
},
|
||||||
|
"changeDetection": 5,
|
||||||
|
"inputs": {},
|
||||||
|
"outputs": {},
|
||||||
|
"hostListeners": {},
|
||||||
|
"hostProperties": {},
|
||||||
|
"hostAttributes": {},
|
||||||
|
"lifecycleHooks": [],
|
||||||
|
"template": {
|
||||||
|
"encapsulation": 0,
|
||||||
|
"template": "<li *ng-for=\"#thing of things\"><div>test</div></li>",
|
||||||
|
"templateUrl": null,
|
||||||
|
"styles": null,
|
||||||
|
"styleUrls": null,
|
||||||
|
"ngContentSelectors": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue