refactor(dart/transform): Compose NgDepsModel & NgMeta phases
Link `NgDeps` & `NgMeta` data in the same phase to avoid unnecessary asset creation & reading. Remove `NgMeta#exports` and instead use `NgDeps#exports` to link `NgMeta` files in `ng_meta_linker.dart`.
This commit is contained in:
parent
75187d605b
commit
4ac29621f4
@ -8,16 +8,17 @@ import 'package:path/path.dart' as path;
|
|||||||
/// If `fromAbsolute` is specified, `importPath` may be a relative path,
|
/// If `fromAbsolute` is specified, `importPath` may be a relative path,
|
||||||
/// otherwise it is expected to be absolute.
|
/// otherwise it is expected to be absolute.
|
||||||
String writeImportUri(String importPath, {String prefix, String fromAbsolute}) {
|
String writeImportUri(String importPath, {String prefix, String fromAbsolute}) {
|
||||||
|
var urlResolver = const TransformerUrlResolver();
|
||||||
var codegenImportPath;
|
var codegenImportPath;
|
||||||
|
|
||||||
var resolver = const TransformerUrlResolver();
|
var importUri =
|
||||||
var importUri = resolver.toAssetScheme(Uri.parse(importPath));
|
toAssetScheme(Uri.parse(urlResolver.resolve(fromAbsolute, importPath)));
|
||||||
if (_canPackageImport(importUri) ||
|
if (_canPackageImport(importUri) ||
|
||||||
fromAbsolute == null ||
|
fromAbsolute == null ||
|
||||||
fromAbsolute.isEmpty) {
|
fromAbsolute.isEmpty) {
|
||||||
codegenImportPath = _toPackageImport(importUri);
|
codegenImportPath = _toPackageImport(importUri);
|
||||||
} else {
|
} else {
|
||||||
var moduleUri = resolver.toAssetScheme(Uri.parse(fromAbsolute));
|
var moduleUri = toAssetScheme(Uri.parse(fromAbsolute));
|
||||||
if (_canImportRelative(importUri, from: moduleUri)) {
|
if (_canImportRelative(importUri, from: moduleUri)) {
|
||||||
codegenImportPath = path.url.relative(importUri.toString(),
|
codegenImportPath = path.url.relative(importUri.toString(),
|
||||||
from: path.dirname(moduleUri.toString()));
|
from: path.dirname(moduleUri.toString()));
|
||||||
|
@ -2,74 +2,123 @@ library angular2.transform.common.ng_meta;
|
|||||||
|
|
||||||
import 'package:angular2/src/core/compiler/directive_metadata.dart';
|
import 'package:angular2/src/core/compiler/directive_metadata.dart';
|
||||||
import 'logging.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
|
/// [NgMeta] is used in three stages of the transformation process:
|
||||||
/// store directive aliases exported from a single file in an [NgMeta] instance.
|
|
||||||
/// Later we use another [NgMeta] instance to store more information about a
|
|
||||||
/// single file, including both directive aliases and directives extracted from
|
|
||||||
/// the corresponding `.ng_deps.dart` file. Further down the compilation
|
|
||||||
/// process, the template compiler needs to reason about the namespace of import
|
|
||||||
/// prefixes, so it will combine multple [NgMeta] instances together if they
|
|
||||||
/// were imported into a file with the same prefix.
|
|
||||||
///
|
///
|
||||||
/// Instances of this class are serialized into `.aliases.json` and
|
/// First we store directive aliases and types exported directly (that is, not
|
||||||
/// `.ng_meta.json` files as intermediate assets to make the compilation process
|
/// via an `export` statement) from a single file in an [NgMeta] instance.
|
||||||
/// easier.
|
///
|
||||||
|
/// 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 {
|
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.
|
/// Directive metadata for each type annotated as a directive.
|
||||||
final Map<String, CompileDirectiveMetadata> types;
|
final Map<String, CompileDirectiveMetadata> types;
|
||||||
|
|
||||||
/// List of other types and names associated with a given name.
|
/// List of other types and names associated with a given name.
|
||||||
final Map<String, List<String>> aliases;
|
final Map<String, List<String>> aliases;
|
||||||
|
|
||||||
/// TODO(kegluneq): Once merged with NgDepsModel, use its exports.
|
// The NgDeps generated from
|
||||||
final List<String> exports;
|
final NgDepsModel ngDeps;
|
||||||
|
|
||||||
NgMeta(this.types, this.aliases, this.exports);
|
NgMeta(
|
||||||
|
{Map<String, CompileDirectiveMetadata> types,
|
||||||
|
Map<String, List<String>> 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].
|
/// Parse from the serialized form produced by [toJson].
|
||||||
factory NgMeta.fromJson(Map json) {
|
factory NgMeta.fromJson(Map json) {
|
||||||
var exports = <String>[];
|
var ngDeps = null;
|
||||||
var types = {};
|
final types = {};
|
||||||
var aliases = {};
|
final aliases = {};
|
||||||
for (var key in json.keys) {
|
for (var key in json.keys) {
|
||||||
if (key == '__exports__') {
|
if (key == _NG_DEPS_KEY) {
|
||||||
exports = json[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 {
|
} else {
|
||||||
var entry = json[key];
|
var entry = json[key];
|
||||||
if (entry['kind'] == 'type') {
|
if (entry is! Map) {
|
||||||
types[key] = CompileDirectiveMetadata.fromJson(entry['value']);
|
logger.warning('Unexpected value $entry for key "$key" in NgMeta.');
|
||||||
} else if (entry['kind'] == 'alias') {
|
continue;
|
||||||
aliases[key] = entry['value'];
|
}
|
||||||
|
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.
|
/// Serialized representation of this instance.
|
||||||
Map toJson() {
|
Map toJson({bool withNgDeps: true}) {
|
||||||
var result = {};
|
var result = {};
|
||||||
result['__exports__'] = exports;
|
if (withNgDeps) {
|
||||||
|
result[_NG_DEPS_KEY] = isNgDepsEmpty ? null : ngDeps.writeToJsonMap();
|
||||||
|
}
|
||||||
|
|
||||||
types.forEach((k, v) {
|
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) {
|
aliases.forEach((k, v) {
|
||||||
result[k] = {'kind': 'alias', 'value': v};
|
result[k] = {_KIND_KEY: _ALIAS_VALUE, _VALUE_KEY: v};
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Merge into this instance all information from [other].
|
/// Merge into this instance all information from [other].
|
||||||
/// This does not include `exports`.
|
/// This does not include `ngDeps`.
|
||||||
void addAll(NgMeta other) {
|
void addAll(NgMeta other) {
|
||||||
types.addAll(other.types);
|
types.addAll(other.types);
|
||||||
aliases.addAll(other.aliases);
|
aliases.addAll(other.aliases);
|
||||||
|
@ -5,9 +5,6 @@ import 'package:glob/glob.dart';
|
|||||||
import 'annotation_matcher.dart';
|
import 'annotation_matcher.dart';
|
||||||
import 'mirror_mode.dart';
|
import 'mirror_mode.dart';
|
||||||
|
|
||||||
/// See `optimizationPhases` below for an explanation.
|
|
||||||
const DEFAULT_OPTIMIZATION_PHASES = 5;
|
|
||||||
|
|
||||||
const CUSTOM_ANNOTATIONS_PARAM = 'custom_annotations';
|
const CUSTOM_ANNOTATIONS_PARAM = 'custom_annotations';
|
||||||
const ENTRY_POINT_PARAM = 'entry_points';
|
const ENTRY_POINT_PARAM = 'entry_points';
|
||||||
const FORMAT_CODE_PARAM = 'format_code';
|
const FORMAT_CODE_PARAM = 'format_code';
|
||||||
@ -41,15 +38,6 @@ class TransformerOptions {
|
|||||||
|
|
||||||
final bool reflectPropertiesAsAttributes;
|
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.
|
/// Whether to format generated code.
|
||||||
/// Code that is only modified will never be formatted because doing so may
|
/// Code that is only modified will never be formatted because doing so may
|
||||||
/// invalidate the source maps generated by `dart2js` and/or other tools.
|
/// invalidate the source maps generated by `dart2js` and/or other tools.
|
||||||
@ -62,7 +50,6 @@ class TransformerOptions {
|
|||||||
this.mirrorMode,
|
this.mirrorMode,
|
||||||
this.initReflector,
|
this.initReflector,
|
||||||
this.annotationMatcher,
|
this.annotationMatcher,
|
||||||
this.optimizationPhases,
|
|
||||||
{this.reflectPropertiesAsAttributes,
|
{this.reflectPropertiesAsAttributes,
|
||||||
this.formatCode});
|
this.formatCode});
|
||||||
|
|
||||||
@ -71,24 +58,16 @@ class TransformerOptions {
|
|||||||
MirrorMode mirrorMode: MirrorMode.none,
|
MirrorMode mirrorMode: MirrorMode.none,
|
||||||
bool initReflector: true,
|
bool initReflector: true,
|
||||||
List<ClassDescriptor> customAnnotationDescriptors: const [],
|
List<ClassDescriptor> customAnnotationDescriptors: const [],
|
||||||
int optimizationPhases: DEFAULT_OPTIMIZATION_PHASES,
|
|
||||||
bool inlineViews: true,
|
bool inlineViews: true,
|
||||||
bool reflectPropertiesAsAttributes: true,
|
bool reflectPropertiesAsAttributes: true,
|
||||||
bool formatCode: false}) {
|
bool formatCode: false}) {
|
||||||
var annotationMatcher = new AnnotationMatcher()
|
var annotationMatcher = new AnnotationMatcher()
|
||||||
..addAll(customAnnotationDescriptors);
|
..addAll(customAnnotationDescriptors);
|
||||||
optimizationPhases = optimizationPhases.isNegative ? 0 : optimizationPhases;
|
|
||||||
var entryPointGlobs = entryPoints != null
|
var entryPointGlobs = entryPoints != null
|
||||||
? entryPoints.map((path) => new Glob(path)).toList(growable: false)
|
? entryPoints.map((path) => new Glob(path)).toList(growable: false)
|
||||||
: null;
|
: null;
|
||||||
return new TransformerOptions._internal(
|
return new TransformerOptions._internal(entryPoints, entryPointGlobs,
|
||||||
entryPoints,
|
modeName, mirrorMode, initReflector, annotationMatcher,
|
||||||
entryPointGlobs,
|
|
||||||
modeName,
|
|
||||||
mirrorMode,
|
|
||||||
initReflector,
|
|
||||||
annotationMatcher,
|
|
||||||
optimizationPhases,
|
|
||||||
reflectPropertiesAsAttributes: reflectPropertiesAsAttributes,
|
reflectPropertiesAsAttributes: reflectPropertiesAsAttributes,
|
||||||
formatCode: formatCode);
|
formatCode: formatCode);
|
||||||
}
|
}
|
||||||
|
@ -28,14 +28,11 @@ TransformerOptions parseBarbackSettings(BarbackSettings settings) {
|
|||||||
mirrorMode = MirrorMode.none;
|
mirrorMode = MirrorMode.none;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var optimizationPhases = _readInt(config, OPTIMIZATION_PHASES_PARAM,
|
|
||||||
defaultValue: DEFAULT_OPTIMIZATION_PHASES);
|
|
||||||
return new TransformerOptions(entryPoints,
|
return new TransformerOptions(entryPoints,
|
||||||
modeName: settings.mode.name,
|
modeName: settings.mode.name,
|
||||||
mirrorMode: mirrorMode,
|
mirrorMode: mirrorMode,
|
||||||
initReflector: initReflector,
|
initReflector: initReflector,
|
||||||
customAnnotationDescriptors: _readCustomAnnotations(config),
|
customAnnotationDescriptors: _readCustomAnnotations(config),
|
||||||
optimizationPhases: optimizationPhases,
|
|
||||||
reflectPropertiesAsAttributes: reflectPropertiesAsAttributes,
|
reflectPropertiesAsAttributes: reflectPropertiesAsAttributes,
|
||||||
formatCode: formatCode);
|
formatCode: formatCode);
|
||||||
}
|
}
|
||||||
@ -68,18 +65,6 @@ List<String> _readFileList(Map config, String paramName) {
|
|||||||
return files;
|
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
|
/// Parse the [CUSTOM_ANNOTATIONS_PARAM] options out of the transformer into
|
||||||
/// [ClassDescriptor]s.
|
/// [ClassDescriptor]s.
|
||||||
List<ClassDescriptor> _readCustomAnnotations(Map config) {
|
List<ClassDescriptor> _readCustomAnnotations(Map config) {
|
||||||
|
@ -1,57 +1,83 @@
|
|||||||
library angular2.transform.template_compiler.url_resolver;
|
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 {
|
class TransformerUrlResolver implements UrlResolver {
|
||||||
const TransformerUrlResolver();
|
const TransformerUrlResolver();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String resolve(String baseUrl, String url) {
|
String resolve(String baseUrl, String url) {
|
||||||
|
if (url == null) throw new ArgumentError.notNull('url');
|
||||||
Uri uri = Uri.parse(url);
|
Uri uri = Uri.parse(url);
|
||||||
|
|
||||||
if (!uri.isAbsolute) {
|
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);
|
uri = Uri.parse(baseUrl).resolveUri(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
return toAssetScheme(uri).toString();
|
return toAssetScheme(uri).toString();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Converts `absoluteUri` to use the 'asset' scheme used in the Angular 2
|
String toAssetUri(AssetId assetId) {
|
||||||
/// template compiler.
|
if (assetId == null) throw new ArgumentError.notNull('assetId');
|
||||||
///
|
return 'asset:${assetId.package}/${assetId.path}';
|
||||||
/// The `scheme` of `absoluteUri` is expected to be either 'package' or
|
}
|
||||||
/// 'asset'.
|
|
||||||
Uri toAssetScheme(Uri absoluteUri) {
|
|
||||||
if (absoluteUri == null) return null;
|
|
||||||
|
|
||||||
if (!absoluteUri.isAbsolute) {
|
AssetId fromUri(String assetUri) {
|
||||||
throw new ArgumentError.value(
|
if (assetUri == null) throw new ArgumentError.notNull('assetUri');
|
||||||
absoluteUri, 'absoluteUri', 'Value passed must be an absolute uri');
|
if (assetUri.isEmpty) throw new ArgumentError.value(
|
||||||
}
|
'(empty string)', 'assetUri');
|
||||||
if (absoluteUri.scheme == 'asset') {
|
var uri = toAssetScheme(Uri.parse(assetUri));
|
||||||
if (absoluteUri.pathSegments.length < 3) {
|
return new AssetId(
|
||||||
throw new FormatException(
|
uri.pathSegments.first, uri.pathSegments.skip(1).join('/'));
|
||||||
'An asset: URI must have at least 3 path '
|
}
|
||||||
'segments, for example '
|
|
||||||
'asset:<package-name>/<first-level-dir>/<path-to-dart-file>.',
|
|
||||||
absoluteUri);
|
|
||||||
}
|
|
||||||
return absoluteUri;
|
|
||||||
}
|
|
||||||
if (absoluteUri.scheme != 'package') {
|
|
||||||
throw new ArgumentError.value(
|
|
||||||
absoluteUri, 'absoluteUri', 'Unsupported URI scheme encountered');
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
throw new FormatException(
|
||||||
'A package: URI must have at least 2 path '
|
'An asset: URI must have at least 3 path '
|
||||||
'segments, for example '
|
'segments, for example '
|
||||||
'package:<package-name>/<path-to-dart-file>',
|
'asset:<package-name>/<first-level-dir>/<path-to-dart-file>.',
|
||||||
absoluteUri);
|
absoluteUri);
|
||||||
}
|
}
|
||||||
|
return absoluteUri;
|
||||||
var pathSegments = absoluteUri.pathSegments.toList()..insert(1, 'lib');
|
|
||||||
return new Uri(scheme: 'asset', pathSegments: pathSegments);
|
|
||||||
}
|
}
|
||||||
|
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:<package-name>/<path-to-dart-file>',
|
||||||
|
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:');
|
||||||
}
|
}
|
||||||
|
@ -3,20 +3,25 @@ library angular2.transform.template_compiler.xhr_impl;
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:angular2/src/core/compiler/xhr.dart' show XHR;
|
import 'package:angular2/src/core/compiler/xhr.dart' show XHR;
|
||||||
import 'package:angular2/src/transform/common/asset_reader.dart';
|
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 {
|
class XhrImpl implements XHR {
|
||||||
final AssetReader _reader;
|
final AssetReader _reader;
|
||||||
|
|
||||||
XhrImpl(this._reader);
|
XhrImpl(this._reader);
|
||||||
|
|
||||||
Future<String> get(String url) async {
|
Future<String> get(String url) async {
|
||||||
final uri = Uri.parse(url);
|
final assetId = fromUri(url);
|
||||||
if (uri.scheme != 'asset') {
|
if (!url.startsWith('asset:')) {
|
||||||
throw new FormatException('Unsupported uri encountered: $uri', url);
|
logger.warning('XhrImpl received unexpected url: $url');
|
||||||
}
|
}
|
||||||
final assetId =
|
|
||||||
new AssetId(uri.pathSegments.first, uri.pathSegments.skip(1).join('/'));
|
|
||||||
|
|
||||||
if (!await _reader.hasInput(assetId)) {
|
if (!await _reader.hasInput(assetId)) {
|
||||||
throw new ArgumentError.value('Could not read asset at uri $url', 'url');
|
throw new ArgumentError.value('Could not read asset at uri $url', 'url');
|
||||||
|
@ -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<bool> 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<NgDepsModel> 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<Map<String, String>> _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 = <String, String>{};
|
|
||||||
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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<NgMeta> linkDirectiveMetadata(AssetReader reader, AssetId entryPoint) {
|
|
||||||
return _linkDirectiveMetadataRecursive(
|
|
||||||
reader, entryPoint, new Set<AssetId>());
|
|
||||||
}
|
|
||||||
|
|
||||||
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<NgMeta> _linkDirectiveMetadataRecursive(
|
|
||||||
AssetReader reader, AssetId entryPoint, Set<AssetId> 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);
|
|
||||||
}
|
|
@ -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<NgDepsModel> 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<Map<String, String>> _processNgImports(NgDepsModel model,
|
||||||
|
AssetReader reader, AssetId assetId, UrlResolver resolver) async {
|
||||||
|
final importsAndExports = new List.from(model.imports)..addAll(model.exports);
|
||||||
|
final retVal = <String, String>{};
|
||||||
|
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);
|
||||||
|
}
|
@ -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<NgMeta> 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<String>())
|
||||||
|
]);
|
||||||
|
return ngMeta;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<NgMeta> _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<NgMeta> _linkDirectiveMetadataRecursive(NgMeta ngMeta,
|
||||||
|
AssetReader reader, AssetId assetId, Set<String> 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);
|
||||||
|
}
|
@ -4,11 +4,13 @@ import 'dart:async';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:angular2/src/transform/common/asset_reader.dart';
|
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/logging.dart' as log;
|
||||||
import 'package:angular2/src/transform/common/names.dart';
|
import 'package:angular2/src/transform/common/names.dart';
|
||||||
import 'package:barback/barback.dart';
|
import 'package:barback/barback.dart';
|
||||||
|
|
||||||
import 'linker.dart';
|
import 'ng_meta_linker.dart';
|
||||||
|
|
||||||
/// Transformer responsible for processing .ng_meta.json files created by
|
/// Transformer responsible for processing .ng_meta.json files created by
|
||||||
/// {@link DirectiveProcessor} and "linking" them.
|
/// {@link DirectiveProcessor} and "linking" them.
|
||||||
@ -31,6 +33,7 @@ class DirectiveMetadataLinker extends Transformer
|
|||||||
// incorrectly determine what assets are available in this phase.
|
// incorrectly determine what assets are available in this phase.
|
||||||
// transform.consumePrimary();
|
// transform.consumePrimary();
|
||||||
transform.declareOutput(transform.primaryId);
|
transform.declareOutput(transform.primaryId);
|
||||||
|
transform.declareOutput(_depsAssetId(transform.primaryId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -42,15 +45,32 @@ class DirectiveMetadataLinker extends Transformer
|
|||||||
new AssetReader.fromTransform(transform), primaryId).then((ngMeta) {
|
new AssetReader.fromTransform(transform), primaryId).then((ngMeta) {
|
||||||
// See above
|
// See above
|
||||||
// transform.consumePrimary();
|
// transform.consumePrimary();
|
||||||
if (ngMeta != null && !ngMeta.isEmpty) {
|
if (ngMeta != null) {
|
||||||
transform.addOutput(new Asset.fromString(
|
if (!ngMeta.types.isEmpty || !ngMeta.aliases.isEmpty) {
|
||||||
primaryId, _encoder.convert(ngMeta.toJson())));
|
transform.addOutput(new Asset.fromString(
|
||||||
} else {
|
primaryId, _encoder.convert(ngMeta.toJson(withNgDeps: false))));
|
||||||
// Not outputting an asset could confuse barback, so output an
|
} else {
|
||||||
// empty one.
|
// Not outputting an asset could confuse barback.
|
||||||
transform.addOutput(transform.primaryInput);
|
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));
|
||||||
|
@ -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/directive_metadata_reader.dart';
|
||||||
import 'package:angular2/src/transform/common/interface_matcher.dart';
|
import 'package:angular2/src/transform/common/interface_matcher.dart';
|
||||||
import 'package:angular2/src/transform/common/logging.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_compiler.dart';
|
||||||
import 'package:angular2/src/transform/common/ng_meta.dart';
|
import 'package:angular2/src/transform/common/ng_meta.dart';
|
||||||
import 'package:barback/barback.dart' show AssetId;
|
import 'package:barback/barback.dart' show AssetId;
|
||||||
@ -17,26 +16,20 @@ import 'package:angular2/src/core/compiler/template_compiler.dart';
|
|||||||
|
|
||||||
import 'inliner.dart';
|
import 'inliner.dart';
|
||||||
|
|
||||||
/// Generates a file registering all Angular 2 `Directive`s found in `code` in
|
/// Generates an instance of [NgMeta] describing the file at `assetId`.
|
||||||
/// ngDeps format [TODO(kegluneq): documentation reference needed]. `assetId` is
|
Future<NgMeta> createNgDeps(AssetReader reader, AssetId assetId,
|
||||||
/// the id of the asset containing `code`.
|
AnnotationMatcher annotationMatcher) async {
|
||||||
///
|
|
||||||
/// 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<NgDepsModel> createNgDeps(AssetReader reader, AssetId assetId,
|
|
||||||
AnnotationMatcher annotationMatcher, NgMeta ngMeta) async {
|
|
||||||
// TODO(kegluneq): Shortcut if we can determine that there are no
|
// TODO(kegluneq): Shortcut if we can determine that there are no
|
||||||
// [Directive]s present, taking into account `export`s.
|
// [Directive]s present, taking into account `export`s.
|
||||||
var codeWithParts = await inlineParts(reader, assetId);
|
var codeWithParts = await inlineParts(reader, assetId);
|
||||||
if (codeWithParts == null || codeWithParts.isEmpty) return null;
|
if (codeWithParts == null || codeWithParts.isEmpty) return null;
|
||||||
|
|
||||||
var parsedCode =
|
var parsedCode =
|
||||||
parseCompilationUnit(codeWithParts, name: '${assetId.path} and parts');
|
parseCompilationUnit(codeWithParts, name: '${assetId.path} and parts');
|
||||||
|
|
||||||
var ngDepsVisitor = new NgDepsVisitor(assetId, annotationMatcher);
|
var ngDepsVisitor = new NgDepsVisitor(assetId, annotationMatcher);
|
||||||
parsedCode.accept(ngDepsVisitor);
|
parsedCode.accept(ngDepsVisitor);
|
||||||
var ngDepsModel = ngDepsVisitor.model;
|
|
||||||
|
var ngMeta = new NgMeta(ngDeps: ngDepsVisitor.model);
|
||||||
|
|
||||||
var templateCompiler = createTemplateCompiler(reader);
|
var templateCompiler = createTemplateCompiler(reader);
|
||||||
var ngMetaVisitor = new _NgMetaVisitor(
|
var ngMetaVisitor = new _NgMetaVisitor(
|
||||||
@ -44,21 +37,9 @@ Future<NgDepsModel> createNgDeps(AssetReader reader, AssetId assetId,
|
|||||||
parsedCode.accept(ngMetaVisitor);
|
parsedCode.accept(ngMetaVisitor);
|
||||||
await ngMetaVisitor.whenDone();
|
await ngMetaVisitor.whenDone();
|
||||||
|
|
||||||
// If this file imports only dart: libraries and does not define any
|
return ngMeta;
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// `model` can be an [ImportModel] or [ExportModel].
|
|
||||||
bool _isDartImport(dynamic model) => model.uri.startsWith('dart:');
|
|
||||||
|
|
||||||
// TODO(kegluneq): Allow the caller to provide an InterfaceMatcher.
|
// TODO(kegluneq): Allow the caller to provide an InterfaceMatcher.
|
||||||
final _interfaceMatcher = new InterfaceMatcher();
|
final _interfaceMatcher = new InterfaceMatcher();
|
||||||
|
|
||||||
@ -96,12 +77,6 @@ class _NgMetaVisitor extends Object with SimpleAstVisitor<Object> {
|
|||||||
return node.declarations.accept(this);
|
return node.declarations.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Object visitExportDirective(ExportDirective node) {
|
|
||||||
ngMeta.exports.add(stringLiteralToString(node.uri));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Object visitClassDeclaration(ClassDeclaration node) {
|
Object visitClassDeclaration(ClassDeclaration node) {
|
||||||
_normalizations.add(_reader
|
_normalizations.add(_reader
|
||||||
|
@ -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/logging.dart' as log;
|
||||||
import 'package:angular2/src/transform/common/names.dart';
|
import 'package:angular2/src/transform/common/names.dart';
|
||||||
import 'package:angular2/src/transform/common/options.dart';
|
import 'package:angular2/src/transform/common/options.dart';
|
||||||
import 'package:angular2/src/transform/common/ng_meta.dart';
|
|
||||||
import 'package:barback/barback.dart';
|
import 'package:barback/barback.dart';
|
||||||
|
|
||||||
import 'rewriter.dart';
|
import 'rewriter.dart';
|
||||||
@ -37,7 +36,6 @@ class DirectiveProcessor extends Transformer implements DeclaringTransformer {
|
|||||||
@override
|
@override
|
||||||
declareOutputs(DeclaringTransform transform) {
|
declareOutputs(DeclaringTransform transform) {
|
||||||
transform.declareOutput(_ngMetaAssetId(transform.primaryId));
|
transform.declareOutput(_ngMetaAssetId(transform.primaryId));
|
||||||
transform.declareOutput(_ngDepsAssetId(transform.primaryId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -46,20 +44,13 @@ class DirectiveProcessor extends Transformer implements DeclaringTransformer {
|
|||||||
await log.initZoned(transform, () async {
|
await log.initZoned(transform, () async {
|
||||||
var primaryId = transform.primaryInput.id;
|
var primaryId = transform.primaryInput.id;
|
||||||
var reader = new AssetReader.fromTransform(transform);
|
var reader = new AssetReader.fromTransform(transform);
|
||||||
var ngMeta = new NgMeta.empty();
|
var ngMeta =
|
||||||
var ngDepsModel = await createNgDeps(
|
await createNgDeps(reader, primaryId, options.annotationMatcher);
|
||||||
reader, primaryId, options.annotationMatcher, ngMeta);
|
if (ngMeta == null || ngMeta.isEmpty) {
|
||||||
// TODO(kegluneq): Combine NgDepsModel with NgMeta in a single .json file.
|
return;
|
||||||
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())));
|
|
||||||
}
|
}
|
||||||
|
transform.addOutput(new Asset.fromString(
|
||||||
|
_ngMetaAssetId(primaryId), _encoder.convert(ngMeta.toJson())));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,8 +59,3 @@ AssetId _ngMetaAssetId(AssetId primaryInputId) {
|
|||||||
return new AssetId(
|
return new AssetId(
|
||||||
primaryInputId.package, toMetaExtension(primaryInputId.path));
|
primaryInputId.package, toMetaExtension(primaryInputId.path));
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetId _ngDepsAssetId(AssetId primaryInputId) {
|
|
||||||
return new AssetId(
|
|
||||||
primaryInputId.package, toJsonExtension(primaryInputId.path));
|
|
||||||
}
|
|
||||||
|
@ -30,7 +30,8 @@ class CompileDataResults {
|
|||||||
NormalizedComponentWithViewDirectives> viewDefinitions;
|
NormalizedComponentWithViewDirectives> viewDefinitions;
|
||||||
final List<CompileDirectiveMetadata> directiveMetadatas;
|
final List<CompileDirectiveMetadata> directiveMetadatas;
|
||||||
|
|
||||||
CompileDataResults._(this.ngDeps, this.viewDefinitions, this.directiveMetadatas);
|
CompileDataResults._(
|
||||||
|
this.ngDeps, this.viewDefinitions, this.directiveMetadatas);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(kegluenq): Improve this test.
|
// TODO(kegluenq): Improve this test.
|
||||||
@ -86,9 +87,7 @@ class _CompileDataCreator {
|
|||||||
Future<Map<AssetId, String>> _createImportAssetToPrefixMap() async {
|
Future<Map<AssetId, String>> _createImportAssetToPrefixMap() async {
|
||||||
var ngDeps = await ngDepsFuture;
|
var ngDeps = await ngDepsFuture;
|
||||||
|
|
||||||
var importAssetToPrefix = <AssetId, String>{
|
var importAssetToPrefix = <AssetId, String>{entryPoint: null};
|
||||||
entryPoint: null
|
|
||||||
};
|
|
||||||
|
|
||||||
for (ImportDirective node in ngDeps.imports) {
|
for (ImportDirective node in ngDeps.imports) {
|
||||||
var uri = stringLiteralToString(node.uri);
|
var uri = stringLiteralToString(node.uri);
|
||||||
@ -144,12 +143,15 @@ class _CompileDataCreator {
|
|||||||
importAssetId.package, toMetaExtension(importAssetId.path));
|
importAssetId.package, toMetaExtension(importAssetId.path));
|
||||||
if (await reader.hasInput(metaAssetId)) {
|
if (await reader.hasInput(metaAssetId)) {
|
||||||
try {
|
try {
|
||||||
var json = JSON.decode(await reader.readAsString(metaAssetId));
|
var jsonString = await reader.readAsString(metaAssetId);
|
||||||
var newMetadata = new NgMeta.fromJson(json);
|
if (jsonString != null && jsonString.isNotEmpty) {
|
||||||
if (importAssetId == entryPoint) {
|
var json = JSON.decode(jsonString);
|
||||||
this.directiveMetadatas.addAll(newMetadata.types.values);
|
var newMetadata = new NgMeta.fromJson(json);
|
||||||
|
if (importAssetId == entryPoint) {
|
||||||
|
this.directiveMetadatas.addAll(newMetadata.types.values);
|
||||||
|
}
|
||||||
|
ngMeta.addAll(newMetadata);
|
||||||
}
|
}
|
||||||
ngMeta.addAll(newMetadata);
|
|
||||||
} catch (ex, stackTrace) {
|
} catch (ex, stackTrace) {
|
||||||
logger.warning('Failed to decode: $ex, $stackTrace',
|
logger.warning('Failed to decode: $ex, $stackTrace',
|
||||||
asset: metaAssetId);
|
asset: metaAssetId);
|
||||||
|
@ -4,7 +4,6 @@ import 'package:barback/barback.dart';
|
|||||||
import 'package:dart_style/dart_style.dart';
|
import 'package:dart_style/dart_style.dart';
|
||||||
|
|
||||||
import 'deferred_rewriter/transformer.dart';
|
import 'deferred_rewriter/transformer.dart';
|
||||||
import 'directive_linker/transformer.dart';
|
|
||||||
import 'directive_metadata_linker/transformer.dart';
|
import 'directive_metadata_linker/transformer.dart';
|
||||||
import 'directive_processor/transformer.dart';
|
import 'directive_processor/transformer.dart';
|
||||||
import 'bind_generator/transformer.dart';
|
import 'bind_generator/transformer.dart';
|
||||||
@ -30,14 +29,8 @@ class AngularTransformerGroup extends TransformerGroup {
|
|||||||
[new ReflectionRemover(options)],
|
[new ReflectionRemover(options)],
|
||||||
[new DirectiveProcessor(options)]
|
[new DirectiveProcessor(options)]
|
||||||
];
|
];
|
||||||
phases.addAll(new List.generate(
|
|
||||||
options.optimizationPhases, (_) => [new EmptyNgDepsRemover()]));
|
|
||||||
phases.addAll([
|
phases.addAll([
|
||||||
[
|
[new DeferredRewriter(options), new DirectiveMetadataLinker()],
|
||||||
new DeferredRewriter(options),
|
|
||||||
new DirectiveLinker(),
|
|
||||||
new DirectiveMetadataLinker()
|
|
||||||
],
|
|
||||||
[new BindGenerator(options)],
|
[new BindGenerator(options)],
|
||||||
[new TemplateCompiler(options)],
|
[new TemplateCompiler(options)],
|
||||||
[new StylesheetCompiler()],
|
[new StylesheetCompiler()],
|
||||||
|
@ -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);
|
||||||
|
}
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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()));
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -1,17 +1,14 @@
|
|||||||
library angular2.test.transform.directive_metadata_linker.all_tests;
|
library angular2.test.transform.directive_metadata_linker.all_tests;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:convert';
|
||||||
import 'package:angular2/src/core/render/api.dart';
|
|
||||||
import 'package:angular2/src/core/change_detection/change_detection.dart';
|
import 'package:angular2/src/transform/common/model/import_export_model.pb.dart';
|
||||||
import 'package:angular2/src/transform/common/directive_metadata_reader.dart';
|
import 'package:angular2/src/transform/directive_metadata_linker/ng_meta_linker.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 'package:barback/barback.dart';
|
import 'package:barback/barback.dart';
|
||||||
import 'package:dart_style/dart_style.dart';
|
import 'package:dart_style/dart_style.dart';
|
||||||
import 'package:guinness/guinness.dart';
|
import 'package:guinness/guinness.dart';
|
||||||
|
|
||||||
|
import '../common/ng_meta_helper.dart';
|
||||||
import '../common/read_file.dart';
|
import '../common/read_file.dart';
|
||||||
|
|
||||||
var formatter = new DartFormatter();
|
var formatter = new DartFormatter();
|
||||||
@ -20,59 +17,148 @@ main() => allTests();
|
|||||||
|
|
||||||
void allTests() {
|
void allTests() {
|
||||||
TestAssetReader reader = null;
|
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(() {
|
beforeEach(() {
|
||||||
reader = new TestAssetReader();
|
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 {
|
describe('NgMeta linker', () {
|
||||||
var extracted = await linkDirectiveMetadata(
|
it('should include `DirectiveMetadata` from exported files.', () async {
|
||||||
reader,
|
fooNgMeta.ngDeps.exports.add(new ExportModel()..uri = 'bar.dart');
|
||||||
new AssetId(
|
updateReader();
|
||||||
'a', 'directive_metadata_linker/export_files/foo.ng_meta.json'));
|
|
||||||
expect(extracted.types).toContain('FooComponent');
|
|
||||||
expect(extracted.types).toContain('BarComponent');
|
|
||||||
|
|
||||||
expect(extracted.types['FooComponent'].selector).toEqual('[foo]');
|
var extracted = await linkDirectiveMetadata(reader, fooAssetId);
|
||||||
expect(extracted.types['BarComponent'].selector).toEqual('[bar]');
|
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.',
|
describe('NgDeps linker', () {
|
||||||
() async {
|
it('should chain imported dependencies.', () async {
|
||||||
var extracted = await linkDirectiveMetadata(
|
fooNgMeta.ngDeps
|
||||||
reader,
|
..libraryUri = 'test.foo'
|
||||||
new AssetId('a',
|
..imports.add(new ImportModel()
|
||||||
'directive_metadata_linker/recursive_export_files/foo.ng_meta.json'));
|
..uri = 'bar.dart'
|
||||||
expect(extracted.types).toContain('FooComponent');
|
..prefix = 'dep');
|
||||||
expect(extracted.types).toContain('BarComponent');
|
barNgMeta.ngDeps.libraryUri = 'test.bar';
|
||||||
expect(extracted.types).toContain('BazComponent');
|
updateReader();
|
||||||
|
|
||||||
expect(extracted.types['FooComponent'].selector).toEqual('[foo]');
|
var linked = (await linkDirectiveMetadata(reader, fooAssetId)).ngDeps;
|
||||||
expect(extracted.types['BarComponent'].selector).toEqual('[bar]');
|
expect(linked).toBeNotNull();
|
||||||
expect(extracted.types['BazComponent'].selector).toEqual('[baz]');
|
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 {
|
it('should chain exported dependencies.', () async {
|
||||||
var extracted = await linkDirectiveMetadata(
|
fooNgMeta.ngDeps
|
||||||
reader,
|
..libraryUri = 'test.foo'
|
||||||
new AssetId('a',
|
..exports.add(new ExportModel()..uri = 'bar.dart');
|
||||||
'directive_metadata_linker/export_cycle_files/baz.ng_meta.json'));
|
barNgMeta.ngDeps.libraryUri = 'test.bar';
|
||||||
expect(extracted.types).toContain('FooComponent');
|
updateReader();
|
||||||
expect(extracted.types).toContain('BarComponent');
|
|
||||||
expect(extracted.types).toContain('BazComponent');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(
|
var linked = (await linkDirectiveMetadata(reader, fooAssetId)).ngDeps;
|
||||||
'should include `DirectiveMetadata` from exported files '
|
expect(linked).toBeNotNull();
|
||||||
'expressed as absolute uris', () async {
|
var linkedImport =
|
||||||
var extracted = await linkDirectiveMetadata(
|
linked.imports.firstWhere((i) => i.uri.endsWith('bar.ng_deps.dart'));
|
||||||
reader,
|
expect(linkedImport).toBeNotNull();
|
||||||
new AssetId('a',
|
expect(linkedImport.isNgDeps).toBeTrue();
|
||||||
'directive_metadata_linker/absolute_export_files/foo.ng_meta.json'));
|
expect(linkedImport.prefix.startsWith('i')).toBeTrue();
|
||||||
expect(extracted.types).toContain('FooComponent');
|
});
|
||||||
expect(extracted.types).toContain('BarComponent');
|
|
||||||
|
|
||||||
expect(extracted.types['FooComponent'].selector).toEqual('[foo]');
|
|
||||||
expect(extracted.types['BarComponent'].selector).toEqual('[bar]');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ Expect _expectSelector(ReflectionInfoModel model) {
|
|||||||
|
|
||||||
void allTests() {
|
void allTests() {
|
||||||
it('should preserve parameter annotations.', () async {
|
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);
|
expect(model.reflectables.length).toBe(1);
|
||||||
var reflectable = model.reflectables.first;
|
var reflectable = model.reflectables.first;
|
||||||
expect(reflectable.parameters.length).toBe(2);
|
expect(reflectable.parameters.length).toBe(2);
|
||||||
@ -59,7 +59,8 @@ void allTests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('part support', () {
|
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 {
|
it('should include directives from the part.', () async {
|
||||||
var model = await modelFuture;
|
var model = await modelFuture;
|
||||||
@ -79,56 +80,59 @@ void allTests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should handle multiple `part` directives.', () async {
|
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);
|
expect(model.reflectables.length).toEqual(3);
|
||||||
_expectSelector(model.reflectables.first).toEqual("'[part1]'");
|
_expectSelector(model.reflectables.first).toEqual("'[part1]'");
|
||||||
_expectSelector(model.reflectables[1]).toEqual("'[part2]'");
|
_expectSelector(model.reflectables[1]).toEqual("'[part2]'");
|
||||||
_expectSelector(model.reflectables[2]).toEqual("'[main]'");
|
_expectSelector(model.reflectables[2]).toEqual("'[main]'");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not generate .ng_deps.dart for `part` files.', () async {
|
it('should not generate anything for `part` files.', () async {
|
||||||
var model = await _testCreateModel('part_files/part.dart');
|
expect(await _testCreateModel('part_files/part.dart')).toBeNull();
|
||||||
expect(model).toBeNull();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('custom annotations', () {
|
describe('custom annotations', () {
|
||||||
it('should be recognized from package: imports', () async {
|
it('should be recognized from package: imports', () async {
|
||||||
var model =
|
var ngMeta =
|
||||||
await _testCreateModel('custom_metadata/package_soup.dart', customDescriptors:
|
await _testCreateModel('custom_metadata/package_soup.dart', customDescriptors:
|
||||||
[
|
[
|
||||||
const ClassDescriptor('Soup', 'package:soup/soup.dart',
|
const ClassDescriptor('Soup', 'package:soup/soup.dart',
|
||||||
superClass: 'Component')
|
superClass: 'Component')
|
||||||
]);
|
]);
|
||||||
|
var model = ngMeta.ngDeps;
|
||||||
expect(model.reflectables.length).toEqual(1);
|
expect(model.reflectables.length).toEqual(1);
|
||||||
expect(model.reflectables.first.name).toEqual('PackageSoup');
|
expect(model.reflectables.first.name).toEqual('PackageSoup');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be recognized from relative imports', () async {
|
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'),
|
assetId: new AssetId('soup', 'lib/relative_soup.dart'),
|
||||||
customDescriptors: [
|
customDescriptors: [
|
||||||
const ClassDescriptor('Soup', 'package:soup/annotations/soup.dart',
|
const ClassDescriptor('Soup', 'package:soup/annotations/soup.dart',
|
||||||
superClass: 'Component')
|
superClass: 'Component')
|
||||||
]);
|
]);
|
||||||
|
var model = ngMeta.ngDeps;
|
||||||
expect(model.reflectables.length).toEqual(1);
|
expect(model.reflectables.length).toEqual(1);
|
||||||
expect(model.reflectables.first.name).toEqual('RelativeSoup');
|
expect(model.reflectables.first.name).toEqual('RelativeSoup');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should ignore annotations that are not imported', () async {
|
it('should ignore annotations that are not imported', () async {
|
||||||
var model =
|
var ngMeta =
|
||||||
await _testCreateModel('custom_metadata/bad_soup.dart', customDescriptors:
|
await _testCreateModel('custom_metadata/bad_soup.dart', customDescriptors:
|
||||||
[
|
[
|
||||||
const ClassDescriptor('Soup', 'package:soup/soup.dart',
|
const ClassDescriptor('Soup', 'package:soup/soup.dart',
|
||||||
superClass: 'Component')
|
superClass: 'Component')
|
||||||
]);
|
]);
|
||||||
expect(model).toBeNull();
|
expect(ngMeta.ngDeps == null || ngMeta.ngDeps.reflectables.isEmpty)
|
||||||
|
.toBeTrue();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('interfaces', () {
|
describe('interfaces', () {
|
||||||
it('should include implemented types', () async {
|
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).toBeNotNull();
|
||||||
expect(model.reflectables.first.interfaces.isNotEmpty).toBeTrue();
|
expect(model.reflectables.first.interfaces.isNotEmpty).toBeTrue();
|
||||||
@ -139,7 +143,8 @@ void allTests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should not include transitively implemented types', () async {
|
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).toBeNotNull();
|
||||||
expect(model.reflectables.first.interfaces.isNotEmpty).toBeTrue();
|
expect(model.reflectables.first.interfaces.isNotEmpty).toBeTrue();
|
||||||
@ -152,15 +157,15 @@ void allTests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should not include superclasses.', () async {
|
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;
|
var interfaces = model.reflectables.first.interfaces;
|
||||||
expect(interfaces == null || interfaces.isEmpty).toBeTrue();
|
expect(interfaces == null || interfaces.isEmpty).toBeTrue();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should populate multiple `lifecycle` values when necessary.', () async {
|
it('should populate multiple `lifecycle` values when necessary.', () async {
|
||||||
var model = await _testCreateModel(
|
var model = (await _testCreateModel(
|
||||||
'multiple_interface_lifecycle_files/soup.dart');
|
'multiple_interface_lifecycle_files/soup.dart')).ngDeps;
|
||||||
|
|
||||||
expect(model.reflectables.first.interfaces).toBeNotNull();
|
expect(model.reflectables.first.interfaces).toBeNotNull();
|
||||||
expect(model.reflectables.first.interfaces.isNotEmpty).toBeTrue();
|
expect(model.reflectables.first.interfaces.isNotEmpty).toBeTrue();
|
||||||
@ -174,15 +179,16 @@ void allTests() {
|
|||||||
it('should not populate `lifecycle` when lifecycle superclass is present.',
|
it('should not populate `lifecycle` when lifecycle superclass is present.',
|
||||||
() async {
|
() async {
|
||||||
var model =
|
var model =
|
||||||
await _testCreateModel('superclass_lifecycle_files/soup.dart');
|
(await _testCreateModel('superclass_lifecycle_files/soup.dart'))
|
||||||
|
.ngDeps;
|
||||||
|
|
||||||
var interfaces = model.reflectables.first.interfaces;
|
var interfaces = model.reflectables.first.interfaces;
|
||||||
expect(interfaces == null || interfaces.isEmpty).toBeTrue();
|
expect(interfaces == null || interfaces.isEmpty).toBeTrue();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should populate `lifecycle` with prefix when necessary.', () async {
|
it('should populate `lifecycle` with prefix when necessary.', () async {
|
||||||
var model = await _testCreateModel(
|
var model = (await _testCreateModel(
|
||||||
'prefixed_interface_lifecycle_files/soup.dart');
|
'prefixed_interface_lifecycle_files/soup.dart')).ngDeps;
|
||||||
expect(model.reflectables.first.interfaces).toBeNotNull();
|
expect(model.reflectables.first.interfaces).toBeNotNull();
|
||||||
expect(model.reflectables.first.interfaces.isNotEmpty).toBeTrue();
|
expect(model.reflectables.first.interfaces.isNotEmpty).toBeTrue();
|
||||||
expect(model.reflectables.first.interfaces
|
expect(model.reflectables.first.interfaces
|
||||||
@ -193,7 +199,8 @@ void allTests() {
|
|||||||
|
|
||||||
describe('property metadata', () {
|
describe('property metadata', () {
|
||||||
it('should be recorded on fields', () async {
|
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).toBeNotNull();
|
||||||
expect(model.reflectables.first.propertyMetadata.isNotEmpty).toBeTrue();
|
expect(model.reflectables.first.propertyMetadata.isNotEmpty).toBeTrue();
|
||||||
@ -205,7 +212,8 @@ void allTests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be recorded on getters', () async {
|
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).toBeNotNull();
|
||||||
expect(model.reflectables.first.propertyMetadata.isNotEmpty).toBeTrue();
|
expect(model.reflectables.first.propertyMetadata.isNotEmpty).toBeTrue();
|
||||||
@ -221,7 +229,8 @@ void allTests() {
|
|||||||
|
|
||||||
it('should gracefully handle const instances of annotations', () async {
|
it('should gracefully handle const instances of annotations', () async {
|
||||||
// Regression test for i/4481
|
// 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).toBeNotNull();
|
||||||
expect(model.reflectables.first.propertyMetadata.isNotEmpty).toBeTrue();
|
expect(model.reflectables.first.propertyMetadata.isNotEmpty).toBeTrue();
|
||||||
@ -240,7 +249,8 @@ void allTests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be recorded on setters', () async {
|
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).toBeNotNull();
|
||||||
expect(model.reflectables.first.propertyMetadata.isNotEmpty).toBeTrue();
|
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',
|
it('should be coalesced when getters and setters have the same name',
|
||||||
() async {
|
() async {
|
||||||
var model = await _testCreateModel(
|
var model = (await _testCreateModel(
|
||||||
'prop_metadata_files/getters_and_setters.dart');
|
'prop_metadata_files/getters_and_setters.dart')).ngDeps;
|
||||||
|
|
||||||
expect(model.reflectables.first.propertyMetadata).toBeNotNull();
|
expect(model.reflectables.first.propertyMetadata).toBeNotNull();
|
||||||
expect(model.reflectables.first.propertyMetadata.length).toBe(1);
|
expect(model.reflectables.first.propertyMetadata.length).toBe(1);
|
||||||
@ -271,8 +281,7 @@ void allTests() {
|
|||||||
|
|
||||||
it('should not throw/hang on invalid urls', () async {
|
it('should not throw/hang on invalid urls', () async {
|
||||||
var logger = new RecordingLogger();
|
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.hasErrors).toBeTrue();
|
||||||
expect(logger.logs)
|
expect(logger.logs)
|
||||||
..toContain('ERROR: ERROR: Invalid argument (url): '
|
..toContain('ERROR: ERROR: Invalid argument (url): '
|
||||||
@ -280,7 +289,8 @@ void allTests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should find and register static functions.', () async {
|
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 =
|
var functionReflectable =
|
||||||
model.reflectables.firstWhere((i) => i.isFunction, orElse: () => null);
|
model.reflectables.firstWhere((i) => i.isFunction, orElse: () => null);
|
||||||
@ -295,9 +305,7 @@ void allTests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should find direcive aliases patterns.', () async {
|
it('should find direcive aliases patterns.', () async {
|
||||||
var ngMeta = new NgMeta.empty();
|
var ngMeta = await _testCreateModel('directive_aliases_files/hello.dart');
|
||||||
await _testCreateModel('directive_aliases_files/hello.dart',
|
|
||||||
ngMeta: ngMeta);
|
|
||||||
|
|
||||||
expect(ngMeta.aliases).toContain('alias1');
|
expect(ngMeta.aliases).toContain('alias1');
|
||||||
expect(ngMeta.aliases['alias1']).toContain('HelloCmp');
|
expect(ngMeta.aliases['alias1']).toContain('HelloCmp');
|
||||||
@ -307,8 +315,7 @@ void allTests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should include hooks for implemented types (single)', () async {
|
it('should include hooks for implemented types (single)', () async {
|
||||||
var ngMeta = new NgMeta.empty();
|
var ngMeta = await _testCreateModel('interfaces_files/soup.dart');
|
||||||
await _testCreateModel('interfaces_files/soup.dart', ngMeta: ngMeta);
|
|
||||||
|
|
||||||
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
||||||
expect(ngMeta.types['ChangingSoupComponent']).toBeNotNull();
|
expect(ngMeta.types['ChangingSoupComponent']).toBeNotNull();
|
||||||
@ -318,9 +325,8 @@ void allTests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should include hooks for implemented types (many)', () async {
|
it('should include hooks for implemented types (many)', () async {
|
||||||
var ngMeta = new NgMeta.empty();
|
var ngMeta = await _testCreateModel(
|
||||||
await _testCreateModel('multiple_interface_lifecycle_files/soup.dart',
|
'multiple_interface_lifecycle_files/soup.dart');
|
||||||
ngMeta: ngMeta);
|
|
||||||
|
|
||||||
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
||||||
expect(ngMeta.types['MultiSoupComponent']).toBeNotNull();
|
expect(ngMeta.types['MultiSoupComponent']).toBeNotNull();
|
||||||
@ -335,9 +341,9 @@ void allTests() {
|
|||||||
fakeReader
|
fakeReader
|
||||||
..addAsset(new AssetId('other_package', 'lib/template.html'), '')
|
..addAsset(new AssetId('other_package', 'lib/template.html'), '')
|
||||||
..addAsset(new AssetId('other_package', 'lib/template.css'), '');
|
..addAsset(new AssetId('other_package', 'lib/template.css'), '');
|
||||||
var ngMeta = new NgMeta.empty();
|
var ngMeta = await _testCreateModel(
|
||||||
await _testCreateModel('absolute_url_expression_files/hello.dart',
|
'absolute_url_expression_files/hello.dart',
|
||||||
ngMeta: ngMeta, reader: fakeReader);
|
reader: fakeReader);
|
||||||
|
|
||||||
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
||||||
expect(ngMeta.types['HelloCmp']).toBeNotNull();
|
expect(ngMeta.types['HelloCmp']).toBeNotNull();
|
||||||
@ -346,9 +352,7 @@ void allTests() {
|
|||||||
|
|
||||||
it('should populate all provided values for Components & Directives',
|
it('should populate all provided values for Components & Directives',
|
||||||
() async {
|
() async {
|
||||||
var ngMeta = new NgMeta.empty();
|
var ngMeta = await _testCreateModel('unusual_component_files/hello.dart');
|
||||||
await _testCreateModel('unusual_component_files/hello.dart',
|
|
||||||
ngMeta: ngMeta);
|
|
||||||
|
|
||||||
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
||||||
|
|
||||||
@ -382,8 +386,7 @@ void allTests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should include hooks for implemented types (single)', () async {
|
it('should include hooks for implemented types (single)', () async {
|
||||||
var ngMeta = new NgMeta.empty();
|
var ngMeta = await _testCreateModel('interfaces_files/soup.dart');
|
||||||
await _testCreateModel('interfaces_files/soup.dart', ngMeta: ngMeta);
|
|
||||||
|
|
||||||
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
||||||
expect(ngMeta.types['ChangingSoupComponent']).toBeNotNull();
|
expect(ngMeta.types['ChangingSoupComponent']).toBeNotNull();
|
||||||
@ -393,9 +396,8 @@ void allTests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should include hooks for implemented types (many)', () async {
|
it('should include hooks for implemented types (many)', () async {
|
||||||
var ngMeta = new NgMeta.empty();
|
var ngMeta = await _testCreateModel(
|
||||||
await _testCreateModel('multiple_interface_lifecycle_files/soup.dart',
|
'multiple_interface_lifecycle_files/soup.dart');
|
||||||
ngMeta: ngMeta);
|
|
||||||
|
|
||||||
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
||||||
expect(ngMeta.types['MultiSoupComponent']).toBeNotNull();
|
expect(ngMeta.types['MultiSoupComponent']).toBeNotNull();
|
||||||
@ -410,9 +412,9 @@ void allTests() {
|
|||||||
fakeReader
|
fakeReader
|
||||||
..addAsset(new AssetId('other_package', 'lib/template.html'), '')
|
..addAsset(new AssetId('other_package', 'lib/template.html'), '')
|
||||||
..addAsset(new AssetId('other_package', 'lib/template.css'), '');
|
..addAsset(new AssetId('other_package', 'lib/template.css'), '');
|
||||||
var ngMeta = new NgMeta.empty();
|
var ngMeta = await _testCreateModel(
|
||||||
await _testCreateModel('absolute_url_expression_files/hello.dart',
|
'absolute_url_expression_files/hello.dart',
|
||||||
ngMeta: ngMeta, reader: fakeReader);
|
reader: fakeReader);
|
||||||
|
|
||||||
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
||||||
expect(ngMeta.types['HelloCmp']).toBeNotNull();
|
expect(ngMeta.types['HelloCmp']).toBeNotNull();
|
||||||
@ -423,12 +425,11 @@ void allTests() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<NgDepsModel> _testCreateModel(String inputPath,
|
Future<NgMeta> _testCreateModel(String inputPath,
|
||||||
{List<AnnotationDescriptor> customDescriptors: const [],
|
{List<AnnotationDescriptor> customDescriptors: const [],
|
||||||
AssetId assetId,
|
AssetId assetId,
|
||||||
AssetReader reader,
|
AssetReader reader,
|
||||||
BuildLogger logger,
|
BuildLogger logger}) {
|
||||||
NgMeta ngMeta}) {
|
|
||||||
if (logger == null) logger = new RecordingLogger();
|
if (logger == null) logger = new RecordingLogger();
|
||||||
return log.setZoned(logger, () async {
|
return log.setZoned(logger, () async {
|
||||||
var inputId = _assetIdForPath(inputPath);
|
var inputId = _assetIdForPath(inputPath);
|
||||||
@ -439,12 +440,9 @@ Future<NgDepsModel> _testCreateModel(String inputPath,
|
|||||||
reader.addAsset(assetId, await reader.readAsString(inputId));
|
reader.addAsset(assetId, await reader.readAsString(inputId));
|
||||||
inputId = assetId;
|
inputId = assetId;
|
||||||
}
|
}
|
||||||
if (ngMeta == null) {
|
|
||||||
ngMeta = new NgMeta.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
var annotationMatcher = new AnnotationMatcher()..addAll(customDescriptors);
|
var annotationMatcher = new AnnotationMatcher()..addAll(customDescriptors);
|
||||||
return createNgDeps(reader, inputId, annotationMatcher, ngMeta);
|
return createNgDeps(reader, inputId, annotationMatcher);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,24 +114,25 @@ void allTests() {
|
|||||||
new IntegrationTestConfig(
|
new IntegrationTestConfig(
|
||||||
'should handle Directive depenedencies declared on a View.',
|
'should handle Directive depenedencies declared on a View.',
|
||||||
inputs: {
|
inputs: {
|
||||||
'a|web/index.dart': 'directive_dep_files/index.dart',
|
'a|web/index.dart': 'directive_dep_files/index.dart',
|
||||||
'a|web/foo.dart': 'directive_dep_files/foo.dart',
|
'a|web/foo.dart': 'directive_dep_files/foo.dart',
|
||||||
'a|web/bar.dart': 'directive_dep_files/bar.dart'
|
'a|web/bar.dart': 'directive_dep_files/bar.dart'
|
||||||
},
|
},
|
||||||
outputs: {
|
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(
|
new IntegrationTestConfig(
|
||||||
'should handle chained Directive dependencies declared on a View.',
|
'should handle chained Directive dependencies declared on a View.',
|
||||||
inputs: {
|
inputs: {
|
||||||
'a|web/index.dart': 'directive_chain_files/index.dart',
|
'a|web/index.dart': 'directive_chain_files/index.dart',
|
||||||
'a|web/foo.dart': 'directive_chain_files/foo.dart',
|
'a|web/foo.dart': 'directive_chain_files/foo.dart',
|
||||||
'a|web/bar.dart': 'directive_chain_files/bar.dart',
|
'a|web/bar.dart': 'directive_chain_files/bar.dart',
|
||||||
'a|web/baz.dart': 'directive_chain_files/baz.dart'
|
'a|web/baz.dart': 'directive_chain_files/baz.dart'
|
||||||
},
|
},
|
||||||
outputs: {
|
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 = {};
|
var cache = {};
|
||||||
@ -160,8 +161,9 @@ void allTests() {
|
|||||||
],
|
],
|
||||||
config.assetPathToInputPath,
|
config.assetPathToInputPath,
|
||||||
config.assetPathToExpectedOutputPath,
|
config.assetPathToExpectedOutputPath,
|
||||||
[],
|
[]);
|
||||||
StringFormatter.noNewlinesOrSurroundingWhitespace);
|
//,
|
||||||
|
// StringFormatter.noNewlinesOrSurroundingWhitespace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates;
|
|||||||
import 'bar.dart';
|
import 'bar.dart';
|
||||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||||
import 'package:angular2/src/core/metadata.dart';
|
import 'package:angular2/src/core/metadata.dart';
|
||||||
|
import 'package:angular2/src/core/metadata.ng_deps.dart' as i0;
|
||||||
import 'baz.dart';
|
import 'baz.dart';
|
||||||
import 'baz.ng_deps.dart' as i1;
|
import 'baz.ng_deps.dart' as i1;
|
||||||
export 'bar.dart';
|
export 'bar.dart';
|
||||||
@ -21,5 +22,6 @@ void initReflector() {
|
|||||||
const View(directives: [Foo], template: 'foo'),
|
const View(directives: [Foo], template: 'foo'),
|
||||||
_templates.HostMyComponentTemplate
|
_templates.HostMyComponentTemplate
|
||||||
], const [], () => new MyComponent()));
|
], const [], () => new MyComponent()));
|
||||||
|
i0.initReflector();
|
||||||
i1.initReflector();
|
i1.initReflector();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates;
|
|||||||
import 'bar.dart';
|
import 'bar.dart';
|
||||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||||
import 'package:angular2/src/core/metadata.dart';
|
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.dart' as prefix;
|
||||||
import 'foo.ng_deps.dart' as i1;
|
import 'foo.ng_deps.dart' as i1;
|
||||||
export 'bar.dart';
|
export 'bar.dart';
|
||||||
@ -21,5 +22,6 @@ void initReflector() {
|
|||||||
const View(directives: [prefix.Foo], template: 'foo'),
|
const View(directives: [prefix.Foo], template: 'foo'),
|
||||||
_templates.HostMyComponentTemplate
|
_templates.HostMyComponentTemplate
|
||||||
], const [], () => new MyComponent()));
|
], const [], () => new MyComponent()));
|
||||||
|
i0.initReflector();
|
||||||
i1.initReflector();
|
i1.initReflector();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates;
|
|||||||
import 'bar.dart';
|
import 'bar.dart';
|
||||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||||
import 'package:angular2/src/core/metadata.dart';
|
import 'package:angular2/src/core/metadata.dart';
|
||||||
|
import 'package:angular2/src/core/metadata.ng_deps.dart' as i0;
|
||||||
export 'bar.dart';
|
export 'bar.dart';
|
||||||
|
|
||||||
var _visited = false;
|
var _visited = false;
|
||||||
@ -23,4 +24,5 @@ void initReflector() {
|
|||||||
], const [], () => new MyComponent()))
|
], const [], () => new MyComponent()))
|
||||||
..registerGetters(
|
..registerGetters(
|
||||||
{'eventName1': (o) => o.eventName1, 'eventName2': (o) => o.eventName2});
|
{'eventName1': (o) => o.eventName1, 'eventName2': (o) => o.eventName2});
|
||||||
|
i0.initReflector();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates;
|
|||||||
import 'bar.dart';
|
import 'bar.dart';
|
||||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||||
import 'package:angular2/src/core/metadata.dart';
|
import 'package:angular2/src/core/metadata.dart';
|
||||||
|
import 'package:angular2/src/core/metadata.ng_deps.dart' as i0;
|
||||||
import 'foo.dart';
|
import 'foo.dart';
|
||||||
export 'bar.dart';
|
export 'bar.dart';
|
||||||
|
|
||||||
@ -22,4 +23,5 @@ void initReflector() {
|
|||||||
], const [
|
], const [
|
||||||
const [MyContext]
|
const [MyContext]
|
||||||
], (MyContext c) => new MyComponent(c)));
|
], (MyContext c) => new MyComponent(c)));
|
||||||
|
i0.initReflector();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates;
|
|||||||
import 'bar.dart';
|
import 'bar.dart';
|
||||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||||
import 'package:angular2/src/core/metadata.dart';
|
import 'package:angular2/src/core/metadata.dart';
|
||||||
|
import 'package:angular2/src/core/metadata.ng_deps.dart' as i0;
|
||||||
export 'bar.dart';
|
export 'bar.dart';
|
||||||
|
|
||||||
var _visited = false;
|
var _visited = false;
|
||||||
@ -19,4 +20,5 @@ void initReflector() {
|
|||||||
const View(template: ''),
|
const View(template: ''),
|
||||||
_templates.HostMyComponentTemplate
|
_templates.HostMyComponentTemplate
|
||||||
], const [], () => new MyComponent()));
|
], const [], () => new MyComponent()));
|
||||||
|
i0.initReflector();
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import 'index.dart';
|
|||||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||||
import 'package:angular2/bootstrap_static.dart';
|
import 'package:angular2/bootstrap_static.dart';
|
||||||
import 'index.ng_deps.dart' as ngStaticInit;
|
import 'index.ng_deps.dart' as ngStaticInit;
|
||||||
|
import 'index.ng_deps.dart' as i1;
|
||||||
import 'package:angular2/src/core/reflection/reflection.dart';
|
import 'package:angular2/src/core/reflection/reflection.dart';
|
||||||
import 'bar.dart';
|
import 'bar.dart';
|
||||||
import 'bar.ng_deps.dart' as i3;
|
import 'bar.ng_deps.dart' as i3;
|
||||||
@ -13,5 +14,6 @@ var _visited = false;
|
|||||||
void initReflector() {
|
void initReflector() {
|
||||||
if (_visited) return;
|
if (_visited) return;
|
||||||
_visited = true;
|
_visited = true;
|
||||||
|
i1.initReflector();
|
||||||
i3.initReflector();
|
i3.initReflector();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates;
|
|||||||
import 'bar.dart';
|
import 'bar.dart';
|
||||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||||
import 'package:angular2/src/core/metadata.dart';
|
import 'package:angular2/src/core/metadata.dart';
|
||||||
|
import 'package:angular2/src/core/metadata.ng_deps.dart' as i0;
|
||||||
export 'bar.dart';
|
export 'bar.dart';
|
||||||
|
|
||||||
var _visited = false;
|
var _visited = false;
|
||||||
@ -19,4 +20,5 @@ void initReflector() {
|
|||||||
const View(template: ''),
|
const View(template: ''),
|
||||||
_templates.HostMyComponentTemplate
|
_templates.HostMyComponentTemplate
|
||||||
], const [], () => new MyComponent()));
|
], const [], () => new MyComponent()));
|
||||||
|
i0.initReflector();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates;
|
|||||||
import 'bar.dart';
|
import 'bar.dart';
|
||||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||||
import 'package:angular2/src/core/metadata.dart';
|
import 'package:angular2/src/core/metadata.dart';
|
||||||
|
import 'package:angular2/src/core/metadata.ng_deps.dart' as i0;
|
||||||
export 'bar.dart';
|
export 'bar.dart';
|
||||||
|
|
||||||
var _visited = false;
|
var _visited = false;
|
||||||
@ -19,4 +20,5 @@ void initReflector() {
|
|||||||
const View(template: 'Salad: {{myNum}} is awesome'),
|
const View(template: 'Salad: {{myNum}} is awesome'),
|
||||||
_templates.HostMyComponentTemplate
|
_templates.HostMyComponentTemplate
|
||||||
], const [], () => new MyComponent()));
|
], const [], () => new MyComponent()));
|
||||||
|
i0.initReflector();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import 'bar.template.dart' as _templates;
|
|||||||
import 'bar.dart';
|
import 'bar.dart';
|
||||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||||
import 'package:angular2/src/core/metadata.dart';
|
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.dart' as prefix;
|
||||||
export 'bar.dart';
|
export 'bar.dart';
|
||||||
|
|
||||||
@ -27,4 +28,5 @@ void initReflector() {
|
|||||||
],
|
],
|
||||||
(prefix.MyContext c, String inValue) =>
|
(prefix.MyContext c, String inValue) =>
|
||||||
new MyComponent(c, inValue)));
|
new MyComponent(c, inValue)));
|
||||||
|
i0.initReflector();
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@ import 'package:unittest/vm_config.dart';
|
|||||||
|
|
||||||
import 'common/async_string_writer_tests.dart' as asyncStringWriter;
|
import 'common/async_string_writer_tests.dart' as asyncStringWriter;
|
||||||
import 'common/ng_meta_test.dart' as ngMetaTest;
|
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 'bind_generator/all_tests.dart' as bindGenerator;
|
||||||
import 'deferred_rewriter/all_tests.dart' as deferredRewriter;
|
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_metadata_linker/all_tests.dart' as directiveMeta;
|
||||||
import 'directive_processor/all_tests.dart' as directiveProcessor;
|
import 'directive_processor/all_tests.dart' as directiveProcessor;
|
||||||
import 'inliner_for_test/all_tests.dart' as inliner;
|
import 'inliner_for_test/all_tests.dart' as inliner;
|
||||||
@ -22,7 +22,6 @@ main() {
|
|||||||
describe('AsyncStringWriter', asyncStringWriter.allTests);
|
describe('AsyncStringWriter', asyncStringWriter.allTests);
|
||||||
describe('NgMeta', ngMetaTest.allTests);
|
describe('NgMeta', ngMetaTest.allTests);
|
||||||
describe('Bind Generator', bindGenerator.allTests);
|
describe('Bind Generator', bindGenerator.allTests);
|
||||||
describe('Directive Linker', directiveLinker.allTests);
|
|
||||||
describe('Directive Metadata Linker', directiveMeta.allTests);
|
describe('Directive Metadata Linker', directiveMeta.allTests);
|
||||||
describe('Directive Processor', directiveProcessor.allTests);
|
describe('Directive Processor', directiveProcessor.allTests);
|
||||||
describe('Inliner For Test', inliner.allTests);
|
describe('Inliner For Test', inliner.allTests);
|
||||||
@ -30,6 +29,7 @@ main() {
|
|||||||
describe('Template Compiler', templateCompiler.allTests);
|
describe('Template Compiler', templateCompiler.allTests);
|
||||||
describe('Deferred Rewriter', deferredRewriter.allTests);
|
describe('Deferred Rewriter', deferredRewriter.allTests);
|
||||||
describe('Stylesheet Compiler', stylesheetCompiler.allTests);
|
describe('Stylesheet Compiler', stylesheetCompiler.allTests);
|
||||||
|
describe('Url Resolver', urlResolver.allTests);
|
||||||
// NOTE(kegluneq): These use `code_transformers#testPhases`, which is not
|
// NOTE(kegluneq): These use `code_transformers#testPhases`, which is not
|
||||||
// designed to work with `guinness`.
|
// designed to work with `guinness`.
|
||||||
group('Transformer Pipeline', integration.allTests);
|
group('Transformer Pipeline', integration.allTests);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user