feat(dart/transform): Fix handling of Dart keywords
Use `package:analyzer`'s list of Dart keywords to ensure we are properly reporting usages of Dart keywords as runtime errors.
This commit is contained in:
parent
2cab7c79c3
commit
f6e9d1f857
|
@ -4,6 +4,7 @@ import 'dart:async';
|
|||
|
||||
import 'package:angular2/src/transform/common/asset_reader.dart';
|
||||
import 'package:angular2/src/transform/common/parser.dart';
|
||||
import 'package:angular2/src/transform/common/property_utils.dart' as prop;
|
||||
import 'package:barback/barback.dart';
|
||||
|
||||
import 'visitor.dart';
|
||||
|
@ -22,12 +23,20 @@ Future<String> createNgSetters(AssetReader reader, AssetId entryPoint) async {
|
|||
'${code.substring(codeInjectIdx)}';
|
||||
}
|
||||
|
||||
// TODO(kegluneq): De-dupe from template_compiler/generator.dart.
|
||||
|
||||
/// Consumes the map generated by [_createBindMap] to codegen setters.
|
||||
List<String> _generateSetters(Map<String, String> bindMap) {
|
||||
var setters = [];
|
||||
// TODO(kegluneq): Include types for receivers. See #886.
|
||||
bindMap.forEach((prop, type) {
|
||||
setters.add(''''$prop': (o, String v) => o.$prop = v''');
|
||||
bindMap.forEach((setterName, type) {
|
||||
if (!prop.isValid(setterName)) {
|
||||
// TODO(kegluenq): Eagerly throw here once #1295 is addressed.
|
||||
setters.add(prop.lazyInvalidSetter(setterName));
|
||||
} else {
|
||||
setters.add(''' '${prop.sanitize(setterName)}': '''
|
||||
''' (o, v) => o.$setterName = v ''');
|
||||
}
|
||||
});
|
||||
return setters;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
library angular2.transform.common.property_utils;
|
||||
|
||||
import 'package:analyzer/src/generated/scanner.dart' show Keyword;
|
||||
|
||||
/// Whether `name` is a valid property name.
|
||||
bool isValid(String name) => !Keyword.keywords.containsKey(name);
|
||||
|
||||
/// Prepares [name] to be emitted inside a string.
|
||||
String sanitize(String name) => name.replaceAll('\$', '\\\$');
|
||||
|
||||
/// Get a string usable as a lazy invalid setter, that is, one which will
|
||||
/// `throw` immediately upon use.
|
||||
String lazyInvalidSetter(String setterName) {
|
||||
var sName = sanitize(setterName);
|
||||
return ''' '$sName': (o, v) => '''
|
||||
''' throw 'Invalid setter name "$sName" is a Dart keyword.' ''';
|
||||
}
|
||||
|
||||
/// Get a string usable as a lazy invalid getter, that is, one which will
|
||||
/// `throw` immediately upon use.
|
||||
String lazyInvalidGetter(String getterName) {
|
||||
var sName = sanitize(getterName);
|
||||
return ''' '$sName': (o) => '''
|
||||
''' throw 'Invalid getter name "$sName" is a Dart keyword.' ''';
|
||||
}
|
||||
|
||||
/// Get a string usable as a lazy invalid method, that is, one which will
|
||||
/// `throw` immediately upon use.
|
||||
String lazyInvalidMethod(String methodName) {
|
||||
var sName = sanitize(methodName);
|
||||
return ''' '$sName': (o, args) => '''
|
||||
''' throw 'Invalid method name "$sName" is a Dart keyword.' ''';
|
||||
}
|
|
@ -200,6 +200,7 @@ class _Tester {
|
|||
return metaName == 'Component' ||
|
||||
metaName == 'Decorator' ||
|
||||
metaName == 'Injectable' ||
|
||||
metaName == 'View';
|
||||
metaName == 'View' ||
|
||||
metaName == 'Viewport';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import 'package:angular2/src/transform/common/asset_reader.dart';
|
|||
import 'package:angular2/src/transform/common/logging.dart';
|
||||
import 'package:angular2/src/transform/common/names.dart';
|
||||
import 'package:angular2/src/transform/common/parser.dart';
|
||||
import 'package:angular2/src/transform/common/property_utils.dart' as prop;
|
||||
import 'package:barback/barback.dart';
|
||||
import 'package:code_transformers/assets.dart';
|
||||
|
||||
|
@ -63,21 +64,38 @@ Future<String> processTemplates(AssetReader reader, AssetId entryPoint) async {
|
|||
|
||||
Iterable<String> _generateGetters(String typeName, List<String> getterNames) {
|
||||
// TODO(kegluneq): Include `typeName` where possible.
|
||||
return getterNames.map((prop) => '''
|
||||
'$prop': (o) => o.$prop
|
||||
''');
|
||||
return getterNames.map((getterName) {
|
||||
if (!prop.isValid(getterName)) {
|
||||
// TODO(kegluenq): Eagerly throw here once #1295 is addressed.
|
||||
return prop.lazyInvalidGetter(getterName);
|
||||
} else {
|
||||
return ''' '${prop.sanitize(getterName)}': (o) => o.$getterName''';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Iterable<String> _generateSetters(String typeName, List<String> setterName) {
|
||||
return setterName.map((prop) => '''
|
||||
'$prop': (o, v) => o.$prop = v
|
||||
''');
|
||||
return setterName.map((setterName) {
|
||||
if (!prop.isValid(setterName)) {
|
||||
// TODO(kegluenq): Eagerly throw here once #1295 is addressed.
|
||||
return prop.lazyInvalidSetter(setterName);
|
||||
} else {
|
||||
return ''' '${prop.sanitize(setterName)}': '''
|
||||
''' (o, v) => o.$setterName = v ''';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Iterable<String> _generateMethods(String typeName, List<String> methodNames) {
|
||||
return methodNames.map((methodName) => '''
|
||||
'$methodName': (o, List args) => Function.apply(o.$methodName, args)
|
||||
''');
|
||||
return methodNames.map((methodName) {
|
||||
if (!prop.isValid(methodName)) {
|
||||
// TODO(kegluenq): Eagerly throw here once #1295 is addressed.
|
||||
return prop.lazyInvalidMethod(methodName);
|
||||
} else {
|
||||
return ''' '${prop.sanitize(methodName)}': '''
|
||||
'(o, List args) => Function.apply(o.$methodName, args) ';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Extracts `template` and `url` values from `View` annotations, reads
|
||||
|
|
|
@ -16,5 +16,5 @@ void initReflector(reflector) {
|
|||
selector: '[tool-tip]', properties: const {'text': 'tool-tip'})
|
||||
]
|
||||
})
|
||||
..registerSetters({'text': (o, String v) => o.text = v});
|
||||
..registerSetters({'text': (o, v) => o.text = v});
|
||||
}
|
||||
|
|
|
@ -22,5 +22,5 @@ void initReflector(reflector) {
|
|||
'parameters': const [],
|
||||
'annotations': const [const Component(properties: const {'menu': 'menu'})]
|
||||
})
|
||||
..registerSetters({'menu': (o, String v) => o.menu = v});
|
||||
..registerSetters({'menu': (o, v) => o.menu = v});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue