diff --git a/modules_dart/transform/lib/src/transform/common/code/uri.dart b/modules_dart/transform/lib/src/transform/common/code/uri.dart index a477299602..9f7edbd150 100644 --- a/modules_dart/transform/lib/src/transform/common/code/uri.dart +++ b/modules_dart/transform/lib/src/transform/common/code/uri.dart @@ -8,16 +8,17 @@ import 'package:path/path.dart' as path; /// If `fromAbsolute` is specified, `importPath` may be a relative path, /// otherwise it is expected to be absolute. String writeImportUri(String importPath, {String prefix, String fromAbsolute}) { + var urlResolver = const TransformerUrlResolver(); var codegenImportPath; - var resolver = const TransformerUrlResolver(); - var importUri = resolver.toAssetScheme(Uri.parse(importPath)); + var importUri = + toAssetScheme(Uri.parse(urlResolver.resolve(fromAbsolute, importPath))); if (_canPackageImport(importUri) || fromAbsolute == null || fromAbsolute.isEmpty) { codegenImportPath = _toPackageImport(importUri); } else { - var moduleUri = resolver.toAssetScheme(Uri.parse(fromAbsolute)); + var moduleUri = toAssetScheme(Uri.parse(fromAbsolute)); if (_canImportRelative(importUri, from: moduleUri)) { codegenImportPath = path.url.relative(importUri.toString(), from: path.dirname(moduleUri.toString())); diff --git a/modules_dart/transform/lib/src/transform/common/ng_meta.dart b/modules_dart/transform/lib/src/transform/common/ng_meta.dart index ab758db9b2..6af170d01e 100644 --- a/modules_dart/transform/lib/src/transform/common/ng_meta.dart +++ b/modules_dart/transform/lib/src/transform/common/ng_meta.dart @@ -2,74 +2,123 @@ library angular2.transform.common.ng_meta; import 'package:angular2/src/core/compiler/directive_metadata.dart'; import 'logging.dart'; +import 'model/ng_deps_model.pb.dart'; +import 'url_resolver.dart' show isDartCoreUri; -/// Metadata about directives and directive aliases. +/// Metadata about directives, directive aliases, and injectable values. /// -/// [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. +/// [NgMeta] is used in three stages of the transformation process: /// -/// Instances of this class are serialized into `.aliases.json` and -/// `.ng_meta.json` files as intermediate assets to make the compilation process -/// easier. +/// First we store directive aliases and types exported directly (that is, not +/// via an `export` statement) from a single file in an [NgMeta] instance. +/// +/// In the second phase, we perform two actions: +/// 1. Incorporate all the data from [NgMeta] instances created by all +/// files `exported` by the original file, such that all aliases and types +/// visible when importing the original file are stored in its associated +/// [NgMeta] instance. +/// 2. Use the [NgDepsModel] to write Dart code registering all injectable +/// values with the Angular 2 runtime reflection system. +/// +/// Further down the compilation process, the template compiler needs to reason +/// about the namespace of import prefixes, so it will combine multiple [NgMeta] +/// instances together if they were imported into a file with the same prefix. +/// +/// Instances of this class are serialized into `.ng_meta.json` files as +/// intermediate assets to make the compilation process easier. class NgMeta { + static const _ALIAS_VALUE = 'alias'; + static const _KIND_KEY = 'kind'; + static const _NG_DEPS_KEY = 'ngDeps'; + static const _TYPE_VALUE = 'type'; + static const _VALUE_KEY = 'value'; + /// Directive metadata for each type annotated as a directive. final Map types; /// List of other types and names associated with a given name. final Map> aliases; - /// TODO(kegluneq): Once merged with NgDepsModel, use its exports. - final List exports; + // The NgDeps generated from + final NgDepsModel ngDeps; - NgMeta(this.types, this.aliases, this.exports); + NgMeta( + {Map types, + Map> aliases, + this.ngDeps: null}) + : this.types = types != null ? types : {}, + this.aliases = aliases != null ? aliases : {}; - NgMeta.empty() : this({}, {}, []); + NgMeta.empty() : this(); - bool get isEmpty => types.isEmpty && aliases.isEmpty && exports.isEmpty; + // `model` can be an `ImportModel` or `ExportModel`. + static bool _isDartImport(dynamic model) => isDartCoreUri(model.uri); + + bool get isNgDepsEmpty { + if (ngDeps == null) return true; + // If this file imports only dart: libraries and does not define any + // reflectables of its own, it doesn't need a .ng_deps.dart file. + if (ngDeps.reflectables == null || ngDeps.reflectables.isEmpty) { + if ((ngDeps.imports == null || ngDeps.imports.every(_isDartImport)) && + (ngDeps.exports == null || ngDeps.exports.every(_isDartImport))) { + return true; + } + } + return false; + } + + bool get isEmpty => types.isEmpty && aliases.isEmpty && isNgDepsEmpty; /// Parse from the serialized form produced by [toJson]. factory NgMeta.fromJson(Map json) { - var exports = []; - var types = {}; - var aliases = {}; + var ngDeps = null; + final types = {}; + final aliases = {}; for (var key in json.keys) { - if (key == '__exports__') { - exports = json[key]; + if (key == _NG_DEPS_KEY) { + var ngDepsJsonMap = json[key]; + if (ngDepsJsonMap == null) continue; + if (ngDepsJsonMap is! Map) { + logger.warning( + 'Unexpected value $ngDepsJsonMap for key "$key" in NgMeta.'); + continue; + } + ngDeps = new NgDepsModel()..mergeFromJsonMap(ngDepsJsonMap); } else { var entry = json[key]; - if (entry['kind'] == 'type') { - types[key] = CompileDirectiveMetadata.fromJson(entry['value']); - } else if (entry['kind'] == 'alias') { - aliases[key] = entry['value']; + if (entry is! Map) { + logger.warning('Unexpected value $entry for key "$key" in NgMeta.'); + continue; + } + if (entry[_KIND_KEY] == _TYPE_VALUE) { + types[key] = CompileDirectiveMetadata.fromJson(entry[_VALUE_KEY]); + } else if (entry[_KIND_KEY] == _ALIAS_VALUE) { + aliases[key] = entry[_VALUE_KEY]; } } } - return new NgMeta(types, aliases, exports); + return new NgMeta(types: types, aliases: aliases, ngDeps: ngDeps); } /// Serialized representation of this instance. - Map toJson() { + Map toJson({bool withNgDeps: true}) { var result = {}; - result['__exports__'] = exports; + if (withNgDeps) { + result[_NG_DEPS_KEY] = isNgDepsEmpty ? null : ngDeps.writeToJsonMap(); + } types.forEach((k, v) { - result[k] = {'kind': 'type', 'value': v.toJson()}; + result[k] = {_KIND_KEY: _TYPE_VALUE, _VALUE_KEY: v.toJson()}; }); aliases.forEach((k, v) { - result[k] = {'kind': 'alias', 'value': v}; + result[k] = {_KIND_KEY: _ALIAS_VALUE, _VALUE_KEY: v}; }); return result; } /// Merge into this instance all information from [other]. - /// This does not include `exports`. + /// This does not include `ngDeps`. void addAll(NgMeta other) { types.addAll(other.types); aliases.addAll(other.aliases); diff --git a/modules_dart/transform/lib/src/transform/common/options.dart b/modules_dart/transform/lib/src/transform/common/options.dart index 15517cbe3c..88517c1965 100644 --- a/modules_dart/transform/lib/src/transform/common/options.dart +++ b/modules_dart/transform/lib/src/transform/common/options.dart @@ -5,9 +5,6 @@ import 'package:glob/glob.dart'; import 'annotation_matcher.dart'; import 'mirror_mode.dart'; -/// See `optimizationPhases` below for an explanation. -const DEFAULT_OPTIMIZATION_PHASES = 5; - const CUSTOM_ANNOTATIONS_PARAM = 'custom_annotations'; const ENTRY_POINT_PARAM = 'entry_points'; const FORMAT_CODE_PARAM = 'format_code'; @@ -41,15 +38,6 @@ class TransformerOptions { final bool reflectPropertiesAsAttributes; - /// The number of phases to spend optimizing output size. - /// Each additional phase adds time to the transformation but may decrease - /// final output size. There is a limit beyond which this will no longer - /// decrease size, that is, setting this to 20 may not decrease size any - /// more than setting it to 10, but you will still pay an additional - /// penalty in transformation time. - /// The "correct" number of phases varies with the structure of the app. - final int optimizationPhases; - /// Whether to format generated code. /// Code that is only modified will never be formatted because doing so may /// invalidate the source maps generated by `dart2js` and/or other tools. @@ -62,7 +50,6 @@ class TransformerOptions { this.mirrorMode, this.initReflector, this.annotationMatcher, - this.optimizationPhases, {this.reflectPropertiesAsAttributes, this.formatCode}); @@ -71,24 +58,16 @@ class TransformerOptions { MirrorMode mirrorMode: MirrorMode.none, bool initReflector: true, List customAnnotationDescriptors: const [], - int optimizationPhases: DEFAULT_OPTIMIZATION_PHASES, bool inlineViews: true, bool reflectPropertiesAsAttributes: true, bool formatCode: false}) { var annotationMatcher = new AnnotationMatcher() ..addAll(customAnnotationDescriptors); - optimizationPhases = optimizationPhases.isNegative ? 0 : optimizationPhases; var entryPointGlobs = entryPoints != null ? entryPoints.map((path) => new Glob(path)).toList(growable: false) : null; - return new TransformerOptions._internal( - entryPoints, - entryPointGlobs, - modeName, - mirrorMode, - initReflector, - annotationMatcher, - optimizationPhases, + return new TransformerOptions._internal(entryPoints, entryPointGlobs, + modeName, mirrorMode, initReflector, annotationMatcher, reflectPropertiesAsAttributes: reflectPropertiesAsAttributes, formatCode: formatCode); } diff --git a/modules_dart/transform/lib/src/transform/common/options_reader.dart b/modules_dart/transform/lib/src/transform/common/options_reader.dart index 42693106cb..413e6714eb 100644 --- a/modules_dart/transform/lib/src/transform/common/options_reader.dart +++ b/modules_dart/transform/lib/src/transform/common/options_reader.dart @@ -28,14 +28,11 @@ TransformerOptions parseBarbackSettings(BarbackSettings settings) { mirrorMode = MirrorMode.none; break; } - var optimizationPhases = _readInt(config, OPTIMIZATION_PHASES_PARAM, - defaultValue: DEFAULT_OPTIMIZATION_PHASES); return new TransformerOptions(entryPoints, modeName: settings.mode.name, mirrorMode: mirrorMode, initReflector: initReflector, customAnnotationDescriptors: _readCustomAnnotations(config), - optimizationPhases: optimizationPhases, reflectPropertiesAsAttributes: reflectPropertiesAsAttributes, formatCode: formatCode); } @@ -68,18 +65,6 @@ List _readFileList(Map config, String paramName) { return files; } -int _readInt(Map config, String paramName, {int defaultValue: null}) { - if (!config.containsKey(paramName)) return defaultValue; - var value = config[paramName]; - if (value is String) { - value = int.parse(value); - } - if (value is! int) { - throw new ArgumentError.value(value, paramName, 'Expected an integer'); - } - return value; -} - /// Parse the [CUSTOM_ANNOTATIONS_PARAM] options out of the transformer into /// [ClassDescriptor]s. List _readCustomAnnotations(Map config) { diff --git a/modules_dart/transform/lib/src/transform/common/url_resolver.dart b/modules_dart/transform/lib/src/transform/common/url_resolver.dart index 6cb8c11c7b..18556de0a7 100644 --- a/modules_dart/transform/lib/src/transform/common/url_resolver.dart +++ b/modules_dart/transform/lib/src/transform/common/url_resolver.dart @@ -1,57 +1,83 @@ library angular2.transform.template_compiler.url_resolver; -import 'package:angular2/src/core/compiler/url_resolver.dart'; +import 'package:angular2/src/core/services.dart'; +import 'package:barback/barback.dart'; class TransformerUrlResolver implements UrlResolver { const TransformerUrlResolver(); @override String resolve(String baseUrl, String url) { + if (url == null) throw new ArgumentError.notNull('url'); Uri uri = Uri.parse(url); if (!uri.isAbsolute) { + if (baseUrl == null) throw new ArgumentError.notNull('baseUrl'); + if (baseUrl.isEmpty) throw new ArgumentError.value( + '(empty string)', 'baseUrl'); uri = Uri.parse(baseUrl).resolveUri(uri); } return toAssetScheme(uri).toString(); } +} - /// Converts `absoluteUri` to use the 'asset' scheme used in the Angular 2 - /// template compiler. - /// - /// The `scheme` of `absoluteUri` is expected to be either 'package' or - /// 'asset'. - Uri toAssetScheme(Uri absoluteUri) { - if (absoluteUri == null) return null; +String toAssetUri(AssetId assetId) { + if (assetId == null) throw new ArgumentError.notNull('assetId'); + return 'asset:${assetId.package}/${assetId.path}'; +} - if (!absoluteUri.isAbsolute) { - throw new ArgumentError.value( - absoluteUri, 'absoluteUri', 'Value passed must be an absolute uri'); - } - if (absoluteUri.scheme == 'asset') { - if (absoluteUri.pathSegments.length < 3) { - throw new FormatException( - 'An asset: URI must have at least 3 path ' - 'segments, for example ' - 'asset://.', - absoluteUri); - } - return absoluteUri; - } - if (absoluteUri.scheme != 'package') { - throw new ArgumentError.value( - absoluteUri, 'absoluteUri', 'Unsupported URI scheme encountered'); - } +AssetId fromUri(String assetUri) { + if (assetUri == null) throw new ArgumentError.notNull('assetUri'); + if (assetUri.isEmpty) throw new ArgumentError.value( + '(empty string)', 'assetUri'); + var uri = toAssetScheme(Uri.parse(assetUri)); + return new AssetId( + uri.pathSegments.first, uri.pathSegments.skip(1).join('/')); +} - if (absoluteUri.pathSegments.length < 2) { +/// Converts `absoluteUri` to use the 'asset' scheme used in the Angular 2 +/// template compiler. +/// +/// The `scheme` of `absoluteUri` is expected to be either 'package' or +/// 'asset'. +Uri toAssetScheme(Uri absoluteUri) { + if (absoluteUri == null) throw new ArgumentError.notNull('absoluteUri'); + + if (!absoluteUri.isAbsolute) { + throw new ArgumentError.value( + absoluteUri, 'absoluteUri', 'Value passed must be an absolute uri'); + } + if (absoluteUri.scheme == 'asset') { + if (absoluteUri.pathSegments.length < 3) { throw new FormatException( - 'A package: URI must have at least 2 path ' + 'An asset: URI must have at least 3 path ' 'segments, for example ' - 'package:/', + 'asset://.', absoluteUri); } - - var pathSegments = absoluteUri.pathSegments.toList()..insert(1, 'lib'); - return new Uri(scheme: 'asset', pathSegments: pathSegments); + return absoluteUri; } + if (absoluteUri.scheme != 'package') { + throw new FormatException( + 'Unsupported URI scheme "${absoluteUri.scheme}" encountered.', + absoluteUri); + } + + if (absoluteUri.pathSegments.length < 2) { + throw new FormatException( + 'A package: URI must have at least 2 path ' + 'segments, for example ' + 'package:/', + absoluteUri); + } + + var pathSegments = absoluteUri.pathSegments.toList()..insert(1, 'lib'); + return new Uri(scheme: 'asset', pathSegments: pathSegments); +} + +bool isDartCoreUri(String uri) { + if (uri == null) throw new ArgumentError.notNull('uri'); + if (uri.isEmpty) throw new ArgumentError.value('(empty string)', 'uri'); + return uri.startsWith('dart:'); } diff --git a/modules_dart/transform/lib/src/transform/common/xhr_impl.dart b/modules_dart/transform/lib/src/transform/common/xhr_impl.dart index 13f3f2610b..7c9afd64f3 100644 --- a/modules_dart/transform/lib/src/transform/common/xhr_impl.dart +++ b/modules_dart/transform/lib/src/transform/common/xhr_impl.dart @@ -3,20 +3,25 @@ library angular2.transform.template_compiler.xhr_impl; import 'dart:async'; import 'package:angular2/src/core/compiler/xhr.dart' show XHR; import 'package:angular2/src/transform/common/asset_reader.dart'; -import 'package:barback/barback.dart'; +import 'package:angular2/src/transform/common/logging.dart'; +import 'package:angular2/src/transform/common/url_resolver.dart'; +/// Transformer-specific implementation of XHR that is backed by an +/// [AssetReader]. +/// +/// This implementation expects urls using the asset: scheme. +/// See [src/transform/common/url_resolver.dart] for a way to convert package: +/// and relative urls to asset: urls. class XhrImpl implements XHR { final AssetReader _reader; XhrImpl(this._reader); Future get(String url) async { - final uri = Uri.parse(url); - if (uri.scheme != 'asset') { - throw new FormatException('Unsupported uri encountered: $uri', url); + final assetId = fromUri(url); + if (!url.startsWith('asset:')) { + logger.warning('XhrImpl received unexpected url: $url'); } - final assetId = - new AssetId(uri.pathSegments.first, uri.pathSegments.skip(1).join('/')); if (!await _reader.hasInput(assetId)) { throw new ArgumentError.value('Could not read asset at uri $url', 'url'); diff --git a/modules_dart/transform/lib/src/transform/directive_linker/linker.dart b/modules_dart/transform/lib/src/transform/directive_linker/linker.dart deleted file mode 100644 index e537c1edd0..0000000000 --- a/modules_dart/transform/lib/src/transform/directive_linker/linker.dart +++ /dev/null @@ -1,118 +0,0 @@ -library angular2.transform.directive_linker.linker; - -import 'dart:async'; - -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/model/import_export_model.pb.dart'; -import 'package:angular2/src/transform/common/model/ng_deps_model.pb.dart'; -import 'package:barback/barback.dart'; -import 'package:code_transformers/assets.dart'; - -/// Checks the `.ng_deps.json` file represented by `entryPoint` and -/// determines whether it is necessary to the functioning of the Angular 2 -/// Dart app. -/// -/// An `.ng_deps.json` file is not necessary if: -/// 1. It does not register any `@Injectable` types with the system. -/// 2. It does not import any libraries whose `.ng_deps.json` files register -/// any `@Injectable` types with the system. -/// -/// Since `@Directive` and `@Component` inherit from `@Injectable`, we know -/// we will not miss processing any classes annotated with those tags. -Future isNecessary(AssetReader reader, AssetId entryPoint) async { - if (!(await reader.hasInput(entryPoint))) return false; - var jsonString = await reader.readAsString(entryPoint); - if (jsonString == null || jsonString.isEmpty) return false; - var ngDepsModel = new NgDepsModel.fromJson(jsonString); - - if (ngDepsModel.reflectables != null && - ngDepsModel.reflectables.isNotEmpty) return true; - - // We do not register any @Injectables, do we call any dependencies? - var linkedDepsMap = await _processNgImports(reader, entryPoint, ngDepsModel); - return linkedDepsMap.isNotEmpty; -} - -/// Modifies the [NgDepsModel] represented by `entryPoint` to import its -/// dependencies' associated `.ng_deps.dart` files. -/// -/// For example, if entry_point.ng_deps.dart imports dependency.dart, this -/// will check if dependency.ng_deps.json exists. If it does, we add an import -/// to dependency.ng_deps.dart to the entry_point [NgDepsModel] and set -/// `isNgDeps` to `true` to signify that it is a dependency on which we need to -/// call `initReflector`. -Future linkNgDeps(AssetReader reader, AssetId entryPoint) async { - if (!(await reader.hasInput(entryPoint))) return null; - var jsonString = await reader.readAsString(entryPoint); - if (jsonString.isEmpty) return null; - var ngDepsModel = new NgDepsModel.fromJson(jsonString); - - var linkedDepsMap = await _processNgImports(reader, entryPoint, ngDepsModel); - - if (linkedDepsMap.isEmpty) { - // We are not calling `initReflector` on any other libraries, but we still - // return the model to ensure it is written to code. - // TODO(kegluneq): Continue using the protobuf format after this phase. - return ngDepsModel; - } - - for (var i = ngDepsModel.imports.length - 1; i >= 0; --i) { - var import = ngDepsModel.imports[i]; - if (linkedDepsMap.containsKey(import.uri)) { - var linkedModel = new ImportModel() - ..isNgDeps = true - ..uri = toDepsExtension(linkedDepsMap[import.uri]) - ..prefix = 'i$i'; - // TODO(kegluneq): Preserve combinators? - ngDepsModel.imports.insert(i + 1, linkedModel); - } - } - for (var i = 0, iLen = ngDepsModel.exports.length; i < iLen; ++i) { - var export = ngDepsModel.exports[i]; - if (linkedDepsMap.containsKey(export.uri)) { - var linkedModel = new ImportModel() - ..isNgDeps = true - ..uri = toDepsExtension(linkedDepsMap[export.uri]) - ..prefix = 'i${ngDepsModel.imports.length}'; - // TODO(kegluneq): Preserve combinators? - ngDepsModel.imports.add(linkedModel); - } - } - - return ngDepsModel; -} - -bool _isNotDartDirective(dynamic model) { - return !model.uri.startsWith('dart:'); -} - -/// Maps the `uri` of each input [ImportModel] or [ExportModel] to its -/// associated `.ng_deps.json` file, if one exists. -Future> _processNgImports( - AssetReader reader, AssetId ngJsonAsset, NgDepsModel model) { - final nullFuture = new Future.value(null); - final importsAndExports = new List.from(model.imports)..addAll(model.exports); - final retVal = {}; - final entryPoint = - new AssetId(ngJsonAsset.package, toDepsExtension(ngJsonAsset.path)); - return Future - .wait( - importsAndExports.where(_isNotDartDirective).map((dynamic directive) { - // The uri of the import or export with .dart replaced with .ng_deps.json. - // This is the json file containing Angular 2 codegen info, if one exists. - var linkedJsonUri = toJsonExtension(directive.uri); - var spanArg = null; - var linkedNgJsonAsset = uriToAssetId( - entryPoint, linkedJsonUri, logger, spanArg, - errorOnAbsolute: false); - if (linkedNgJsonAsset == ngJsonAsset) return nullFuture; - return reader.hasInput(linkedNgJsonAsset).then((hasInput) { - if (hasInput) { - retVal[directive.uri] = linkedJsonUri; - } - }, onError: (_) => null); - })) - .then((_) => retVal); -} diff --git a/modules_dart/transform/lib/src/transform/directive_linker/transformer.dart b/modules_dart/transform/lib/src/transform/directive_linker/transformer.dart deleted file mode 100644 index 4c60683d4a..0000000000 --- a/modules_dart/transform/lib/src/transform/directive_linker/transformer.dart +++ /dev/null @@ -1,84 +0,0 @@ -library angular2.transform.directive_linker.transformer; - -import 'dart:async'; - -import 'package:angular2/src/transform/common/asset_reader.dart'; -import 'package:angular2/src/transform/common/code/ng_deps_code.dart'; -import 'package:angular2/src/transform/common/formatter.dart'; -import 'package:angular2/src/transform/common/logging.dart' as log; -import 'package:angular2/src/transform/common/names.dart'; -import 'package:barback/barback.dart'; - -import 'linker.dart'; - -/// Transformer responsible for processing `.ng_deps.json` files created by -/// {@link DirectiveProcessor} and ensuring that each imports its dependencies' -/// .ng_deps.dart files. -class DirectiveLinker extends Transformer implements DeclaringTransformer { - DirectiveLinker(); - - @override - bool isPrimary(AssetId id) => id.path.endsWith(DEPS_JSON_EXTENSION); - - @override - declareOutputs(DeclaringTransform transform) { - // TODO(kegluenq): We should consume this, but doing so causes barback to - // incorrectly determine what assets are available in this phase. - // transform.consumePrimary(); - transform.declareOutput(_depsAssetId(transform.primaryId)); - } - - @override - Future apply(Transform transform) async { - await log.initZoned(transform, () async { - var reader = new AssetReader.fromTransform(transform); - var primaryId = transform.primaryInput.id; - var ngDepsModel = await linkNgDeps(reader, primaryId); - // See above - // transform.consumePrimary(); - var outputAssetId = _depsAssetId(primaryId); - if (ngDepsModel != null) { - var buf = new StringBuffer(); - var writer = new NgDepsWriter(buf); - writer.writeNgDepsModel(ngDepsModel); - var formattedCode = formatter.format('$buf', uri: primaryId.path); - transform.addOutput(new Asset.fromString(outputAssetId, formattedCode)); - } else { - transform.addOutput(new Asset.fromString(outputAssetId, '')); - } - }); - } -} - -AssetId _depsAssetId(AssetId primaryId) => - new AssetId(primaryId.package, toDepsExtension(primaryId.path)); - -/// Transformer responsible for removing unnecessary `.ng_deps.json` files -/// created by {@link DirectiveProcessor}. -class EmptyNgDepsRemover extends Transformer implements DeclaringTransformer { - EmptyNgDepsRemover(); - - @override - bool isPrimary(AssetId id) => id.path.endsWith(DEPS_JSON_EXTENSION); - - /// We occasionally consume the primary input, but that depends on the - /// contents of the file, so we conservatively declare that we both consume - /// and output the asset. This prevents barback from making any assumptions - /// about the existence of the assets until after the transformer has run. - @override - declareOutputs(DeclaringTransform transform) { - transform.consumePrimary(); - transform.declareOutput(transform.primaryId); - } - - @override - Future apply(Transform transform) async { - await log.initZoned(transform, () async { - var reader = new AssetReader.fromTransform(transform); - transform.consumePrimary(); - if ((await isNecessary(reader, transform.primaryInput.id))) { - transform.addOutput(transform.primaryInput); - } - }); - } -} diff --git a/modules_dart/transform/lib/src/transform/directive_metadata_linker/linker.dart b/modules_dart/transform/lib/src/transform/directive_metadata_linker/linker.dart deleted file mode 100644 index 06a66f1194..0000000000 --- a/modules_dart/transform/lib/src/transform/directive_metadata_linker/linker.dart +++ /dev/null @@ -1,78 +0,0 @@ -library angular2.transform.directive_metadata_linker.linker; - -import 'dart:async'; -import 'dart:convert'; - -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/ng_meta.dart'; -import 'package:barback/barback.dart'; -import 'package:code_transformers/assets.dart'; -import 'package:path/path.dart' as path; - -/// Returns [NgMeta] associated with [entryPoint] combined with the [NgMeta] of -/// all files `export`ed from the original file. -/// -/// This includes entries for every `Directive`-annotated class and -/// constants that match the directive-aliases pattern. -/// -/// There are entries for each of these which is visible from a file importing -/// the original .dart file that produced `entryPoint`. That is, this includes -/// all `Directive` annotated public classes in that file, all `DirectiveAlias` -/// annotated public variables, and any of those entries which are visible from -/// files which the .dart file `export`ed. -/// -/// Returns an empty [NgMeta] if there are no `Directive`-annotated classes or -/// `DirectiveAlias` annotated constants in `entryPoint`. -Future linkDirectiveMetadata(AssetReader reader, AssetId entryPoint) { - return _linkDirectiveMetadataRecursive( - reader, entryPoint, new Set()); -} - -final _nullFuture = new Future.value(null); - -// TODO(kegluneq): Don't reinvent the wheel? Centalize? -AssetId _fromPackageUri(String packageUri) { - var pathParts = path.url.split(packageUri); - return new AssetId(pathParts[0].substring('package:'.length), - 'lib/${pathParts.getRange(1, pathParts.length).join('/')}'); -} - -Future _linkDirectiveMetadataRecursive( - AssetReader reader, AssetId entryPoint, Set seen) async { - if (entryPoint == null) { - return new NgMeta.empty(); - } - // Break cycles, if they exist. - if (seen.contains(entryPoint)) return _nullFuture; - seen.add(entryPoint); - if (!(await reader.hasInput(entryPoint))) return new NgMeta.empty(); - - var ngMetaJson = await reader.readAsString(entryPoint); - if (ngMetaJson == null || ngMetaJson.isEmpty) return new NgMeta.empty(); - - var ngMeta = new NgMeta.fromJson(JSON.decode(ngMetaJson)); - - if (ngMeta.exports == null) return ngMeta; - - // Recursively add NgMeta files from `exports`. - return Future.wait(ngMeta.exports.map((uri) { - if (uri.startsWith('dart:')) return _nullFuture; - var metaUri = toMetaExtension(uri); - var assetId; - if (uri.startsWith('package:')) { - assetId = _fromPackageUri(metaUri); - } else { - assetId = uriToAssetId(entryPoint, metaUri, logger, null /* span */, - errorOnAbsolute: false); - } - - return _linkDirectiveMetadataRecursive(reader, assetId, seen) - .then((exportedNgMeta) { - if (exportedNgMeta != null) { - ngMeta.addAll(exportedNgMeta); - } - }); - })).then((_) => ngMeta); -} diff --git a/modules_dart/transform/lib/src/transform/directive_metadata_linker/ng_deps_linker.dart b/modules_dart/transform/lib/src/transform/directive_metadata_linker/ng_deps_linker.dart new file mode 100644 index 0000000000..3b532a262d --- /dev/null +++ b/modules_dart/transform/lib/src/transform/directive_metadata_linker/ng_deps_linker.dart @@ -0,0 +1,88 @@ +library angular2.transform.directive_metadata_linker.ng_deps_linker; + +import 'dart:async'; + +import 'package:angular2/src/core/services.dart'; +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/model/import_export_model.pb.dart'; +import 'package:angular2/src/transform/common/model/ng_deps_model.pb.dart'; +import 'package:angular2/src/transform/common/url_resolver.dart'; +import 'package:barback/barback.dart'; + +/// Modifies the [NgDepsModel] represented by `entryPoint` to import its +/// dependencies' associated `.ng_deps.dart` files. +/// +/// For example, if entry_point.ng_deps.dart imports dependency.dart, this +/// will check if dependency.ng_meta.json exists. If it does, we add an import +/// to dependency.ng_deps.dart to the entry_point [NgDepsModel] and set +/// `isNgDeps` to `true` to signify that it is a dependency on which we need to +/// call `initReflector`. +Future linkNgDeps(NgDepsModel ngDepsModel, AssetReader reader, + AssetId entryPoint, UrlResolver resolver) async { + if (ngDepsModel == null) return null; + var linkedDepsMap = + await _processNgImports(ngDepsModel, reader, entryPoint, resolver); + + if (linkedDepsMap.isEmpty) { + // We are not calling `initReflector` on any other libraries, but we still + // return the model to ensure it is written to code. + // TODO(kegluneq): Continue using the protobuf format after this phase. + return ngDepsModel; + } + + for (var i = ngDepsModel.imports.length - 1; i >= 0; --i) { + var import = ngDepsModel.imports[i]; + if (linkedDepsMap.containsKey(import.uri)) { + var linkedModel = new ImportModel() + ..isNgDeps = true + ..uri = toDepsExtension(import.uri) + ..prefix = 'i$i'; + // TODO(kegluneq): Preserve combinators? + ngDepsModel.imports.insert(i + 1, linkedModel); + } + } + for (var i = 0, iLen = ngDepsModel.exports.length; i < iLen; ++i) { + var export = ngDepsModel.exports[i]; + if (linkedDepsMap.containsKey(export.uri)) { + var linkedModel = new ImportModel() + ..isNgDeps = true + ..uri = toDepsExtension(export.uri) + ..prefix = 'i${ngDepsModel.imports.length}'; + // TODO(kegluneq): Preserve combinators? + ngDepsModel.imports.add(linkedModel); + } + } + + return ngDepsModel; +} + +bool _isNotDartDirective(dynamic model) => !isDartCoreUri(model.uri); + +/// Maps the `uri` of each input [ImportModel] or [ExportModel] to its +/// associated `.ng_deps.json` file, if one exists. +Future> _processNgImports(NgDepsModel model, + AssetReader reader, AssetId assetId, UrlResolver resolver) async { + final importsAndExports = new List.from(model.imports)..addAll(model.exports); + final retVal = {}; + final assetUri = toAssetUri(assetId); + return Future + .wait( + importsAndExports.where(_isNotDartDirective).map((dynamic directive) { + // The uri of the import or export with .dart replaced with .ng_meta.json. + // This is the json file containing Angular 2 codegen info, if one exists. + var linkedJsonUri = + resolver.resolve(assetUri, toMetaExtension(directive.uri)); + return reader.hasInput(fromUri(linkedJsonUri)).then((hasInput) { + if (hasInput) { + retVal[directive.uri] = linkedJsonUri; + } + }, onError: (err, stack) { + logger.warning('Error while looking for $linkedJsonUri. ' + 'Message: $err\n' + 'Stack: $stack'); + }); + })) + .then((_) => retVal); +} diff --git a/modules_dart/transform/lib/src/transform/directive_metadata_linker/ng_meta_linker.dart b/modules_dart/transform/lib/src/transform/directive_metadata_linker/ng_meta_linker.dart new file mode 100644 index 0000000000..a2a066d96d --- /dev/null +++ b/modules_dart/transform/lib/src/transform/directive_metadata_linker/ng_meta_linker.dart @@ -0,0 +1,88 @@ +library angular2.transform.directive_metadata_linker.linker; + +import 'dart:async'; +import 'dart:convert'; + +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/ng_meta.dart'; +import 'package:angular2/src/transform/common/url_resolver.dart'; +import 'package:barback/barback.dart'; + +import 'ng_deps_linker.dart'; + +/// Returns [NgMeta] associated with [entryPoint] combined with the [NgMeta] of +/// all files `export`ed from the original file. +/// +/// This includes entries for every `Directive`-annotated class and +/// constants that match the directive-aliases pattern. +/// +/// There are entries for each of these which is visible from a file importing +/// the original .dart file that produced `entryPoint`. That is, this includes +/// all `Directive` annotated public classes in that file, all `DirectiveAlias` +/// annotated public variables, and any of those entries which are visible from +/// files which the .dart file `export`ed. +/// +/// Returns an empty [NgMeta] if there are no `Directive`-annotated classes or +/// `DirectiveAlias` annotated constants in `entryPoint`. +Future linkDirectiveMetadata( + AssetReader reader, AssetId entryPoint) async { + var ngMeta = await _readNgMeta(reader, entryPoint); + if (ngMeta == null || ngMeta.isEmpty) return null; + + await Future.wait([ + linkNgDeps(ngMeta.ngDeps, reader, entryPoint, _urlResolver), + _linkDirectiveMetadataRecursive( + ngMeta, reader, entryPoint, new Set()) + ]); + return ngMeta; +} + +Future _readNgMeta(AssetReader reader, AssetId ngMetaAssetId) async { + if (!(await reader.hasInput(ngMetaAssetId))) return null; + + var ngMetaJson = await reader.readAsString(ngMetaAssetId); + if (ngMetaJson == null || ngMetaJson.isEmpty) return null; + + return new NgMeta.fromJson(JSON.decode(ngMetaJson)); +} + +final _urlResolver = const TransformerUrlResolver(); + +Future _linkDirectiveMetadataRecursive(NgMeta ngMeta, + AssetReader reader, AssetId assetId, Set seen) async { + if (ngMeta == null || + ngMeta.ngDeps == null || + ngMeta.ngDeps.exports == null) { + return ngMeta; + } + var assetUri = toAssetUri(assetId); + + return Future + .wait(ngMeta.ngDeps.exports + .where((export) => !isDartCoreUri(export.uri)) + .map((export) => + _urlResolver.resolve(assetUri, toMetaExtension(export.uri))) + .where((uri) => !seen.contains(uri)) + .map((uri) async { + seen.add(uri); + try { + final exportAssetId = fromUri(uri); + if (await reader.hasInput(exportAssetId)) { + var exportNgMetaJson = await reader.readAsString(exportAssetId); + if (exportNgMetaJson == null) return null; + var exportNgMeta = new NgMeta.fromJson(JSON.decode(exportNgMetaJson)); + await _linkDirectiveMetadataRecursive( + exportNgMeta, reader, exportAssetId, seen); + if (exportNgMeta != null) { + ngMeta.addAll(exportNgMeta); + } + } + } catch (err, st) { + // Log and continue. + logger.warning('Failed to fetch $uri. Message: $err.\n$st'); + } + })) + .then((_) => ngMeta); +} diff --git a/modules_dart/transform/lib/src/transform/directive_metadata_linker/transformer.dart b/modules_dart/transform/lib/src/transform/directive_metadata_linker/transformer.dart index eb4975ba4f..2210e9e37d 100644 --- a/modules_dart/transform/lib/src/transform/directive_metadata_linker/transformer.dart +++ b/modules_dart/transform/lib/src/transform/directive_metadata_linker/transformer.dart @@ -4,11 +4,13 @@ import 'dart:async'; import 'dart:convert'; import 'package:angular2/src/transform/common/asset_reader.dart'; +import 'package:angular2/src/transform/common/code/ng_deps_code.dart'; +import 'package:angular2/src/transform/common/formatter.dart'; import 'package:angular2/src/transform/common/logging.dart' as log; import 'package:angular2/src/transform/common/names.dart'; import 'package:barback/barback.dart'; -import 'linker.dart'; +import 'ng_meta_linker.dart'; /// Transformer responsible for processing .ng_meta.json files created by /// {@link DirectiveProcessor} and "linking" them. @@ -31,6 +33,7 @@ class DirectiveMetadataLinker extends Transformer // incorrectly determine what assets are available in this phase. // transform.consumePrimary(); transform.declareOutput(transform.primaryId); + transform.declareOutput(_depsAssetId(transform.primaryId)); } @override @@ -42,15 +45,32 @@ class DirectiveMetadataLinker extends Transformer new AssetReader.fromTransform(transform), primaryId).then((ngMeta) { // See above // transform.consumePrimary(); - if (ngMeta != null && !ngMeta.isEmpty) { - transform.addOutput(new Asset.fromString( - primaryId, _encoder.convert(ngMeta.toJson()))); - } else { - // Not outputting an asset could confuse barback, so output an - // empty one. - transform.addOutput(transform.primaryInput); + if (ngMeta != null) { + if (!ngMeta.types.isEmpty || !ngMeta.aliases.isEmpty) { + transform.addOutput(new Asset.fromString( + primaryId, _encoder.convert(ngMeta.toJson(withNgDeps: false)))); + } else { + // Not outputting an asset could confuse barback. + transform.addOutput(new Asset.fromString(primaryId, '')); + } + + var depsAssetId = _depsAssetId(primaryId); + if (!ngMeta.isNgDepsEmpty) { + var buf = new StringBuffer(); + var writer = new NgDepsWriter(buf); + writer.writeNgDepsModel(ngMeta.ngDeps); + var formattedCode = + formatter.format(buf.toString(), uri: depsAssetId.path); + transform + .addOutput(new Asset.fromString(depsAssetId, formattedCode)); + } else { + transform.addOutput(new Asset.fromString(depsAssetId, '')); + } } }); }); } } + +AssetId _depsAssetId(AssetId primaryId) => + new AssetId(primaryId.package, toDepsExtension(primaryId.path)); diff --git a/modules_dart/transform/lib/src/transform/directive_processor/rewriter.dart b/modules_dart/transform/lib/src/transform/directive_processor/rewriter.dart index 5daefe89db..c00bd71500 100644 --- a/modules_dart/transform/lib/src/transform/directive_processor/rewriter.dart +++ b/modules_dart/transform/lib/src/transform/directive_processor/rewriter.dart @@ -9,7 +9,6 @@ import 'package:angular2/src/transform/common/code/ng_deps_code.dart'; import 'package:angular2/src/transform/common/directive_metadata_reader.dart'; import 'package:angular2/src/transform/common/interface_matcher.dart'; import 'package:angular2/src/transform/common/logging.dart'; -import 'package:angular2/src/transform/common/model/ng_deps_model.pb.dart'; import 'package:angular2/src/transform/common/ng_compiler.dart'; import 'package:angular2/src/transform/common/ng_meta.dart'; import 'package:barback/barback.dart' show AssetId; @@ -17,26 +16,20 @@ import 'package:angular2/src/core/compiler/template_compiler.dart'; import 'inliner.dart'; -/// Generates a file registering all Angular 2 `Directive`s found in `code` in -/// ngDeps format [TODO(kegluneq): documentation reference needed]. `assetId` is -/// the id of the asset containing `code`. -/// -/// If no Angular 2 `Directive`s are found in `code`, returns the empty -/// string unless `forceGenerate` is true, in which case an empty ngDeps -/// file is created. -Future createNgDeps(AssetReader reader, AssetId assetId, - AnnotationMatcher annotationMatcher, NgMeta ngMeta) async { +/// Generates an instance of [NgMeta] describing the file at `assetId`. +Future createNgDeps(AssetReader reader, AssetId assetId, + AnnotationMatcher annotationMatcher) async { // TODO(kegluneq): Shortcut if we can determine that there are no // [Directive]s present, taking into account `export`s. var codeWithParts = await inlineParts(reader, assetId); if (codeWithParts == null || codeWithParts.isEmpty) return null; - var parsedCode = parseCompilationUnit(codeWithParts, name: '${assetId.path} and parts'); var ngDepsVisitor = new NgDepsVisitor(assetId, annotationMatcher); parsedCode.accept(ngDepsVisitor); - var ngDepsModel = ngDepsVisitor.model; + + var ngMeta = new NgMeta(ngDeps: ngDepsVisitor.model); var templateCompiler = createTemplateCompiler(reader); var ngMetaVisitor = new _NgMetaVisitor( @@ -44,21 +37,9 @@ Future createNgDeps(AssetReader reader, AssetId assetId, parsedCode.accept(ngMetaVisitor); await ngMetaVisitor.whenDone(); - // If this file imports only dart: libraries and does not define any - // reflectables of its own, it doesn't need a .ng_deps.dart file. - if (ngDepsModel.reflectables == null || ngDepsModel.reflectables.isEmpty) { - if (ngDepsModel.imports.every(_isDartImport) && - ngDepsModel.exports.every(_isDartImport)) { - return null; - } - } - - return ngDepsModel; + return ngMeta; } -// `model` can be an [ImportModel] or [ExportModel]. -bool _isDartImport(dynamic model) => model.uri.startsWith('dart:'); - // TODO(kegluneq): Allow the caller to provide an InterfaceMatcher. final _interfaceMatcher = new InterfaceMatcher(); @@ -96,12 +77,6 @@ class _NgMetaVisitor extends Object with SimpleAstVisitor { return node.declarations.accept(this); } - @override - Object visitExportDirective(ExportDirective node) { - ngMeta.exports.add(stringLiteralToString(node.uri)); - return null; - } - @override Object visitClassDeclaration(ClassDeclaration node) { _normalizations.add(_reader diff --git a/modules_dart/transform/lib/src/transform/directive_processor/transformer.dart b/modules_dart/transform/lib/src/transform/directive_processor/transformer.dart index be8e253e9c..fb30856281 100644 --- a/modules_dart/transform/lib/src/transform/directive_processor/transformer.dart +++ b/modules_dart/transform/lib/src/transform/directive_processor/transformer.dart @@ -8,7 +8,6 @@ import 'package:angular2/src/transform/common/asset_reader.dart'; import 'package:angular2/src/transform/common/logging.dart' as log; import 'package:angular2/src/transform/common/names.dart'; import 'package:angular2/src/transform/common/options.dart'; -import 'package:angular2/src/transform/common/ng_meta.dart'; import 'package:barback/barback.dart'; import 'rewriter.dart'; @@ -37,7 +36,6 @@ class DirectiveProcessor extends Transformer implements DeclaringTransformer { @override declareOutputs(DeclaringTransform transform) { transform.declareOutput(_ngMetaAssetId(transform.primaryId)); - transform.declareOutput(_ngDepsAssetId(transform.primaryId)); } @override @@ -46,20 +44,13 @@ class DirectiveProcessor extends Transformer implements DeclaringTransformer { await log.initZoned(transform, () async { var primaryId = transform.primaryInput.id; var reader = new AssetReader.fromTransform(transform); - var ngMeta = new NgMeta.empty(); - var ngDepsModel = await createNgDeps( - reader, primaryId, options.annotationMatcher, ngMeta); - // TODO(kegluneq): Combine NgDepsModel with NgMeta in a single .json file. - if (ngDepsModel != null) { - var ngDepsAssetId = _ngDepsAssetId(primaryId); - transform.addOutput(new Asset.fromString( - ngDepsAssetId, _encoder.convert(ngDepsModel.writeToJsonMap()))); - } - var metaOutputId = _ngMetaAssetId(primaryId); - if (!ngMeta.isEmpty) { - transform.addOutput(new Asset.fromString( - metaOutputId, _encoder.convert(ngMeta.toJson()))); + var ngMeta = + await createNgDeps(reader, primaryId, options.annotationMatcher); + if (ngMeta == null || ngMeta.isEmpty) { + return; } + transform.addOutput(new Asset.fromString( + _ngMetaAssetId(primaryId), _encoder.convert(ngMeta.toJson()))); }); } } @@ -68,8 +59,3 @@ AssetId _ngMetaAssetId(AssetId primaryInputId) { return new AssetId( primaryInputId.package, toMetaExtension(primaryInputId.path)); } - -AssetId _ngDepsAssetId(AssetId primaryInputId) { - return new AssetId( - primaryInputId.package, toJsonExtension(primaryInputId.path)); -} diff --git a/modules_dart/transform/lib/src/transform/template_compiler/compile_data_creator.dart b/modules_dart/transform/lib/src/transform/template_compiler/compile_data_creator.dart index 15beca57cc..4668d34470 100644 --- a/modules_dart/transform/lib/src/transform/template_compiler/compile_data_creator.dart +++ b/modules_dart/transform/lib/src/transform/template_compiler/compile_data_creator.dart @@ -30,7 +30,8 @@ class CompileDataResults { NormalizedComponentWithViewDirectives> viewDefinitions; final List directiveMetadatas; - CompileDataResults._(this.ngDeps, this.viewDefinitions, this.directiveMetadatas); + CompileDataResults._( + this.ngDeps, this.viewDefinitions, this.directiveMetadatas); } // TODO(kegluenq): Improve this test. @@ -86,9 +87,7 @@ class _CompileDataCreator { Future> _createImportAssetToPrefixMap() async { var ngDeps = await ngDepsFuture; - var importAssetToPrefix = { - entryPoint: null - }; + var importAssetToPrefix = {entryPoint: null}; for (ImportDirective node in ngDeps.imports) { var uri = stringLiteralToString(node.uri); @@ -144,12 +143,15 @@ class _CompileDataCreator { importAssetId.package, toMetaExtension(importAssetId.path)); if (await reader.hasInput(metaAssetId)) { try { - var json = JSON.decode(await reader.readAsString(metaAssetId)); - var newMetadata = new NgMeta.fromJson(json); - if (importAssetId == entryPoint) { - this.directiveMetadatas.addAll(newMetadata.types.values); + var jsonString = await reader.readAsString(metaAssetId); + if (jsonString != null && jsonString.isNotEmpty) { + var json = JSON.decode(jsonString); + var newMetadata = new NgMeta.fromJson(json); + if (importAssetId == entryPoint) { + this.directiveMetadatas.addAll(newMetadata.types.values); + } + ngMeta.addAll(newMetadata); } - ngMeta.addAll(newMetadata); } catch (ex, stackTrace) { logger.warning('Failed to decode: $ex, $stackTrace', asset: metaAssetId); diff --git a/modules_dart/transform/lib/src/transform/transformer.dart b/modules_dart/transform/lib/src/transform/transformer.dart index 045e194d1a..975274b364 100644 --- a/modules_dart/transform/lib/src/transform/transformer.dart +++ b/modules_dart/transform/lib/src/transform/transformer.dart @@ -4,7 +4,6 @@ import 'package:barback/barback.dart'; import 'package:dart_style/dart_style.dart'; import 'deferred_rewriter/transformer.dart'; -import 'directive_linker/transformer.dart'; import 'directive_metadata_linker/transformer.dart'; import 'directive_processor/transformer.dart'; import 'bind_generator/transformer.dart'; @@ -30,14 +29,8 @@ class AngularTransformerGroup extends TransformerGroup { [new ReflectionRemover(options)], [new DirectiveProcessor(options)] ]; - phases.addAll(new List.generate( - options.optimizationPhases, (_) => [new EmptyNgDepsRemover()])); phases.addAll([ - [ - new DeferredRewriter(options), - new DirectiveLinker(), - new DirectiveMetadataLinker() - ], + [new DeferredRewriter(options), new DirectiveMetadataLinker()], [new BindGenerator(options)], [new TemplateCompiler(options)], [new StylesheetCompiler()], diff --git a/modules_dart/transform/test/transform/common/ng_meta_helper.dart b/modules_dart/transform/test/transform/common/ng_meta_helper.dart new file mode 100644 index 0000000000..e724aa89e1 --- /dev/null +++ b/modules_dart/transform/test/transform/common/ng_meta_helper.dart @@ -0,0 +1,43 @@ +library angular2.test.transform.common.ng_meta_helper; + +import 'package:angular2/src/core/compiler/directive_metadata.dart'; +import 'package:angular2/src/core/change_detection/change_detection.dart'; +import 'package:angular2/src/core/metadata/view.dart' show ViewEncapsulation; + +export 'package:angular2/src/core/compiler/directive_metadata.dart'; +export 'package:angular2/src/core/change_detection/change_detection.dart'; +export 'package:angular2/src/core/metadata/view.dart' show ViewEncapsulation; +export 'package:angular2/src/transform/common/model/ng_deps_model.pb.dart'; +export 'package:angular2/src/transform/common/ng_meta.dart'; + +CompileDirectiveMetadata createComponentMetadataForTest( + {String name: 'TestMetadata', + moduleUrl: 'asset:angular2/test/test.dart', + selector: '[test]', + String template: 'Test'}) { + return createDirectiveMetadataForTest( + name: name, + moduleUrl: moduleUrl, + selector: selector, + template: new CompileTemplateMetadata( + encapsulation: ViewEncapsulation.Emulated, template: template)); +} + +CompileDirectiveMetadata createDirectiveMetadataForTest( + {String name: 'TestMetadata', + String moduleUrl: 'asset:angular2/test/test.dart', + String selector: '[test]', + CompileTemplateMetadata template: null}) { + return CompileDirectiveMetadata.create( + type: new CompileTypeMetadata(name: name, moduleUrl: moduleUrl), + isComponent: false, + dynamicLoadable: true, + selector: selector, + exportAs: null, + changeDetection: ChangeDetectionStrategy.Default, + inputs: [], + outputs: [], + host: {}, + lifecycleHooks: [], + template: template); +} diff --git a/modules_dart/transform/test/transform/common/url_resolver_tests.dart b/modules_dart/transform/test/transform/common/url_resolver_tests.dart new file mode 100644 index 0000000000..4deffa16b5 --- /dev/null +++ b/modules_dart/transform/test/transform/common/url_resolver_tests.dart @@ -0,0 +1,166 @@ +library angular2.test.transform.common.url_resolver_tests; + +import 'package:angular2/src/transform/common/url_resolver.dart'; +import 'package:barback/barback.dart'; +import 'package:guinness/guinness.dart'; + +main() => allTests(); + +void allTests() { + var urlResolver = const TransformerUrlResolver(); + + describe('toAssetUri', () { + it('should convert `AssetId`s to asset: uris', () { + var assetId = new AssetId('test_package', 'lib/src/impl.dart'); + expect(toAssetUri(assetId)) + .toEqual('asset:test_package/lib/src/impl.dart'); + }); + + it('should throw if passed a null AssetId', () { + expect(() => toAssetUri(null)).toThrowWith(anInstanceOf: ArgumentError); + }); + }); + + describe('fromUri', () { + it('should convert asset: `uri`s to `AssetId`s', () { + expect(fromUri('asset:test_package/lib/src/impl.dart')) + .toEqual(new AssetId('test_package', 'lib/src/impl.dart')); + }); + + it('should convert package: `uri`s to `AssetId`s', () { + expect(fromUri('package:test_package/src/impl.dart')) + .toEqual(new AssetId('test_package', 'lib/src/impl.dart')); + }); + + it('should throw if passed a null uri', () { + expect(() => fromUri(null)).toThrowWith(anInstanceOf: ArgumentError); + }); + + it('should throw if passed an empty uri', () { + expect(() => fromUri('')).toThrowWith(anInstanceOf: ArgumentError); + }); + }); + + describe('isDartCoreUri', () { + it('should detect dart: uris', () { + expect(isDartCoreUri('dart:core')).toBeTrue(); + expect(isDartCoreUri('dart:convert')).toBeTrue(); + expect(isDartCoreUri('package:angular2/angular2.dart')).toBeFalse(); + expect(isDartCoreUri('asset:angular2/lib/angular2.dart')).toBeFalse(); + }); + + it('should throw if passed a null uri', () { + expect(() => isDartCoreUri(null)) + .toThrowWith(anInstanceOf: ArgumentError); + }); + + it('should throw if passed an empty uri', () { + expect(() => isDartCoreUri('')).toThrowWith(anInstanceOf: ArgumentError); + }); + }); + + describe('toAssetScheme', () { + it('should throw for relative `Uri`s', () { + expect(() => toAssetScheme(Uri.parse('/lib/src/file.dart'))) + .toThrowWith(anInstanceOf: ArgumentError); + }); + + it('should convert package: `Uri`s to asset:', () { + expect(toAssetScheme(Uri.parse('package:angular2/angular2.dart'))) + .toEqual(Uri.parse('asset:angular2/lib/angular2.dart')); + }); + + it('should throw for package: `Uri`s which are too short', () { + expect(() => toAssetScheme(Uri.parse('package:angular2'))) + .toThrowWith(anInstanceOf: FormatException); + }); + + it('should convert asset: `Uri`s to asset:', () { + expect(toAssetScheme(Uri.parse('asset:angular2/lib/angular2.dart'))) + .toEqual(Uri.parse('asset:angular2/lib/angular2.dart')); + }); + + it('should throw for asset: `Uri`s which are too short', () { + expect(() => toAssetScheme(Uri.parse('asset:angular2'))) + .toThrowWith(anInstanceOf: FormatException); + + expect(() => toAssetScheme(Uri.parse('asset:angular2/lib'))) + .toThrowWith(anInstanceOf: FormatException); + }); + + it('should throw for unsupported schemes', () { + expect(() => toAssetScheme(Uri.parse('file:///angular2'))) + .toThrowWith(anInstanceOf: FormatException); + }); + + it('should throw if passed a null uri', () { + expect(() => toAssetScheme(null)) + .toThrowWith(anInstanceOf: ArgumentError); + }); + }); + + describe('resolve', () { + it('should resolve package: uris to asset: uris', () { + expect(urlResolver.resolve('', 'package:angular2/angular2.dart')) + .toEqual('asset:angular2/lib/angular2.dart'); + }); + + it('should ignore baseUrl for absolute uris', () { + expect(urlResolver.resolve(null, 'package:angular2/angular2.dart')) + .toEqual('asset:angular2/lib/angular2.dart'); + expect(urlResolver.resolve(null, 'asset:angular2/lib/angular2.dart')) + .toEqual('asset:angular2/lib/angular2.dart'); + }); + + it('should resolve asset: uris to asset: uris', () { + expect(urlResolver.resolve('', 'asset:angular2/lib/angular2.dart')) + .toEqual('asset:angular2/lib/angular2.dart'); + }); + + it('should resolve relative uris when baseUrl is package: uri', () { + expect(urlResolver.resolve('package:angular2/angular2.dart', + 'src/transform/transformer.dart')) + .toEqual('asset:angular2/lib/src/transform/transformer.dart'); + }); + + it('should resolve relative uris when baseUrl is asset: uri', () { + expect(urlResolver.resolve('asset:angular2/lib/angular2.dart', + 'src/transform/transformer.dart')) + .toEqual('asset:angular2/lib/src/transform/transformer.dart'); + }); + + it('should normalize uris', () { + expect(urlResolver.resolve('asset:angular2/lib/angular2.dart', + 'src/transform/../transform/transformer.dart')) + .toEqual('asset:angular2/lib/src/transform/transformer.dart'); + expect(urlResolver.resolve('asset:angular2/lib/src/../angular2.dart', + 'src/transform/transformer.dart')) + .toEqual('asset:angular2/lib/src/transform/transformer.dart'); + }); + + it('should throw if passed a null uri', () { + expect(() => urlResolver.resolve('package:angular2/angular2.dart', null)) + .toThrowWith(anInstanceOf: ArgumentError); + }); + + it('should gracefully handle an empty uri', () { + expect(urlResolver.resolve('package:angular2/angular2.dart', '')) + .toEqual('asset:angular2/lib/angular2.dart'); + }); + + it('should throw if passed a relative uri and a null baseUri', () { + expect(() => urlResolver.resolve(null, 'angular2/angular2.dart')) + .toThrowWith(anInstanceOf: ArgumentError); + }); + + it('should throw if passed a relative uri and an empty baseUri', () { + expect(() => urlResolver.resolve('', 'angular2/angular2.dart')) + .toThrowWith(anInstanceOf: ArgumentError); + }); + + it('should throw if the resolved uri is relative', () { + expect(() => urlResolver.resolve('/angular2/', 'angular2.dart')) + .toThrowWith(anInstanceOf: ArgumentError); + }); + }); +} diff --git a/modules_dart/transform/test/transform/directive_linker/all_tests.dart b/modules_dart/transform/test/transform/directive_linker/all_tests.dart deleted file mode 100644 index b295098ed7..0000000000 --- a/modules_dart/transform/test/transform/directive_linker/all_tests.dart +++ /dev/null @@ -1,137 +0,0 @@ -library angular2.test.transform.directive_linker.all_tests; - -import 'package:barback/barback.dart'; -import 'package:angular2/src/transform/common/model/annotation_model.pb.dart'; -import 'package:angular2/src/transform/common/model/import_export_model.pb.dart'; -import 'package:angular2/src/transform/common/model/ng_deps_model.pb.dart'; -import 'package:angular2/src/transform/common/model/reflection_info_model.pb.dart'; -import 'package:angular2/src/transform/directive_linker/linker.dart'; -import 'package:dart_style/dart_style.dart'; -import 'package:guinness/guinness.dart'; - -import '../common/read_file.dart'; - -var formatter = new DartFormatter(); - -main() => allTests(); - -void allTests() { - var reader; - - beforeEach(() { - reader = new TestAssetReader(); - }); - - it('should chain imported dependencies.', () async { - var fooModel = new NgDepsModel() - ..libraryUri = 'test.foo' - ..imports.add(new ImportModel() - ..uri = 'bar.dart' - ..prefix = 'dep'); - var barModel = new NgDepsModel()..libraryUri = 'test.bar'; - - var fooAssetId = new AssetId('a', 'lib/foo.ng_deps.json'); - reader - ..addAsset(fooAssetId, fooModel.writeToJson()) - ..addAsset( - new AssetId('a', 'lib/bar.ng_deps.json'), barModel.writeToJson()); - - var linked = await linkNgDeps(reader, fooAssetId); - expect(linked).toBeNotNull(); - var linkedImport = - linked.imports.firstWhere((i) => i.uri.endsWith('bar.ng_deps.dart')); - expect(linkedImport).toBeNotNull(); - expect(linkedImport.isNgDeps).toBeTrue(); - expect(linkedImport.prefix.startsWith('i')).toBeTrue(); - }); - - it('should chain exported dependencies.', () async { - var fooModel = new NgDepsModel() - ..libraryUri = 'test.foo' - ..exports.add(new ExportModel()..uri = 'bar.dart'); - var barModel = new NgDepsModel()..libraryUri = 'test.bar'; - - var fooAssetId = new AssetId('a', 'lib/foo.ng_deps.json'); - reader - ..addAsset(fooAssetId, fooModel.writeToJson()) - ..addAsset( - new AssetId('a', 'lib/bar.ng_deps.json'), barModel.writeToJson()); - - var linked = await linkNgDeps(reader, fooAssetId); - expect(linked).toBeNotNull(); - var linkedImport = - linked.imports.firstWhere((i) => i.uri.endsWith('bar.ng_deps.dart')); - expect(linkedImport).toBeNotNull(); - expect(linkedImport.isNgDeps).toBeTrue(); - expect(linkedImport.prefix.startsWith('i')).toBeTrue(); - }); - - describe('isNecessary', () { - it('should drop deps that do no registration and do not import.', () async { - var fooModel = new NgDepsModel()..libraryUri = 'test.foo'; - - var fooAssetId = new AssetId('a', 'lib/foo.ng_deps.json'); - reader.addAsset(fooAssetId, fooModel.writeToJson()); - expect(await isNecessary(reader, fooAssetId)).toBeFalse(); - }); - - it('should retain deps that import other deps.', () async { - var fooModel = new NgDepsModel() - ..libraryUri = 'test.foo' - ..imports.add(new ImportModel()..uri = 'bar.dart'); - var barModel = new NgDepsModel()..libraryUri = 'test.bar'; - - var fooAssetId = new AssetId('a', 'lib/foo.ng_deps.json'); - reader - ..addAsset(fooAssetId, fooModel.writeToJson()) - ..addAsset( - new AssetId('a', 'lib/bar.ng_deps.json'), barModel.writeToJson()); - - expect(await isNecessary(reader, fooAssetId)).toBeTrue(); - }); - - it('should retain deps that export other deps.', () async { - var fooModel = new NgDepsModel() - ..libraryUri = 'test.foo' - ..exports.add(new ExportModel()..uri = 'bar.dart'); - var barModel = new NgDepsModel()..libraryUri = 'test.bar'; - - var fooAssetId = new AssetId('a', 'lib/foo.ng_deps.json'); - reader - ..addAsset(fooAssetId, fooModel.writeToJson()) - ..addAsset( - new AssetId('a', 'lib/bar.ng_deps.json'), barModel.writeToJson()); - - expect(await isNecessary(reader, fooAssetId)).toBeTrue(); - }); - - it('should retain deps that register injectable types.', () async { - var fooModel = new NgDepsModel() - ..libraryUri = 'test.foo' - ..reflectables.add(new ReflectionInfoModel() - ..name = 'MyInjectable' - ..annotations.add(new AnnotationModel() - ..name = 'Injectable' - ..isInjectable = true)); - - var fooAssetId = new AssetId('a', 'lib/foo.ng_deps.json'); - reader.addAsset(fooAssetId, fooModel.writeToJson()); - expect(await isNecessary(reader, fooAssetId)).toBeTrue(); - }); - - it('should retain deps that register injectable functions.', () async { - var fooModel = new NgDepsModel() - ..libraryUri = 'test.foo' - ..reflectables.add(new ReflectionInfoModel() - ..name = 'injectableFunction' - ..isFunction = true - ..annotations.add(new AnnotationModel() - ..name = 'Injectable' - ..isInjectable = true)); - - var fooAssetId = new AssetId('a', 'lib/foo.ng_deps.json'); - reader.addAsset(fooAssetId, fooModel.writeToJson()); - expect(await isNecessary(reader, fooAssetId)).toBeTrue(); - }); - }); -} diff --git a/modules_dart/transform/test/transform/directive_metadata_extractor/export_cycle_files/bar.ng_deps.dart b/modules_dart/transform/test/transform/directive_metadata_extractor/export_cycle_files/bar.ng_deps.dart deleted file mode 100644 index 0381a810ef..0000000000 --- a/modules_dart/transform/test/transform/directive_metadata_extractor/export_cycle_files/bar.ng_deps.dart +++ /dev/null @@ -1,19 +0,0 @@ -library foo.ng_deps.dart; - -import 'bar.dart'; -import 'package:angular2/src/core/metadata.dart'; - -export 'baz.dart'; -import 'baz.ng_deps.dart' as i0; - -var _visited = false; -void initReflector(reflector) { - if (_visited) return; - _visited = true; - reflector - ..registerType( - BarComponent, - new ReflectionInfo(const [const Component(selector: '[bar]')], const [], - () => new BarComponent())); - i0.initReflector(reflector); -} diff --git a/modules_dart/transform/test/transform/directive_metadata_extractor/export_cycle_files/baz.ng_deps.dart b/modules_dart/transform/test/transform/directive_metadata_extractor/export_cycle_files/baz.ng_deps.dart deleted file mode 100644 index 58fee37db4..0000000000 --- a/modules_dart/transform/test/transform/directive_metadata_extractor/export_cycle_files/baz.ng_deps.dart +++ /dev/null @@ -1,17 +0,0 @@ -library foo.ng_deps.dart; - -import 'baz.dart'; -import 'package:angular2/src/core/metadata.dart'; - -export 'foo.dart'; - -var _visited = false; -void initReflector(reflector) { - if (_visited) return; - _visited = true; - reflector - ..registerType( - BazComponent, - new ReflectionInfo(const [const Component(selector: '[baz]')], const [], - () => new BazComponent())); -} diff --git a/modules_dart/transform/test/transform/directive_metadata_extractor/export_cycle_files/foo.ng_deps.dart b/modules_dart/transform/test/transform/directive_metadata_extractor/export_cycle_files/foo.ng_deps.dart deleted file mode 100644 index 542f008d16..0000000000 --- a/modules_dart/transform/test/transform/directive_metadata_extractor/export_cycle_files/foo.ng_deps.dart +++ /dev/null @@ -1,19 +0,0 @@ -library foo.ng_deps.dart; - -import 'foo.dart'; -import 'package:angular2/src/core/metadata.dart'; - -export 'bar.dart'; -import 'bar.ng_deps.dart' as i0; - -var _visited = false; -void initReflector(reflector) { - if (_visited) return; - _visited = true; - reflector - ..registerType( - FooComponent, - new ReflectionInfo(const [const Component(selector: '[foo]')], const [], - () => new FooComponent())); - i0.initReflector(reflector); -} diff --git a/modules_dart/transform/test/transform/directive_metadata_linker/all_tests.dart b/modules_dart/transform/test/transform/directive_metadata_linker/all_tests.dart index 1afea9ec2a..3e8797c4b9 100644 --- a/modules_dart/transform/test/transform/directive_metadata_linker/all_tests.dart +++ b/modules_dart/transform/test/transform/directive_metadata_linker/all_tests.dart @@ -1,17 +1,14 @@ library angular2.test.transform.directive_metadata_linker.all_tests; -import 'dart:async'; -import 'package:angular2/src/core/render/api.dart'; -import 'package:angular2/src/core/change_detection/change_detection.dart'; -import 'package:angular2/src/transform/common/directive_metadata_reader.dart'; -import 'package:angular2/src/transform/common/logging.dart'; -import 'package:angular2/src/transform/common/ng_deps.dart'; -import 'package:angular2/src/transform/directive_metadata_linker/' - 'linker.dart'; +import 'dart:convert'; + +import 'package:angular2/src/transform/common/model/import_export_model.pb.dart'; +import 'package:angular2/src/transform/directive_metadata_linker/ng_meta_linker.dart'; import 'package:barback/barback.dart'; import 'package:dart_style/dart_style.dart'; import 'package:guinness/guinness.dart'; +import '../common/ng_meta_helper.dart'; import '../common/read_file.dart'; var formatter = new DartFormatter(); @@ -20,59 +17,148 @@ main() => allTests(); void allTests() { TestAssetReader reader = null; + final moduleBase = 'asset:a'; + var fooNgMeta, fooAssetId; + var barNgMeta, barAssetId; + var bazNgMeta, bazAssetId; + + /// Call after making changes to `fooNgMeta`, `barNgMeta`, or `bazNgMeta` and + /// before trying to read them from `reader`. + final updateReader = () => reader + ..addAsset(fooAssetId, JSON.encode(fooNgMeta.toJson())) + ..addAsset(barAssetId, JSON.encode(barNgMeta.toJson())) + ..addAsset(bazAssetId, JSON.encode(bazNgMeta.toJson())); beforeEach(() { reader = new TestAssetReader(); + + // Establish some test NgMeta objects with one Component each. + var fooName = 'FooComponent'; + var fooComponentMeta = createComponentMetadataForTest( + name: fooName, + moduleUrl: '$moduleBase/export_cycle_files/foo.dart', + selector: '[foo]', + template: 'Foo'); + fooNgMeta = new NgMeta(ngDeps: new NgDepsModel()); + fooNgMeta.types[fooName] = fooComponentMeta; + + var barName = 'BarComponent'; + var barComponentMeta = createComponentMetadataForTest( + name: barName, + moduleUrl: '$moduleBase/export_cycle_files/bar.dart', + selector: '[bar]', + template: 'Bar'); + barNgMeta = new NgMeta(ngDeps: new NgDepsModel()); + barNgMeta.types[barName] = barComponentMeta; + + var bazName = 'BazComponent'; + var bazComponentMeta = createComponentMetadataForTest( + name: bazName, + moduleUrl: '$moduleBase/export_cycle_files/baz.dart', + selector: '[baz]', + template: 'Baz'); + bazNgMeta = new NgMeta(ngDeps: new NgDepsModel()); + barNgMeta.types[bazName] = bazComponentMeta; + + fooAssetId = new AssetId('a', 'lib/foo.ng_meta.json'); + barAssetId = new AssetId('a', 'lib/bar.ng_meta.json'); + bazAssetId = new AssetId('a', 'lib/baz.ng_meta.json'); + updateReader(); }); - it('should include `DirectiveMetadata` from exported files.', () async { - var extracted = await linkDirectiveMetadata( - reader, - new AssetId( - 'a', 'directive_metadata_linker/export_files/foo.ng_meta.json')); - expect(extracted.types).toContain('FooComponent'); - expect(extracted.types).toContain('BarComponent'); + describe('NgMeta linker', () { + it('should include `DirectiveMetadata` from exported files.', () async { + fooNgMeta.ngDeps.exports.add(new ExportModel()..uri = 'bar.dart'); + updateReader(); - expect(extracted.types['FooComponent'].selector).toEqual('[foo]'); - expect(extracted.types['BarComponent'].selector).toEqual('[bar]'); + var extracted = await linkDirectiveMetadata(reader, fooAssetId); + expect(extracted.types).toContain('FooComponent'); + expect(extracted.types).toContain('BarComponent'); + + expect(extracted.types['FooComponent'].selector).toEqual('[foo]'); + expect(extracted.types['BarComponent'].selector).toEqual('[bar]'); + }); + + it('should include `DirectiveMetadata` recursively from exported files.', + () async { + fooNgMeta.ngDeps.exports.add(new ExportModel()..uri = 'bar.dart'); + barNgMeta.ngDeps.exports.add(new ExportModel()..uri = 'baz.dart'); + updateReader(); + + var extracted = await linkDirectiveMetadata(reader, fooAssetId); + expect(extracted.types).toContain('FooComponent'); + expect(extracted.types).toContain('BarComponent'); + expect(extracted.types).toContain('BazComponent'); + + expect(extracted.types['FooComponent'].selector).toEqual('[foo]'); + expect(extracted.types['BarComponent'].selector).toEqual('[bar]'); + expect(extracted.types['BazComponent'].selector).toEqual('[baz]'); + }); + + it('should handle `DirectiveMetadata` export cycles gracefully.', () async { + fooNgMeta.ngDeps.exports.add(new ExportModel()..uri = 'bar.dart'); + barNgMeta.ngDeps.exports.add(new ExportModel()..uri = 'baz.dart'); + bazNgMeta.ngDeps.exports.add(new ExportModel()..uri = 'foo.dart'); + updateReader(); + + var extracted = await linkDirectiveMetadata(reader, bazAssetId); + expect(extracted.types).toContain('FooComponent'); + expect(extracted.types).toContain('BarComponent'); + expect(extracted.types).toContain('BazComponent'); + }); + + it( + 'should include `DirectiveMetadata` from exported files ' + 'expressed as absolute uris', () async { + fooNgMeta.ngDeps.exports + .add(new ExportModel()..uri = 'package:bar/bar.dart'); + updateReader(); + reader.addAsset(new AssetId('bar', 'lib/bar.ng_meta.json'), + JSON.encode(barNgMeta.toJson())); + + var extracted = await linkDirectiveMetadata(reader, fooAssetId); + + expect(extracted.types).toContain('FooComponent'); + expect(extracted.types).toContain('BarComponent'); + + expect(extracted.types['FooComponent'].selector).toEqual('[foo]'); + expect(extracted.types['BarComponent'].selector).toEqual('[bar]'); + }); }); - it('should include `DirectiveMetadata` recursively from exported files.', - () async { - var extracted = await linkDirectiveMetadata( - reader, - new AssetId('a', - 'directive_metadata_linker/recursive_export_files/foo.ng_meta.json')); - expect(extracted.types).toContain('FooComponent'); - expect(extracted.types).toContain('BarComponent'); - expect(extracted.types).toContain('BazComponent'); + describe('NgDeps linker', () { + it('should chain imported dependencies.', () async { + fooNgMeta.ngDeps + ..libraryUri = 'test.foo' + ..imports.add(new ImportModel() + ..uri = 'bar.dart' + ..prefix = 'dep'); + barNgMeta.ngDeps.libraryUri = 'test.bar'; + updateReader(); - expect(extracted.types['FooComponent'].selector).toEqual('[foo]'); - expect(extracted.types['BarComponent'].selector).toEqual('[bar]'); - expect(extracted.types['BazComponent'].selector).toEqual('[baz]'); - }); + var linked = (await linkDirectiveMetadata(reader, fooAssetId)).ngDeps; + expect(linked).toBeNotNull(); + var linkedImport = + linked.imports.firstWhere((i) => i.uri.endsWith('bar.ng_deps.dart')); + expect(linkedImport).toBeNotNull(); + expect(linkedImport.isNgDeps).toBeTrue(); + expect(linkedImport.prefix.startsWith('i')).toBeTrue(); + }); - it('should handle `DirectiveMetadata` export cycles gracefully.', () async { - var extracted = await linkDirectiveMetadata( - reader, - new AssetId('a', - 'directive_metadata_linker/export_cycle_files/baz.ng_meta.json')); - expect(extracted.types).toContain('FooComponent'); - expect(extracted.types).toContain('BarComponent'); - expect(extracted.types).toContain('BazComponent'); - }); + it('should chain exported dependencies.', () async { + fooNgMeta.ngDeps + ..libraryUri = 'test.foo' + ..exports.add(new ExportModel()..uri = 'bar.dart'); + barNgMeta.ngDeps.libraryUri = 'test.bar'; + updateReader(); - it( - 'should include `DirectiveMetadata` from exported files ' - 'expressed as absolute uris', () async { - var extracted = await linkDirectiveMetadata( - reader, - new AssetId('a', - 'directive_metadata_linker/absolute_export_files/foo.ng_meta.json')); - expect(extracted.types).toContain('FooComponent'); - expect(extracted.types).toContain('BarComponent'); - - expect(extracted.types['FooComponent'].selector).toEqual('[foo]'); - expect(extracted.types['BarComponent'].selector).toEqual('[bar]'); + var linked = (await linkDirectiveMetadata(reader, fooAssetId)).ngDeps; + expect(linked).toBeNotNull(); + var linkedImport = + linked.imports.firstWhere((i) => i.uri.endsWith('bar.ng_deps.dart')); + expect(linkedImport).toBeNotNull(); + expect(linkedImport.isNgDeps).toBeTrue(); + expect(linkedImport.prefix.startsWith('i')).toBeTrue(); + }); }); } diff --git a/modules_dart/transform/test/transform/directive_processor/all_tests.dart b/modules_dart/transform/test/transform/directive_processor/all_tests.dart index b376d8b8d3..4b1d48c026 100644 --- a/modules_dart/transform/test/transform/directive_processor/all_tests.dart +++ b/modules_dart/transform/test/transform/directive_processor/all_tests.dart @@ -41,7 +41,7 @@ Expect _expectSelector(ReflectionInfoModel model) { void allTests() { it('should preserve parameter annotations.', () async { - var model = await _testCreateModel('parameter_metadata/soup.dart'); + var model = (await _testCreateModel('parameter_metadata/soup.dart')).ngDeps; expect(model.reflectables.length).toBe(1); var reflectable = model.reflectables.first; expect(reflectable.parameters.length).toBe(2); @@ -59,7 +59,8 @@ void allTests() { }); describe('part support', () { - var modelFuture = _testCreateModel('part_files/main.dart'); + var modelFuture = _testCreateModel('part_files/main.dart') + .then((ngMeta) => ngMeta != null ? ngMeta.ngDeps : null); it('should include directives from the part.', () async { var model = await modelFuture; @@ -79,56 +80,59 @@ void allTests() { }); it('should handle multiple `part` directives.', () async { - var model = await _testCreateModel('multiple_part_files/main.dart'); + var model = + (await _testCreateModel('multiple_part_files/main.dart')).ngDeps; expect(model.reflectables.length).toEqual(3); _expectSelector(model.reflectables.first).toEqual("'[part1]'"); _expectSelector(model.reflectables[1]).toEqual("'[part2]'"); _expectSelector(model.reflectables[2]).toEqual("'[main]'"); }); - it('should not generate .ng_deps.dart for `part` files.', () async { - var model = await _testCreateModel('part_files/part.dart'); - expect(model).toBeNull(); + it('should not generate anything for `part` files.', () async { + expect(await _testCreateModel('part_files/part.dart')).toBeNull(); }); }); describe('custom annotations', () { it('should be recognized from package: imports', () async { - var model = + var ngMeta = await _testCreateModel('custom_metadata/package_soup.dart', customDescriptors: [ const ClassDescriptor('Soup', 'package:soup/soup.dart', superClass: 'Component') ]); + var model = ngMeta.ngDeps; expect(model.reflectables.length).toEqual(1); expect(model.reflectables.first.name).toEqual('PackageSoup'); }); it('should be recognized from relative imports', () async { - var model = await _testCreateModel('custom_metadata/relative_soup.dart', + var ngMeta = await _testCreateModel('custom_metadata/relative_soup.dart', assetId: new AssetId('soup', 'lib/relative_soup.dart'), customDescriptors: [ const ClassDescriptor('Soup', 'package:soup/annotations/soup.dart', superClass: 'Component') ]); + var model = ngMeta.ngDeps; expect(model.reflectables.length).toEqual(1); expect(model.reflectables.first.name).toEqual('RelativeSoup'); }); it('should ignore annotations that are not imported', () async { - var model = + var ngMeta = await _testCreateModel('custom_metadata/bad_soup.dart', customDescriptors: [ const ClassDescriptor('Soup', 'package:soup/soup.dart', superClass: 'Component') ]); - expect(model).toBeNull(); + expect(ngMeta.ngDeps == null || ngMeta.ngDeps.reflectables.isEmpty) + .toBeTrue(); }); }); describe('interfaces', () { it('should include implemented types', () async { - var model = await _testCreateModel('interfaces_files/soup.dart'); + var model = (await _testCreateModel('interfaces_files/soup.dart')).ngDeps; expect(model.reflectables.first.interfaces).toBeNotNull(); expect(model.reflectables.first.interfaces.isNotEmpty).toBeTrue(); @@ -139,7 +143,8 @@ void allTests() { }); it('should not include transitively implemented types', () async { - var model = await _testCreateModel('interface_chain_files/soup.dart'); + var model = + (await _testCreateModel('interface_chain_files/soup.dart')).ngDeps; expect(model.reflectables.first.interfaces).toBeNotNull(); expect(model.reflectables.first.interfaces.isNotEmpty).toBeTrue(); @@ -152,15 +157,15 @@ void allTests() { }); it('should not include superclasses.', () async { - var model = await _testCreateModel('superclass_files/soup.dart'); + var model = (await _testCreateModel('superclass_files/soup.dart')).ngDeps; var interfaces = model.reflectables.first.interfaces; expect(interfaces == null || interfaces.isEmpty).toBeTrue(); }); it('should populate multiple `lifecycle` values when necessary.', () async { - var model = await _testCreateModel( - 'multiple_interface_lifecycle_files/soup.dart'); + var model = (await _testCreateModel( + 'multiple_interface_lifecycle_files/soup.dart')).ngDeps; expect(model.reflectables.first.interfaces).toBeNotNull(); expect(model.reflectables.first.interfaces.isNotEmpty).toBeTrue(); @@ -174,15 +179,16 @@ void allTests() { it('should not populate `lifecycle` when lifecycle superclass is present.', () async { var model = - await _testCreateModel('superclass_lifecycle_files/soup.dart'); + (await _testCreateModel('superclass_lifecycle_files/soup.dart')) + .ngDeps; var interfaces = model.reflectables.first.interfaces; expect(interfaces == null || interfaces.isEmpty).toBeTrue(); }); it('should populate `lifecycle` with prefix when necessary.', () async { - var model = await _testCreateModel( - 'prefixed_interface_lifecycle_files/soup.dart'); + var model = (await _testCreateModel( + 'prefixed_interface_lifecycle_files/soup.dart')).ngDeps; expect(model.reflectables.first.interfaces).toBeNotNull(); expect(model.reflectables.first.interfaces.isNotEmpty).toBeTrue(); expect(model.reflectables.first.interfaces @@ -193,7 +199,8 @@ void allTests() { describe('property metadata', () { it('should be recorded on fields', () async { - var model = await _testCreateModel('prop_metadata_files/fields.dart'); + var model = + (await _testCreateModel('prop_metadata_files/fields.dart')).ngDeps; expect(model.reflectables.first.propertyMetadata).toBeNotNull(); expect(model.reflectables.first.propertyMetadata.isNotEmpty).toBeTrue(); @@ -205,7 +212,8 @@ void allTests() { }); it('should be recorded on getters', () async { - var model = await _testCreateModel('prop_metadata_files/getters.dart'); + var model = + (await _testCreateModel('prop_metadata_files/getters.dart')).ngDeps; expect(model.reflectables.first.propertyMetadata).toBeNotNull(); expect(model.reflectables.first.propertyMetadata.isNotEmpty).toBeTrue(); @@ -221,7 +229,8 @@ void allTests() { it('should gracefully handle const instances of annotations', () async { // Regression test for i/4481 - var model = await _testCreateModel('prop_metadata_files/override.dart'); + var model = + (await _testCreateModel('prop_metadata_files/override.dart')).ngDeps; expect(model.reflectables.first.propertyMetadata).toBeNotNull(); expect(model.reflectables.first.propertyMetadata.isNotEmpty).toBeTrue(); @@ -240,7 +249,8 @@ void allTests() { }); it('should be recorded on setters', () async { - var model = await _testCreateModel('prop_metadata_files/setters.dart'); + var model = + (await _testCreateModel('prop_metadata_files/setters.dart')).ngDeps; expect(model.reflectables.first.propertyMetadata).toBeNotNull(); expect(model.reflectables.first.propertyMetadata.isNotEmpty).toBeTrue(); @@ -253,8 +263,8 @@ void allTests() { it('should be coalesced when getters and setters have the same name', () async { - var model = await _testCreateModel( - 'prop_metadata_files/getters_and_setters.dart'); + var model = (await _testCreateModel( + 'prop_metadata_files/getters_and_setters.dart')).ngDeps; expect(model.reflectables.first.propertyMetadata).toBeNotNull(); expect(model.reflectables.first.propertyMetadata.length).toBe(1); @@ -271,8 +281,7 @@ void allTests() { it('should not throw/hang on invalid urls', () async { var logger = new RecordingLogger(); - var model = - await _testCreateModel('invalid_url_files/hello.dart', logger: logger); + await _testCreateModel('invalid_url_files/hello.dart', logger: logger); expect(logger.hasErrors).toBeTrue(); expect(logger.logs) ..toContain('ERROR: ERROR: Invalid argument (url): ' @@ -280,7 +289,8 @@ void allTests() { }); it('should find and register static functions.', () async { - var model = await _testCreateModel('static_function_files/hello.dart'); + var model = + (await _testCreateModel('static_function_files/hello.dart')).ngDeps; var functionReflectable = model.reflectables.firstWhere((i) => i.isFunction, orElse: () => null); @@ -295,9 +305,7 @@ void allTests() { }); it('should find direcive aliases patterns.', () async { - var ngMeta = new NgMeta.empty(); - await _testCreateModel('directive_aliases_files/hello.dart', - ngMeta: ngMeta); + var ngMeta = await _testCreateModel('directive_aliases_files/hello.dart'); expect(ngMeta.aliases).toContain('alias1'); expect(ngMeta.aliases['alias1']).toContain('HelloCmp'); @@ -307,8 +315,7 @@ void allTests() { }); it('should include hooks for implemented types (single)', () async { - var ngMeta = new NgMeta.empty(); - await _testCreateModel('interfaces_files/soup.dart', ngMeta: ngMeta); + var ngMeta = await _testCreateModel('interfaces_files/soup.dart'); expect(ngMeta.types.isNotEmpty).toBeTrue(); expect(ngMeta.types['ChangingSoupComponent']).toBeNotNull(); @@ -318,9 +325,8 @@ void allTests() { }); it('should include hooks for implemented types (many)', () async { - var ngMeta = new NgMeta.empty(); - await _testCreateModel('multiple_interface_lifecycle_files/soup.dart', - ngMeta: ngMeta); + var ngMeta = await _testCreateModel( + 'multiple_interface_lifecycle_files/soup.dart'); expect(ngMeta.types.isNotEmpty).toBeTrue(); expect(ngMeta.types['MultiSoupComponent']).toBeNotNull(); @@ -335,9 +341,9 @@ void allTests() { fakeReader ..addAsset(new AssetId('other_package', 'lib/template.html'), '') ..addAsset(new AssetId('other_package', 'lib/template.css'), ''); - var ngMeta = new NgMeta.empty(); - await _testCreateModel('absolute_url_expression_files/hello.dart', - ngMeta: ngMeta, reader: fakeReader); + var ngMeta = await _testCreateModel( + 'absolute_url_expression_files/hello.dart', + reader: fakeReader); expect(ngMeta.types.isNotEmpty).toBeTrue(); expect(ngMeta.types['HelloCmp']).toBeNotNull(); @@ -346,9 +352,7 @@ void allTests() { it('should populate all provided values for Components & Directives', () async { - var ngMeta = new NgMeta.empty(); - await _testCreateModel('unusual_component_files/hello.dart', - ngMeta: ngMeta); + var ngMeta = await _testCreateModel('unusual_component_files/hello.dart'); expect(ngMeta.types.isNotEmpty).toBeTrue(); @@ -382,8 +386,7 @@ void allTests() { }); it('should include hooks for implemented types (single)', () async { - var ngMeta = new NgMeta.empty(); - await _testCreateModel('interfaces_files/soup.dart', ngMeta: ngMeta); + var ngMeta = await _testCreateModel('interfaces_files/soup.dart'); expect(ngMeta.types.isNotEmpty).toBeTrue(); expect(ngMeta.types['ChangingSoupComponent']).toBeNotNull(); @@ -393,9 +396,8 @@ void allTests() { }); it('should include hooks for implemented types (many)', () async { - var ngMeta = new NgMeta.empty(); - await _testCreateModel('multiple_interface_lifecycle_files/soup.dart', - ngMeta: ngMeta); + var ngMeta = await _testCreateModel( + 'multiple_interface_lifecycle_files/soup.dart'); expect(ngMeta.types.isNotEmpty).toBeTrue(); expect(ngMeta.types['MultiSoupComponent']).toBeNotNull(); @@ -410,9 +412,9 @@ void allTests() { fakeReader ..addAsset(new AssetId('other_package', 'lib/template.html'), '') ..addAsset(new AssetId('other_package', 'lib/template.css'), ''); - var ngMeta = new NgMeta.empty(); - await _testCreateModel('absolute_url_expression_files/hello.dart', - ngMeta: ngMeta, reader: fakeReader); + var ngMeta = await _testCreateModel( + 'absolute_url_expression_files/hello.dart', + reader: fakeReader); expect(ngMeta.types.isNotEmpty).toBeTrue(); expect(ngMeta.types['HelloCmp']).toBeNotNull(); @@ -423,12 +425,11 @@ void allTests() { }); } -Future _testCreateModel(String inputPath, +Future _testCreateModel(String inputPath, {List customDescriptors: const [], AssetId assetId, AssetReader reader, - BuildLogger logger, - NgMeta ngMeta}) { + BuildLogger logger}) { if (logger == null) logger = new RecordingLogger(); return log.setZoned(logger, () async { var inputId = _assetIdForPath(inputPath); @@ -439,12 +440,9 @@ Future _testCreateModel(String inputPath, reader.addAsset(assetId, await reader.readAsString(inputId)); inputId = assetId; } - if (ngMeta == null) { - ngMeta = new NgMeta.empty(); - } var annotationMatcher = new AnnotationMatcher()..addAll(customDescriptors); - return createNgDeps(reader, inputId, annotationMatcher, ngMeta); + return createNgDeps(reader, inputId, annotationMatcher); }); } diff --git a/modules_dart/transform/test/transform/integration/all_tests.dart b/modules_dart/transform/test/transform/integration/all_tests.dart index f7d72d43df..3970815697 100644 --- a/modules_dart/transform/test/transform/integration/all_tests.dart +++ b/modules_dart/transform/test/transform/integration/all_tests.dart @@ -114,24 +114,25 @@ void allTests() { new IntegrationTestConfig( 'should handle Directive depenedencies declared on a View.', inputs: { - 'a|web/index.dart': 'directive_dep_files/index.dart', - 'a|web/foo.dart': 'directive_dep_files/foo.dart', - 'a|web/bar.dart': 'directive_dep_files/bar.dart' - }, + 'a|web/index.dart': 'directive_dep_files/index.dart', + 'a|web/foo.dart': 'directive_dep_files/foo.dart', + 'a|web/bar.dart': 'directive_dep_files/bar.dart' + }, outputs: { - 'a|web/bar.ng_deps.dart': 'directive_dep_files/expected/bar.ng_deps.dart' - }), + 'a|web/bar.ng_deps.dart': 'directive_dep_files/expected/bar.ng_deps.dart' + }), new IntegrationTestConfig( 'should handle chained Directive dependencies declared on a View.', inputs: { - 'a|web/index.dart': 'directive_chain_files/index.dart', - 'a|web/foo.dart': 'directive_chain_files/foo.dart', - 'a|web/bar.dart': 'directive_chain_files/bar.dart', - 'a|web/baz.dart': 'directive_chain_files/baz.dart' - }, + 'a|web/index.dart': 'directive_chain_files/index.dart', + 'a|web/foo.dart': 'directive_chain_files/foo.dart', + 'a|web/bar.dart': 'directive_chain_files/bar.dart', + 'a|web/baz.dart': 'directive_chain_files/baz.dart' + }, outputs: { - 'a|web/bar.ng_deps.dart': 'directive_chain_files/expected/bar.ng_deps.dart' - }) + 'a|web/bar.ng_deps.dart': + 'directive_chain_files/expected/bar.ng_deps.dart' + }) ]; var cache = {}; @@ -160,8 +161,9 @@ void allTests() { ], config.assetPathToInputPath, config.assetPathToExpectedOutputPath, - [], - StringFormatter.noNewlinesOrSurroundingWhitespace); + []); +//, +// StringFormatter.noNewlinesOrSurroundingWhitespace); } } } diff --git a/modules_dart/transform/test/transform/integration/directive_chain_files/expected/bar.ng_deps.dart b/modules_dart/transform/test/transform/integration/directive_chain_files/expected/bar.ng_deps.dart index bd9e3cd5a9..9d0708b9a7 100644 --- a/modules_dart/transform/test/transform/integration/directive_chain_files/expected/bar.ng_deps.dart +++ b/modules_dart/transform/test/transform/integration/directive_chain_files/expected/bar.ng_deps.dart @@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates; import 'bar.dart'; import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef; import 'package:angular2/src/core/metadata.dart'; +import 'package:angular2/src/core/metadata.ng_deps.dart' as i0; import 'baz.dart'; import 'baz.ng_deps.dart' as i1; export 'bar.dart'; @@ -21,5 +22,6 @@ void initReflector() { const View(directives: [Foo], template: 'foo'), _templates.HostMyComponentTemplate ], const [], () => new MyComponent())); + i0.initReflector(); i1.initReflector(); } diff --git a/modules_dart/transform/test/transform/integration/directive_dep_files/expected/bar.ng_deps.dart b/modules_dart/transform/test/transform/integration/directive_dep_files/expected/bar.ng_deps.dart index f3dfffe012..44a4323d30 100644 --- a/modules_dart/transform/test/transform/integration/directive_dep_files/expected/bar.ng_deps.dart +++ b/modules_dart/transform/test/transform/integration/directive_dep_files/expected/bar.ng_deps.dart @@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates; import 'bar.dart'; import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef; import 'package:angular2/src/core/metadata.dart'; +import 'package:angular2/src/core/metadata.ng_deps.dart' as i0; import 'foo.dart' as prefix; import 'foo.ng_deps.dart' as i1; export 'bar.dart'; @@ -21,5 +22,6 @@ void initReflector() { const View(directives: [prefix.Foo], template: 'foo'), _templates.HostMyComponentTemplate ], const [], () => new MyComponent())); + i0.initReflector(); i1.initReflector(); } diff --git a/modules_dart/transform/test/transform/integration/event_getter_files/expected/bar.ng_deps.dart b/modules_dart/transform/test/transform/integration/event_getter_files/expected/bar.ng_deps.dart index e9a9df751b..064b1d566c 100644 --- a/modules_dart/transform/test/transform/integration/event_getter_files/expected/bar.ng_deps.dart +++ b/modules_dart/transform/test/transform/integration/event_getter_files/expected/bar.ng_deps.dart @@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates; import 'bar.dart'; import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef; import 'package:angular2/src/core/metadata.dart'; +import 'package:angular2/src/core/metadata.ng_deps.dart' as i0; export 'bar.dart'; var _visited = false; @@ -23,4 +24,5 @@ void initReflector() { ], const [], () => new MyComponent())) ..registerGetters( {'eventName1': (o) => o.eventName1, 'eventName2': (o) => o.eventName2}); + i0.initReflector(); } diff --git a/modules_dart/transform/test/transform/integration/list_of_types_files/expected/bar.ng_deps.dart b/modules_dart/transform/test/transform/integration/list_of_types_files/expected/bar.ng_deps.dart index 2fa6fe61f0..d56847d471 100644 --- a/modules_dart/transform/test/transform/integration/list_of_types_files/expected/bar.ng_deps.dart +++ b/modules_dart/transform/test/transform/integration/list_of_types_files/expected/bar.ng_deps.dart @@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates; import 'bar.dart'; import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef; import 'package:angular2/src/core/metadata.dart'; +import 'package:angular2/src/core/metadata.ng_deps.dart' as i0; import 'foo.dart'; export 'bar.dart'; @@ -22,4 +23,5 @@ void initReflector() { ], const [ const [MyContext] ], (MyContext c) => new MyComponent(c))); + i0.initReflector(); } diff --git a/modules_dart/transform/test/transform/integration/simple_annotation_files/expected/bar.ng_deps.dart b/modules_dart/transform/test/transform/integration/simple_annotation_files/expected/bar.ng_deps.dart index 6cd5eef3f8..b207b8263a 100644 --- a/modules_dart/transform/test/transform/integration/simple_annotation_files/expected/bar.ng_deps.dart +++ b/modules_dart/transform/test/transform/integration/simple_annotation_files/expected/bar.ng_deps.dart @@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates; import 'bar.dart'; import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef; import 'package:angular2/src/core/metadata.dart'; +import 'package:angular2/src/core/metadata.ng_deps.dart' as i0; export 'bar.dart'; var _visited = false; @@ -19,4 +20,5 @@ void initReflector() { const View(template: ''), _templates.HostMyComponentTemplate ], const [], () => new MyComponent())); + i0.initReflector(); } diff --git a/modules_dart/transform/test/transform/integration/simple_annotation_files/expected/index.ng_deps.dart b/modules_dart/transform/test/transform/integration/simple_annotation_files/expected/index.ng_deps.dart index 4230272bd1..77b09d94d5 100644 --- a/modules_dart/transform/test/transform/integration/simple_annotation_files/expected/index.ng_deps.dart +++ b/modules_dart/transform/test/transform/integration/simple_annotation_files/expected/index.ng_deps.dart @@ -4,6 +4,7 @@ import 'index.dart'; import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef; import 'package:angular2/bootstrap_static.dart'; import 'index.ng_deps.dart' as ngStaticInit; +import 'index.ng_deps.dart' as i1; import 'package:angular2/src/core/reflection/reflection.dart'; import 'bar.dart'; import 'bar.ng_deps.dart' as i3; @@ -13,5 +14,6 @@ var _visited = false; void initReflector() { if (_visited) return; _visited = true; + i1.initReflector(); i3.initReflector(); } diff --git a/modules_dart/transform/test/transform/integration/synthetic_ctor_files/expected/bar.ng_deps.dart b/modules_dart/transform/test/transform/integration/synthetic_ctor_files/expected/bar.ng_deps.dart index 6cd5eef3f8..b207b8263a 100644 --- a/modules_dart/transform/test/transform/integration/synthetic_ctor_files/expected/bar.ng_deps.dart +++ b/modules_dart/transform/test/transform/integration/synthetic_ctor_files/expected/bar.ng_deps.dart @@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates; import 'bar.dart'; import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef; import 'package:angular2/src/core/metadata.dart'; +import 'package:angular2/src/core/metadata.ng_deps.dart' as i0; export 'bar.dart'; var _visited = false; @@ -19,4 +20,5 @@ void initReflector() { const View(template: ''), _templates.HostMyComponentTemplate ], const [], () => new MyComponent())); + i0.initReflector(); } diff --git a/modules_dart/transform/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart b/modules_dart/transform/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart index 61984d138a..d79cf710ea 100644 --- a/modules_dart/transform/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart +++ b/modules_dart/transform/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart @@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates; import 'bar.dart'; import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef; import 'package:angular2/src/core/metadata.dart'; +import 'package:angular2/src/core/metadata.ng_deps.dart' as i0; export 'bar.dart'; var _visited = false; @@ -19,4 +20,5 @@ void initReflector() { const View(template: 'Salad: {{myNum}} is awesome'), _templates.HostMyComponentTemplate ], const [], () => new MyComponent())); + i0.initReflector(); } diff --git a/modules_dart/transform/test/transform/integration/two_deps_files/expected/bar.ng_deps.dart b/modules_dart/transform/test/transform/integration/two_deps_files/expected/bar.ng_deps.dart index 7c26127e08..43957ed8e2 100644 --- a/modules_dart/transform/test/transform/integration/two_deps_files/expected/bar.ng_deps.dart +++ b/modules_dart/transform/test/transform/integration/two_deps_files/expected/bar.ng_deps.dart @@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates; import 'bar.dart'; import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef; import 'package:angular2/src/core/metadata.dart'; +import 'package:angular2/src/core/metadata.ng_deps.dart' as i0; import 'foo.dart' as prefix; export 'bar.dart'; @@ -27,4 +28,5 @@ void initReflector() { ], (prefix.MyContext c, String inValue) => new MyComponent(c, inValue))); + i0.initReflector(); } diff --git a/modules_dart/transform/test/transform/transform.server.spec.dart b/modules_dart/transform/test/transform/transform.server.spec.dart index 1e6dd6e13b..aacd4e3f72 100644 --- a/modules_dart/transform/test/transform/transform.server.spec.dart +++ b/modules_dart/transform/test/transform/transform.server.spec.dart @@ -6,9 +6,9 @@ import 'package:unittest/vm_config.dart'; import 'common/async_string_writer_tests.dart' as asyncStringWriter; import 'common/ng_meta_test.dart' as ngMetaTest; +import 'common/url_resolver_tests.dart' as urlResolver; import 'bind_generator/all_tests.dart' as bindGenerator; import 'deferred_rewriter/all_tests.dart' as deferredRewriter; -import 'directive_linker/all_tests.dart' as directiveLinker; import 'directive_metadata_linker/all_tests.dart' as directiveMeta; import 'directive_processor/all_tests.dart' as directiveProcessor; import 'inliner_for_test/all_tests.dart' as inliner; @@ -22,7 +22,6 @@ main() { describe('AsyncStringWriter', asyncStringWriter.allTests); describe('NgMeta', ngMetaTest.allTests); describe('Bind Generator', bindGenerator.allTests); - describe('Directive Linker', directiveLinker.allTests); describe('Directive Metadata Linker', directiveMeta.allTests); describe('Directive Processor', directiveProcessor.allTests); describe('Inliner For Test', inliner.allTests); @@ -30,6 +29,7 @@ main() { describe('Template Compiler', templateCompiler.allTests); describe('Deferred Rewriter', deferredRewriter.allTests); describe('Stylesheet Compiler', stylesheetCompiler.allTests); + describe('Url Resolver', urlResolver.allTests); // NOTE(kegluneq): These use `code_transformers#testPhases`, which is not // designed to work with `guinness`. group('Transformer Pipeline', integration.allTests);