refactor(dart/transform): Use protos to run & test directive_linker
Use the proto ng_deps model objects internally and while testing the directive linker rather than reading & comparing Dart code.
This commit is contained in:
parent
cc0c30484f
commit
820b30c181
|
@ -140,7 +140,7 @@ abstract class NgDepsWriterMixin
|
|||
}
|
||||
|
||||
// We do not support `partUris`, so skip outputting them.
|
||||
model.imports.forEach((importModel) {
|
||||
for (var importModel in model.imports) {
|
||||
// Ignore deferred imports here so as to not load the deferred libraries
|
||||
// code in the current library causing much of the code to not be
|
||||
// deferred. Instead `DeferredRewriter` will rewrite the code as to load
|
||||
|
@ -148,7 +148,7 @@ abstract class NgDepsWriterMixin
|
|||
if (importModel.isDeferred) return;
|
||||
|
||||
writeImportModel(importModel);
|
||||
});
|
||||
}
|
||||
model.exports.forEach(writeExportModel);
|
||||
|
||||
buffer
|
||||
|
@ -162,6 +162,13 @@ abstract class NgDepsWriterMixin
|
|||
buffer.writeln(';');
|
||||
}
|
||||
|
||||
// Call the setup method for our imports that are `.ng_deps` imports.
|
||||
for (var importModel in model.imports) {
|
||||
if (importModel.isNgDeps) {
|
||||
buffer.writeln('${importModel.prefix}.${SETUP_METHOD_NAME}();');
|
||||
}
|
||||
}
|
||||
|
||||
buffer.writeln('}');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ class ImportModel extends GeneratedMessage {
|
|||
..p(3, 'hideCombinators', PbFieldType.PS)
|
||||
..a(4, 'prefix', PbFieldType.OS)
|
||||
..a(5, 'isDeferred', PbFieldType.OB)
|
||||
..a(6, 'isNgDeps', PbFieldType.OB)
|
||||
;
|
||||
|
||||
ImportModel() : super();
|
||||
|
@ -48,6 +49,11 @@ class ImportModel extends GeneratedMessage {
|
|||
void set isDeferred(bool v) { setField(5, v); }
|
||||
bool hasIsDeferred() => hasField(5);
|
||||
void clearIsDeferred() => clearField(5);
|
||||
|
||||
bool get isNgDeps => getField(6);
|
||||
void set isNgDeps(bool v) { setField(6, v); }
|
||||
bool hasIsNgDeps() => hasField(6);
|
||||
void clearIsNgDeps() => clearField(6);
|
||||
}
|
||||
|
||||
class _ReadonlyImportModel extends ImportModel with ReadonlyMessageMixin {}
|
||||
|
@ -95,6 +101,7 @@ const ImportModel$json = const {
|
|||
const {'1': 'hide_combinators', '3': 3, '4': 3, '5': 9},
|
||||
const {'1': 'prefix', '3': 4, '4': 1, '5': 9},
|
||||
const {'1': 'is_deferred', '3': 5, '4': 1, '5': 8},
|
||||
const {'1': 'is_ng_deps', '3': 6, '4': 1, '5': 8},
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -109,7 +116,7 @@ const ExportModel$json = const {
|
|||
|
||||
/**
|
||||
* Generated with:
|
||||
* import_export_model.proto (36a3a72d0884b84b451b7188ffa1fc93b44e7b62)
|
||||
* import_export_model.proto (c018d2ad92db2d341631d813ace70925d1ccbb9b)
|
||||
* libprotoc 2.5.0
|
||||
* dart-protoc-plugin (cc35f743de982a4916588b9c505dd21c7fe87d17)
|
||||
*/
|
||||
|
|
|
@ -16,6 +16,8 @@ message ImportModel {
|
|||
optional string prefix = 4;
|
||||
|
||||
optional bool is_deferred = 5;
|
||||
|
||||
optional bool is_ng_deps = 6;
|
||||
}
|
||||
|
||||
// See message above about wire-compatiblity with `ImportModel`.
|
||||
|
|
|
@ -5,6 +5,7 @@ const SETUP_METHOD_NAME = 'initReflector';
|
|||
const REFLECTOR_VAR_NAME = 'reflector';
|
||||
const TRANSFORM_DYNAMIC_MODE = 'transform_dynamic';
|
||||
const DEPS_EXTENSION = '.ng_deps.dart';
|
||||
const DEPS_JSON_EXTENSION = '.ng_deps.json';
|
||||
const META_EXTENSION = '.ng_meta.json';
|
||||
// TODO(sigmund): consider merging into .ng_meta by generating local metadata
|
||||
// upfront (rather than extracting it from ng_deps).
|
||||
|
@ -19,16 +20,19 @@ const REGISTER_METHODS_METHOD_NAME = 'registerMethods';
|
|||
|
||||
/// Returns `uri` with its extension updated to [META_EXTENSION].
|
||||
String toMetaExtension(String uri) =>
|
||||
_toExtension(uri, const [DEPS_EXTENSION, '.dart'], META_EXTENSION);
|
||||
_toExtension(uri, const [DEPS_EXTENSION, DEPS_JSON_EXTENSION, '.dart'], META_EXTENSION);
|
||||
|
||||
/// Returns `uri` with its extension updated to [DEPS_EXTENSION].
|
||||
String toDepsExtension(String uri) =>
|
||||
_toExtension(uri, const [META_EXTENSION, '.dart'], DEPS_EXTENSION);
|
||||
_toExtension(uri, const [META_EXTENSION, DEPS_JSON_EXTENSION, '.dart'], DEPS_EXTENSION);
|
||||
|
||||
/// Returns `uri` with its extension updated to [ALIAS_EXTENSION].
|
||||
String toAliasExtension(String uri) =>
|
||||
_toExtension(uri, const [DEPS_EXTENSION, '.dart'], ALIAS_EXTENSION);
|
||||
|
||||
String toJsonExtension(String uri) =>
|
||||
_toExtension(uri, const [DEPS_EXTENSION, '.dart'], DEPS_JSON_EXTENSION);
|
||||
|
||||
/// Returns `uri` with its extension updated to `toExtension` if its
|
||||
/// extension is currently in `fromExtension`.
|
||||
String _toExtension(
|
||||
|
|
|
@ -2,118 +2,115 @@ library angular2.transform.directive_linker.linker;
|
|||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:analyzer/analyzer.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/ng_deps.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.dart` file represented by `entryPoint` and
|
||||
/// 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.dart` file is not necessary if:
|
||||
/// 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.dart` files register
|
||||
/// 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 {
|
||||
NgDeps ngDeps = await NgDeps.parse(reader, entryPoint);
|
||||
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 (ngDeps.registeredTypes.isNotEmpty) return true;
|
||||
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, _getSortedDeps(ngDeps));
|
||||
var linkedDepsMap = await _processNgImports(reader, entryPoint, ngDepsModel);
|
||||
return linkedDepsMap.isNotEmpty;
|
||||
}
|
||||
|
||||
/// Modifies the `.ng_deps.dart` file represented by `entryPoint` to call its
|
||||
/// dependencies associated `initReflector` methods.
|
||||
/// 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.dart exists. If it does, we add:
|
||||
///
|
||||
/// ```
|
||||
/// import 'dependency.ng_deps.dart' as i0;
|
||||
/// ...
|
||||
/// void setupReflection(reflector) {
|
||||
/// ...
|
||||
/// i0.initReflector(reflector);
|
||||
/// }
|
||||
/// ```
|
||||
Future<String> linkNgDeps(AssetReader reader, AssetId entryPoint) async {
|
||||
NgDeps ngDeps = await NgDeps.parse(reader, entryPoint);
|
||||
/// 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);
|
||||
|
||||
if (ngDeps == null) return null;
|
||||
|
||||
var allDeps = _getSortedDeps(ngDeps);
|
||||
var linkedDepsMap = await _processNgImports(reader, entryPoint, allDeps);
|
||||
var linkedDepsMap = await _processNgImports(reader, entryPoint, ngDepsModel);
|
||||
|
||||
if (linkedDepsMap.isEmpty) {
|
||||
// We are not calling `initReflector` on any other libraries.
|
||||
return ngDeps.code;
|
||||
// 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;
|
||||
}
|
||||
|
||||
var importBuf = new StringBuffer();
|
||||
var declarationBuf = new StringBuffer();
|
||||
var code = ngDeps.code;
|
||||
var codeIdx = 0;
|
||||
// Generate import statements for linked deps where necessary.
|
||||
for (var i = 0, it = allDeps.iterator; it.moveNext();) {
|
||||
if (linkedDepsMap.containsKey(it.current)) {
|
||||
importBuf.write(code.substring(codeIdx, it.current.end));
|
||||
codeIdx = it.current.end;
|
||||
importBuf.write('''
|
||||
import '${linkedDepsMap[it.current]}' as i${i};
|
||||
''');
|
||||
declarationBuf.write('i${i}.${SETUP_METHOD_NAME}();');
|
||||
++i;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
var declarationSeamIdx = ngDeps.setupMethod.end - 1;
|
||||
return '$importBuf'
|
||||
'${code.substring(codeIdx, declarationSeamIdx)}'
|
||||
'$declarationBuf'
|
||||
'${code.substring(declarationSeamIdx)}';
|
||||
return ngDepsModel;
|
||||
}
|
||||
|
||||
/// All `import`s and `export`s in `ngDeps` sorted by order of appearance in
|
||||
/// the file.
|
||||
List<UriBasedDirective> _getSortedDeps(NgDeps ngDeps) {
|
||||
return <UriBasedDirective>[]
|
||||
..addAll(ngDeps.imports)
|
||||
..addAll(ngDeps.exports)
|
||||
..sort((a, b) => a.end.compareTo(b.end));
|
||||
bool _isNotDartDirective(dynamic model) {
|
||||
return !model.uri.startsWith('dart:');
|
||||
}
|
||||
|
||||
bool _isNotDartDirective(UriBasedDirective directive) {
|
||||
return !stringLiteralToString(directive.uri).startsWith('dart:');
|
||||
}
|
||||
|
||||
/// Maps each input {@link UriBasedDirective} to its associated `.ng_deps.dart`
|
||||
/// file, if it exists.
|
||||
Future<Map<UriBasedDirective, String>> _processNgImports(AssetReader reader,
|
||||
AssetId entryPoint, Iterable<UriBasedDirective> directives) {
|
||||
/// 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 retVal = <UriBasedDirective, String>{};
|
||||
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(directives
|
||||
.where(_isNotDartDirective)
|
||||
.map((UriBasedDirective directive) {
|
||||
var ngDepsUri = toDepsExtension(stringLiteralToString(directive.uri));
|
||||
.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 ngDepsAsset = uriToAssetId(entryPoint, ngDepsUri, logger, spanArg,
|
||||
var linkedNgJsonAsset = uriToAssetId(
|
||||
entryPoint, linkedJsonUri, logger, spanArg,
|
||||
errorOnAbsolute: false);
|
||||
if (ngDepsAsset == entryPoint) return nullFuture;
|
||||
return reader.hasInput(ngDepsAsset).then((hasInput) {
|
||||
if (linkedNgJsonAsset == ngJsonAsset) return nullFuture;
|
||||
return reader.hasInput(linkedNgJsonAsset).then((hasInput) {
|
||||
if (hasInput) {
|
||||
retVal[directive] = ngDepsUri;
|
||||
retVal[directive.uri] = linkedJsonUri;
|
||||
}
|
||||
}, onError: (_) => null);
|
||||
}))
|
||||
|
|
|
@ -3,6 +3,7 @@ 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';
|
||||
|
@ -10,15 +11,14 @@ import 'package:barback/barback.dart';
|
|||
|
||||
import 'linker.dart';
|
||||
|
||||
/// Transformer responsible for processing .ng_deps.dart files created by
|
||||
/// {@link DirectiveProcessor} and ensuring that the generated calls to
|
||||
/// `setupReflection` call the necessary `setupReflection` method in all
|
||||
/// dependencies.
|
||||
/// 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_EXTENSION);
|
||||
bool isPrimary(AssetId id) => id.path.endsWith(DEPS_JSON_EXTENSION);
|
||||
|
||||
@override
|
||||
declareOutputs(DeclaringTransform transform) {
|
||||
|
@ -31,22 +31,27 @@ class DirectiveLinker extends Transformer implements DeclaringTransformer {
|
|||
var reader = new AssetReader.fromTransform(transform);
|
||||
var assetId = transform.primaryInput.id;
|
||||
var assetPath = assetId.path;
|
||||
var transformedCode = await linkNgDeps(reader, assetId);
|
||||
if (transformedCode != null) {
|
||||
var formattedCode = formatter.format(transformedCode, uri: assetPath);
|
||||
transform.addOutput(new Asset.fromString(assetId, formattedCode));
|
||||
var ngDepsModel = await linkNgDeps(reader, assetId);
|
||||
if (ngDepsModel != null) {
|
||||
var buf = new StringBuffer();
|
||||
var writer = new NgDepsWriter(buf);
|
||||
writer.writeNgDepsModel(ngDepsModel);
|
||||
var formattedCode = formatter.format('$buf', uri: assetPath);
|
||||
var ngDepsAssetId =
|
||||
new AssetId(assetId.package, toDepsExtension(assetPath));
|
||||
transform.addOutput(new Asset.fromString(ngDepsAssetId, formattedCode));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Transformer responsible for removing unnecessary `.ng_deps.dart` files
|
||||
/// 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_EXTENSION);
|
||||
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 do not declare any outputs nor
|
||||
|
|
|
@ -51,6 +51,9 @@ Future<NgDepsModel> createNgDeps(AssetReader reader, AssetId assetId,
|
|||
parsedCode.accept(ngDepsVisitor);
|
||||
var ngDepsModel = ngDepsVisitor.model;
|
||||
|
||||
var ngMetaVisitor = new _NgMetaVisitor(ngMeta);
|
||||
parsedCode.accept(ngMetaVisitor);
|
||||
|
||||
// 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 (!directivesVisitor.usesNonLangLibs &&
|
||||
|
@ -58,9 +61,6 @@ Future<NgDepsModel> createNgDeps(AssetReader reader, AssetId assetId,
|
|||
return null;
|
||||
}
|
||||
|
||||
var ngMetaVisitor = new _NgMetaVisitor(ngMeta);
|
||||
parsedCode.accept(ngMetaVisitor);
|
||||
|
||||
if (inlineViews) {
|
||||
await inlineViewProps(new XhrImpl(reader, assetId), ngDepsModel);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import 'dart:async';
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:angular2/src/transform/common/asset_reader.dart';
|
||||
import 'package:angular2/src/transform/common/code/ng_deps_code.dart';
|
||||
import 'package:angular2/src/transform/common/logging.dart' as log;
|
||||
import 'package:angular2/src/transform/common/names.dart';
|
||||
import 'package:angular2/src/transform/common/options.dart';
|
||||
|
@ -52,15 +51,12 @@ class DirectiveProcessor extends Transformer implements DeclaringTransformer {
|
|||
inlineViews: options.inlineViews);
|
||||
if (ngDepsModel != null) {
|
||||
var ngDepsAssetId =
|
||||
transform.primaryInput.id.changeExtension(DEPS_EXTENSION);
|
||||
transform.primaryInput.id.changeExtension(DEPS_JSON_EXTENSION);
|
||||
if (await transform.hasInput(ngDepsAssetId)) {
|
||||
log.logger.error('Clobbering ${ngDepsAssetId}. '
|
||||
'This probably will not end well');
|
||||
}
|
||||
var buf = new StringBuffer();
|
||||
var writer = new NgDepsWriter(buf);
|
||||
writer.writeNgDepsModel(ngDepsModel);
|
||||
transform.addOutput(new Asset.fromString(ngDepsAssetId, '$buf'));
|
||||
transform.addOutput(new Asset.fromString(ngDepsAssetId, ngDepsModel.writeToJson()));
|
||||
}
|
||||
if (!ngMeta.isEmpty) {
|
||||
var ngAliasesId =
|
||||
|
|
|
@ -32,11 +32,8 @@ class AngularTransformerGroup extends TransformerGroup {
|
|||
phases.addAll(new List.generate(
|
||||
options.optimizationPhases, (_) => [new EmptyNgDepsRemover()]));
|
||||
phases.addAll([
|
||||
[
|
||||
new DirectiveLinker(),
|
||||
new DirectiveMetadataExtractor(),
|
||||
new DeferredRewriter(options)
|
||||
],
|
||||
[new DirectiveLinker(), new DeferredRewriter(options)],
|
||||
[new DirectiveMetadataExtractor()],
|
||||
[new BindGenerator(options)],
|
||||
[new TemplateCompiler(options)]
|
||||
]);
|
||||
|
|
|
@ -4,6 +4,7 @@ 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';
|
||||
|
@ -15,36 +16,122 @@ var formatter = new DartFormatter();
|
|||
main() => allTests();
|
||||
|
||||
void allTests() {
|
||||
var reader = new TestAssetReader();
|
||||
var reader;
|
||||
|
||||
it('should ensure that dependencies are property chained.', () async {
|
||||
for (var inputPath in [
|
||||
'bar.ng_deps.dart',
|
||||
'foo.ng_deps.dart',
|
||||
'index.ng_deps.dart'
|
||||
]) {
|
||||
var expected =
|
||||
readFile('directive_linker/simple_files/expected/$inputPath');
|
||||
inputPath = 'directive_linker/simple_files/$inputPath';
|
||||
var actual = formatter
|
||||
.format(await linkNgDeps(reader, new AssetId('a', inputPath)));
|
||||
expect(actual).toEqual(formatter.format(expected));
|
||||
}
|
||||
beforeEach(() {
|
||||
reader = new TestAssetReader();
|
||||
});
|
||||
|
||||
it('should ensure that exported dependencies are property chained.',
|
||||
() async {
|
||||
for (var inputPath in [
|
||||
'bar.ng_deps.dart',
|
||||
'foo.ng_deps.dart',
|
||||
'index.ng_deps.dart'
|
||||
]) {
|
||||
var expected =
|
||||
readFile('directive_linker/simple_export_files/expected/$inputPath');
|
||||
inputPath = 'directive_linker/simple_export_files/$inputPath';
|
||||
var actual = formatter
|
||||
.format(await linkNgDeps(reader, new AssetId('a', inputPath)));
|
||||
expect(actual).toEqual(formatter.format(expected));
|
||||
}
|
||||
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,18 +0,0 @@
|
|||
library bar.ng_deps.dart;
|
||||
|
||||
import 'bar.dart';
|
||||
export 'bar.dart';
|
||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/src/core/metadata.dart';
|
||||
export 'foo.dart';
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
_ngRef.reflector
|
||||
..registerType(
|
||||
MyComponent,
|
||||
new _ngRef.ReflectionInfo(const [const Component(selector: '[soup]')],
|
||||
const [], () => new MyComponent()));
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
library bar.ng_deps.dart;
|
||||
|
||||
import 'bar.dart';
|
||||
export 'bar.dart';
|
||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/src/core/metadata.dart';
|
||||
export 'foo.dart';
|
||||
import 'foo.ng_deps.dart' as i0;
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
_ngRef.reflector
|
||||
..registerType(
|
||||
MyComponent,
|
||||
new _ngRef.ReflectionInfo(const [const Component(selector: '[soup]')],
|
||||
const [], () => new MyComponent()));
|
||||
i0.initReflector();
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
library foo.ng_deps.dart;
|
||||
|
||||
import 'foo.dart';
|
||||
export 'foo.dart';
|
||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/src/core/metadata.dart';
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
_ngRef.reflector
|
||||
..registerType(
|
||||
DependencyComponent,
|
||||
new _ngRef.ReflectionInfo(const [const Component(selector: '[salad]')],
|
||||
const [], () => new DependencyComponent()));
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
library web_foo.ng_deps.dart;
|
||||
|
||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/bootstrap_static.dart';
|
||||
import 'package:angular2/src/core/reflection/reflection_capabilities.dart';
|
||||
import 'bar.dart';
|
||||
import 'bar.ng_deps.dart' as i0;
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
i0.initReflector();
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
library foo.ng_deps.dart;
|
||||
|
||||
import 'foo.dart';
|
||||
export 'foo.dart';
|
||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/src/core/metadata.dart';
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
_ngRef.reflector
|
||||
..registerType(
|
||||
DependencyComponent,
|
||||
new _ngRef.ReflectionInfo(const [const Component(selector: '[salad]')],
|
||||
const [], () => new DependencyComponent()));
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
library web_foo.ng_deps.dart;
|
||||
|
||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/bootstrap_static.dart';
|
||||
import 'package:angular2/src/core/reflection/reflection_capabilities.dart';
|
||||
import 'bar.dart';
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
library bar.ng_deps.dart;
|
||||
|
||||
import 'bar.dart';
|
||||
export 'bar.dart';
|
||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/src/core/metadata.dart';
|
||||
import 'foo.dart' as dep;
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
_ngRef.reflector
|
||||
..registerType(
|
||||
MyComponent,
|
||||
new ReflectionInfo(const [
|
||||
const Component(
|
||||
selector: '[soup]', viewBindings: const [dep.DependencyComponent])
|
||||
], const [], () => new MyComponent()));
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
library bar.ng_deps.dart;
|
||||
|
||||
import 'bar.dart';
|
||||
export 'bar.dart';
|
||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/src/core/metadata.dart';
|
||||
import 'foo.dart' as dep;
|
||||
import 'foo.ng_deps.dart' as i0;
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
_ngRef.reflector
|
||||
..registerType(
|
||||
MyComponent,
|
||||
new ReflectionInfo(const [
|
||||
const Component(
|
||||
selector: '[soup]', viewBindings: const [dep.DependencyComponent])
|
||||
], const [], () => new MyComponent()));
|
||||
i0.initReflector();
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
library foo.ng_deps.dart;
|
||||
|
||||
import 'foo.dart';
|
||||
export 'foo.dart';
|
||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/src/core/metadata.dart';
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
_ngRef.reflector
|
||||
..registerType(
|
||||
DependencyComponent,
|
||||
new _ngRef.ReflectionInfo(const [const Component(selector: '[salad]')],
|
||||
const [], () => new DependencyComponent()));
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
library web_foo.ng_deps.dart;
|
||||
|
||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/bootstrap_static.dart';
|
||||
import 'package:angular2/src/core/reflection/reflection_capabilities.dart';
|
||||
import 'bar.dart';
|
||||
import 'bar.ng_deps.dart' as i0;
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
i0.initReflector();
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
library foo.ng_deps.dart;
|
||||
|
||||
import 'foo.dart';
|
||||
export 'foo.dart';
|
||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/src/core/metadata.dart';
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
_ngRef.reflector
|
||||
..registerType(
|
||||
DependencyComponent,
|
||||
new _ngRef.ReflectionInfo(const [const Component(selector: '[salad]')],
|
||||
const [], () => new DependencyComponent()));
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
library web_foo.ng_deps.dart;
|
||||
|
||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/bootstrap_static.dart';
|
||||
import 'package:angular2/src/core/reflection/reflection_capabilities.dart';
|
||||
import 'bar.dart';
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
}
|
|
@ -6,12 +6,12 @@ import 'package:angular2/bootstrap_static.dart';
|
|||
import 'index.ng_deps.dart' as ngStaticInit;
|
||||
import 'package:angular2/src/core/reflection/reflection.dart';
|
||||
import 'bar.dart';
|
||||
import 'bar.ng_deps.dart' as i0;
|
||||
import 'bar.ng_deps.dart' as i5;
|
||||
export 'index.dart';
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
i0.initReflector();
|
||||
i5.initReflector();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue