feat(transformers): directive aliases in Dart transformers (fix #1747)
This commit is contained in:
@@ -6,6 +6,9 @@ const REFLECTOR_VAR_NAME = 'reflector';
|
||||
const TRANSFORM_DYNAMIC_MODE = 'transform_dynamic';
|
||||
const DEPS_EXTENSION = '.ng_deps.dart';
|
||||
const META_EXTENSION = '.ng_meta.json';
|
||||
// TODO(sigmund): consider merging into .ng_meta by generating local metadata
|
||||
// upfront (rather than extracting it from ng_deps).
|
||||
const ALIAS_EXTENSION = '.aliases.json';
|
||||
const REFLECTION_CAPABILITIES_NAME = 'ReflectionCapabilities';
|
||||
const REGISTER_TYPE_METHOD_NAME = 'registerType';
|
||||
const REGISTER_GETTERS_METHOD_NAME = 'registerGetters';
|
||||
@@ -20,6 +23,10 @@ String toMetaExtension(String uri) =>
|
||||
String toDepsExtension(String uri) =>
|
||||
_toExtension(uri, const [META_EXTENSION, '.dart'], DEPS_EXTENSION);
|
||||
|
||||
/// Returns `uri` with its extension updated to [ALIAS_EXTENSION].
|
||||
String toAliasExtension(String uri) =>
|
||||
_toExtension(uri, const [DEPS_EXTENSION, '.dart'], ALIAS_EXTENSION);
|
||||
|
||||
/// Returns `uri` with its extension updated to `toExtension` if its
|
||||
/// extension is currently in `fromExtension`.
|
||||
String _toExtension(
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
library angular2.transform.common.ng_meta;
|
||||
|
||||
import 'package:angular2/src/render/api.dart';
|
||||
import 'package:angular2/src/render/dom/convert.dart';
|
||||
import 'logging.dart';
|
||||
|
||||
/// Metadata about directives and directive aliases.
|
||||
///
|
||||
/// [NgMeta] is used in three stages of the transformation process. First we
|
||||
/// store directive aliases exported from a single file in an [NgMeta] instance.
|
||||
/// Later we use another [NgMeta] instance to store more information about a
|
||||
/// single file, including both directive aliases and directives extracted from
|
||||
/// the corresponding `.ng_deps.dart` file. Further down the compilation
|
||||
/// process, the template compiler needs to reason about the namespace of import
|
||||
/// prefixes, so it will combine multple [NgMeta] instances together if they
|
||||
/// were imported into a file with the same prefix.
|
||||
///
|
||||
/// Instances of this class are serialized into `.aliases.json` and
|
||||
/// `.ng_meta.json` files as intermediate assets to make the compilation process
|
||||
/// easier.
|
||||
class NgMeta {
|
||||
/// Directive metadata for each type annotated as a directive.
|
||||
final Map<String, DirectiveMetadata> types;
|
||||
|
||||
/// List of other types and names associated with a given name.
|
||||
final Map<String, List<String>> aliases;
|
||||
|
||||
NgMeta(this.types, this.aliases);
|
||||
|
||||
NgMeta.empty() : this({}, {});
|
||||
|
||||
bool get isEmpty => types.isEmpty && aliases.isEmpty;
|
||||
|
||||
/// Parse from the serialized form produced by [toJson].
|
||||
factory NgMeta.fromJson(Map json) {
|
||||
var types = {};
|
||||
var aliases = {};
|
||||
for (var key in json.keys) {
|
||||
var entry = json[key];
|
||||
if (entry['kind'] == 'type') {
|
||||
types[key] = directiveMetadataFromMap(entry['value']);
|
||||
} else if (entry['kind'] == 'alias') {
|
||||
aliases[key] = entry['value'];
|
||||
}
|
||||
}
|
||||
return new NgMeta(types, aliases);
|
||||
}
|
||||
|
||||
/// Serialized representation of this instance.
|
||||
Map toJson() {
|
||||
var result = {};
|
||||
types.forEach((k, v) {
|
||||
result[k] = {'kind': 'type', 'value': directiveMetadataToMap(v)};
|
||||
});
|
||||
|
||||
aliases.forEach((k, v) {
|
||||
result[k] = {'kind': 'alias', 'value': v};
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Merge into this instance all information from [other].
|
||||
void addAll(NgMeta other) {
|
||||
types.addAll(other.types);
|
||||
aliases.addAll(other.aliases);
|
||||
}
|
||||
|
||||
/// Returns the metadata for every type associated with the given [alias].
|
||||
List<DirectiveMetadata> flatten(String alias) {
|
||||
var result = [];
|
||||
var seen = new Set();
|
||||
helper(name) {
|
||||
if (!seen.add(name)) {
|
||||
logger.warning('Circular alias dependency for "$name".');
|
||||
return;
|
||||
}
|
||||
if (types.containsKey(name)) {
|
||||
result.add(types[name]);
|
||||
} else if (aliases.containsKey(name)) {
|
||||
aliases[name].forEach(helper);
|
||||
} else {
|
||||
logger.warning('Unknown alias: "$name".');
|
||||
}
|
||||
}
|
||||
helper(alias);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user