Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,70 @@ library angular2.transform.bind_generator.generator;

import 'dart:async';

import 'package:analyzer/analyzer.dart';
import 'package:angular2/src/transform/common/asset_reader.dart';
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<Object> {
final ConstantEvaluator _evaluator = new ConstantEvaluator();
final List<String> queryFields = [];

@override
Object visitNamedExpression(NamedExpression node) {
if ('${node.name.label}' == "queries") {
if (node.expression is! MapLiteral) {
throw new FormatException(
'Expected a map value for "queries", but got ${node.expression}',
node.toSource());
}
MapLiteral queries = node.expression;
queryFields.addAll(queries.entries.map((e) => e.key.accept(_evaluator)));
}
return super.visitNamedExpression(node);
}

Map asMap() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: by convention Dart uses asN to indicate an unmodifiable view of the data in an object, as with the List#asMap method.

return new Map.fromIterable(queryFields, value: (_) => 'Object');
}
}


class _ExtractQueryFieldsFromPropMetadata extends Object
with RecursiveAstVisitor<Object> {
final ConstantEvaluator _evaluator = new ConstantEvaluator();
final List<String> queryFields = [];

@override
Object visitMapLiteralEntry(MapLiteralEntry node) {
if (_hasQueryAnnotation(node.value)) {
queryFields.add(node.key.accept(_evaluator));
}
return super.visitMapLiteralEntry(node);
}

bool _hasQueryAnnotation(list) {
var res = false;
list.elements.forEach((item) {
var n = item.constructorName.toString();
if(n == "ContentChild" || n == "ViewChild" || n == "ContentChildren" || n == "ViewChildren") {
res = true;
}
});

return res;
}

asMap() {
return new Map.fromIterable(queryFields, value: (_) => 'Object');
}
}


Future<String> createNgSettersAndGetters(
AssetReader reader, AssetId entryPoint) async {
NgDeps ngDeps = await NgDeps.parse(reader, entryPoint);
Expand All @@ -17,6 +74,18 @@ Future<String> createNgSettersAndGetters(
var setters = _generateSetters(_createPropertiesMap(ngDeps));
var getters = _generateGetters(_createEventPropertiesList(ngDeps));

ngDeps.registeredTypes.forEach((t) {
final fromAnnotation = new _ExtractQueryFieldsFromAnnotation();
t.annotations.accept(fromAnnotation);

final fromPropMetadata = new _ExtractQueryFieldsFromPropMetadata();
if (t.propMetadata != null) {
t.propMetadata.accept(fromPropMetadata);
}
setters.addAll(_generateSetters(fromAnnotation.asMap()));
setters.addAll(_generateSetters(fromPropMetadata.asMap()));
});

if (setters.isEmpty && getters.isEmpty) return code;
var out = new StringBuffer();
var codeInjectIdx = ngDeps.registeredTypes.last.registerMethod.end;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ class RegisteredType {
/// The annotations registered.
final Expression annotations;

/// The property metadata registered.
final Expression propMetadata;

RenderDirectiveMetadata _directiveMetadata = null;

RegisteredType._(
Expand All @@ -34,15 +37,16 @@ class RegisteredType {
this.reflectionInfoCreate,
this.factoryFn,
this.parameters,
this.annotations);
this.annotations,
this.propMetadata);

/// Creates a {@link RegisteredType} given a {@link MethodInvocation} node representing
/// a call to `registerType`.
factory RegisteredType.fromMethodInvocation(MethodInvocation registerMethod) {
var visitor = new _ParseRegisterTypeVisitor();
registerMethod.accept(visitor);
return new RegisteredType._(visitor.typeName, registerMethod, visitor.info,
visitor.factoryFn, visitor.parameters, visitor.annotations);
visitor.factoryFn, visitor.parameters, visitor.annotations, visitor.propMetadata);
}

RenderDirectiveMetadata get directiveMetadata {
Expand All @@ -68,6 +72,7 @@ class _ParseRegisterTypeVisitor extends Object
Expression factoryFn;
Expression parameters;
Expression annotations;
Expression propMetadata;

@override
Object visitMethodInvocation(MethodInvocation node) {
Expand All @@ -90,6 +95,8 @@ class _ParseRegisterTypeVisitor extends Object
parameters = arg;
} else if (i == 2) {
factoryFn = arg;
} else if (i == 4) {
propMetadata = arg;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,26 @@ void allTests() {
await createNgSettersAndGetters(reader, new AssetId('a', inputPath)));
expect(output).toEqual(expected);
});

it('should generate setters for queries defined in the class annotation.',
() async {
var inputPath = 'bind_generator/queries_class_annotation_files/bar.ng_deps.dart';
var expected = formatter.format(
readFile('bind_generator/queries_class_annotation_files/expected/bar.ng_deps.dart'));

var output = formatter.format(
await createNgSettersAndGetters(reader, new AssetId('a', inputPath)));
expect(output).toEqual(expected);
});

it('should generate setters for queries defined via prop annotations.',
() async {
var inputPath = 'bind_generator/queries_prop_annotations_files/bar.ng_deps.dart';
var expected = formatter.format(
readFile('bind_generator/queries_prop_annotations_files/expected/bar.ng_deps.dart'));

var output = formatter.format(
await createNgSettersAndGetters(reader, new AssetId('a', inputPath)));
expect(output).toEqual(expected);
});
}
Original file line number Diff line number Diff line change
@@ -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 Directive(
selector: '[tool-tip]',
queries: const {'queryField': const ContentChild('child')})
], const [], () => new ToolTip()));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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 Directive(
selector: '[tool-tip]',
queries: const {'queryField': const ContentChild('child')})
], const [], () => new ToolTip()))
..registerSetters({'queryField': (o, v) => o.queryField = v});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
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 Directive(
selector: '[tool-tip]')
], const [], () => new ToolTip(), null, const {'queryField': const [const ContentChild('child')]}));
}
Original file line number Diff line number Diff line change
@@ -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 Directive(
selector: '[tool-tip]')
], const [], () => new ToolTip(), null, const {'queryField': const [const ContentChild('child')]}))
..registerSetters({'queryField': (o, v) => o.queryField = v});
}