fix(transformer): Add getters for events
.
closes https://github.com/angular/angular/issues/2725
This commit is contained in:
@ -9,22 +9,32 @@ import 'package:barback/barback.dart';
|
||||
|
||||
import 'visitor.dart';
|
||||
|
||||
Future<String> createNgSetters(AssetReader reader, AssetId entryPoint) async {
|
||||
Future<String> createNgSettersAndGetters(
|
||||
AssetReader reader, AssetId entryPoint) async {
|
||||
NgDeps ngDeps = await NgDeps.parse(reader, entryPoint);
|
||||
|
||||
String code = ngDeps.code;
|
||||
var setters = _generateSetters(_createBindMap(ngDeps));
|
||||
var setters = _generateSetters(_createPropertiesMap(ngDeps));
|
||||
var getters = _generateGetters(_createEventsMap(ngDeps));
|
||||
|
||||
if (setters.length == 0) return code;
|
||||
if (setters.isEmpty && getters.isEmpty) return code;
|
||||
var out = new StringBuffer();
|
||||
var codeInjectIdx = ngDeps.registeredTypes.last.registerMethod.end;
|
||||
return '${code.substring(0, codeInjectIdx)}'
|
||||
'..registerSetters({${setters.join(', ')}})'
|
||||
'${code.substring(codeInjectIdx)}';
|
||||
out.write(code.substring(0, codeInjectIdx));
|
||||
if (setters.isNotEmpty) {
|
||||
out.write('..registerSetters({${setters.join(', ')}})');
|
||||
}
|
||||
if (getters.isNotEmpty) {
|
||||
out.write('..registerGetters({${getters.join(', ')}})');
|
||||
}
|
||||
out.write(code.substring(codeInjectIdx));
|
||||
return '$out';
|
||||
}
|
||||
|
||||
// TODO(kegluneq): De-dupe from template_compiler/generator.dart.
|
||||
|
||||
/// Consumes the map generated by {@link _createBindMap} to codegen setters.
|
||||
/// Consumes the map generated by {@link _createPropertiesMap} to codegen
|
||||
/// setters.
|
||||
List<String> _generateSetters(Map<String, String> bindMap) {
|
||||
var setters = [];
|
||||
// TODO(kegluneq): Include types for receivers. See #886.
|
||||
@ -43,8 +53,8 @@ List<String> _generateSetters(Map<String, String> bindMap) {
|
||||
/// Collapses all `properties` in {@link ngDeps} into a map where the keys are
|
||||
/// the bind properties and the values are either the one and only type
|
||||
/// binding to that property or the empty string.
|
||||
Map<String, String> _createBindMap(NgDeps ngDeps) {
|
||||
var visitor = new ExtractSettersVisitor();
|
||||
Map<String, String> _createPropertiesMap(NgDeps ngDeps) {
|
||||
var visitor = new ExtractNamedExpressionVisitor('properties');
|
||||
var bindMap = {};
|
||||
ngDeps.registeredTypes.forEach((RegisteredType t) {
|
||||
visitor.bindConfig.clear();
|
||||
@ -68,3 +78,37 @@ Map<String, String> _createBindMap(NgDeps ngDeps) {
|
||||
});
|
||||
return bindMap;
|
||||
}
|
||||
|
||||
/// Consumes the map generated by {@link _createEventsMap} to codegen getters.
|
||||
List<String> _generateGetters(Map<String, String> bindMap) {
|
||||
var getters = [];
|
||||
// TODO(kegluneq): Include types for receivers. See #886.
|
||||
bindMap.forEach((getterName, eventName) {
|
||||
if (!prop.isValid(eventName)) {
|
||||
// TODO(kegluenq): Eagerly throw here once #1295 is addressed.
|
||||
getters.add(prop.lazyInvalidGetter(eventName));
|
||||
} else {
|
||||
getters.add(''' '${prop.sanitize(eventName)}': (o) => o.$getterName''');
|
||||
}
|
||||
});
|
||||
return getters;
|
||||
}
|
||||
|
||||
/// Collapses all `events` in {@link ngDeps} into a map where the keys are
|
||||
/// the property names for the event emitters and the values are the event name.
|
||||
Map<String, String> _createEventsMap(NgDeps ngDeps) {
|
||||
var visitor = new ExtractNamedExpressionVisitor('events');
|
||||
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 `events` is specified.
|
||||
var parts = config.split(':').map((p) => p.trim()).toList();
|
||||
bindMap[parts[0]] = parts.length > 1 ? parts[1] : parts[0];
|
||||
});
|
||||
});
|
||||
return bindMap;
|
||||
}
|
||||
|
||||
|
@ -31,11 +31,11 @@ class BindGenerator extends Transformer {
|
||||
try {
|
||||
var id = transform.primaryInput.id;
|
||||
var reader = new AssetReader.fromTransform(transform);
|
||||
var transformedCode = await createNgSetters(reader, id);
|
||||
var transformedCode = await createNgSettersAndGetters(reader, id);
|
||||
transform.addOutput(new Asset.fromString(
|
||||
id, formatter.format(transformedCode, uri: id.path)));
|
||||
} catch (ex, stackTrace) {
|
||||
log.logger.error('Creating ng setters failed.\n'
|
||||
log.logger.error('Creating ng setters/getters failed.\n'
|
||||
'Exception: $ex\n'
|
||||
'Stack Trace: $stackTrace');
|
||||
}
|
||||
|
@ -6,18 +6,22 @@ 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 ExtractSettersVisitor extends Object with RecursiveAstVisitor<Object> {
|
||||
class ExtractNamedExpressionVisitor extends Object with
|
||||
RecursiveAstVisitor<Object> {
|
||||
final ConstantEvaluator _evaluator = new ConstantEvaluator();
|
||||
final List<String> bindConfig = [];
|
||||
final String nameToExtract;
|
||||
|
||||
ExtractNamedExpressionVisitor(this.nameToExtract);
|
||||
|
||||
@override
|
||||
Object visitNamedExpression(NamedExpression node) {
|
||||
if ('${node.name.label}' == 'properties') {
|
||||
if ('${node.name.label}' == nameToExtract) {
|
||||
var evaluated = node.expression.accept(_evaluator);
|
||||
if (evaluated is List) {
|
||||
bindConfig.addAll(evaluated);
|
||||
} else {
|
||||
logger.error('`properties` currently only supports List values');
|
||||
logger.error('`$nameToExtract` currently only supports List values');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
Reference in New Issue
Block a user