feat(transformers): implement initializing deferred libraries

Implement deferred libraries to work with dependency injection and other
angular codegen. This is done by not initializing the library in the parent
ng_deps file when it is declared as deferred, rewriting the import and,
chaining a future that initializes the library in any files that are using
deferred libraries which need angular codegen.
This commit is contained in:
Ted Sander
2015-07-17 02:45:27 -07:00
parent 2f08ed8d3e
commit 5cc84ed4bb
46 changed files with 459 additions and 2 deletions
@@ -0,0 +1,58 @@
library angular2.test.transform.deferred_rewriter.all_tests;
import 'package:barback/barback.dart';
import 'package:angular2/src/transform/deferred_rewriter/transformer.dart';
import 'package:angular2/src/transform/common/annotation_matcher.dart';
import 'package:angular2/src/transform/common/asset_reader.dart';
import 'package:angular2/src/transform/common/logging.dart' as log;
import 'package:code_transformers/messages/build_logger.dart';
import 'package:dart_style/dart_style.dart';
import 'package:guinness/guinness.dart';
import 'package:path/path.dart' as path;
import '../common/read_file.dart';
var formatter = new DartFormatter();
main() {
allTests();
}
void allTests() {
_testRewriteDeferredLibraries(
'should return null when no deferred libraries found.',
'no_deferred_libraries/index.dart');
_testRewriteDeferredLibraries(
'should return null when deferred libraries with no ng_deps.',
'no_ng_deps_libraries/index.dart');
_testRewriteDeferredLibraries(
'should rewrite deferred libraries with ng_deps.',
'simple_deferred_example/index.dart');
_testRewriteDeferredLibraries(
'should not rewrite deferred libraries without ng_deps.',
'deferred_example_no_ng_deps/index.dart');
_testRewriteDeferredLibraries(
'should rewrite deferred libraries with ng_deps leave other deferred library alone.',
'complex_deferred_example/index.dart');
}
void _testRewriteDeferredLibraries(String name, String inputPath) {
it(name, () async {
var inputId = _assetIdForPath(inputPath);
var reader = new TestAssetReader();
var expectedPath = path.join(
path.dirname(inputPath), 'expected', path.basename(inputPath));
var expectedId = _assetIdForPath(expectedPath);
var output = await rewriteDeferredLibraries(reader, inputId);
var input = await reader.readAsString(expectedId);
if (input == null) {
// Null input signals no output. Ensure that is true.
expect(output).toBeNull();
} else {
expect(formatter.format(output)).toEqual(formatter.format(input));
}
});
}
AssetId _assetIdForPath(String path) =>
new AssetId('angular2', 'test/transform/deferred_rewriter/$path');
@@ -0,0 +1,17 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'hello.ng_deps.dart' deferred as a; // ng_deps. Should be rewritten.
import 'b.dart' deferred as b; // No ng_deps. Shouldn't be rewritten.
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
a.loadLibrary().then((_) {
a.initReflector();
}).then((_) {
bootstrap(a.HelloCmp);
});
b.loadLibrary();
}
@@ -0,0 +1,8 @@
library examples.src.hello_world.absolute_url_expression_files;
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
@Component(selector: 'hello-app')
@View(templateUrl: 'package:other_package/template.html')
class HelloCmp {}
@@ -0,0 +1,24 @@
library examples.src.hello_world.absolute_url_expression_files.ng_deps.dart;
import 'hello.dart';
export 'hello.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
var _visited = false;
void initReflector() {
if (_visited) return;
_visited = true;
_ngRef.reflector
..registerType(HelloCmp, {
'factory': () => new HelloCmp(),
'parameters': const [],
'annotations': const [
const Component(selector: 'hello-app'),
const View(
template: r'''{{greeting}}''',
templateUrl: r'package:other_package/template.html')
]
});
}
@@ -0,0 +1,15 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'hello.dart' deferred as a; // ng_deps. Should be rewritten.
import 'b.dart' deferred as b; // No ng_deps. Shouldn't be rewritten.
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
a.loadLibrary().then((_) {
bootstrap(a.HelloCmp);
});
b.loadLibrary();
}
@@ -0,0 +1,8 @@
library examples.src.hello_world.absolute_url_expression_files;
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
@Component(selector: 'hello-app')
@View(templateUrl: 'package:other_package/template.html')
class HelloCmp {}
@@ -0,0 +1,13 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'hello.dart' deferred as a;
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
a.loadLibrary().then((_) {
bootstrap(a.HelloCmp);
});
}
@@ -0,0 +1,10 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}
@@ -0,0 +1,11 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'a.dart' deferred as a;
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}
@@ -0,0 +1,15 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'hello.ng_deps.dart' deferred as a;
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
a.loadLibrary().then((_) {
a.initReflector();
}).then((_) {
bootstrap(a.HelloCmp);
});
}
@@ -0,0 +1,8 @@
library examples.src.hello_world.absolute_url_expression_files;
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
@Component(selector: 'hello-app')
@View(templateUrl: 'package:other_package/template.html')
class HelloCmp {}
@@ -0,0 +1,24 @@
library examples.src.hello_world.absolute_url_expression_files.ng_deps.dart;
import 'hello.dart';
export 'hello.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
var _visited = false;
void initReflector() {
if (_visited) return;
_visited = true;
_ngRef.reflector
..registerType(HelloCmp, {
'factory': () => new HelloCmp(),
'parameters': const [],
'annotations': const [
const Component(selector: 'hello-app'),
const View(
template: r'''{{greeting}}''',
templateUrl: r'package:other_package/template.html')
]
});
}
@@ -0,0 +1,13 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'hello.dart' deferred as a;
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
a.loadLibrary().then((_) {
bootstrap(a.HelloCmp);
});
}
@@ -1,6 +1,7 @@
library bar.ng_deps.dart;
import 'bar.dart';
export 'bar.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
export 'foo.dart';
@@ -1,6 +1,7 @@
library bar.ng_deps.dart;
import 'bar.dart';
export 'bar.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
export 'foo.dart';
@@ -1,6 +1,7 @@
library foo.ng_deps.dart;
import 'foo.dart';
export 'foo.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
@@ -1,6 +1,7 @@
library foo.ng_deps.dart;
import 'foo.dart';
export 'foo.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
@@ -1,6 +1,7 @@
library bar.ng_deps.dart;
import 'bar.dart';
export 'bar.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
import 'foo.dart' as dep;
@@ -1,6 +1,7 @@
library bar.ng_deps.dart;
import 'bar.dart';
export 'bar.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
import 'foo.dart' as dep;
@@ -1,6 +1,7 @@
library foo.ng_deps.dart;
import 'foo.dart';
export 'foo.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
@@ -1,6 +1,7 @@
library foo.ng_deps.dart;
import 'foo.dart';
export 'foo.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
@@ -1,6 +1,7 @@
library examples.src.hello_world.absolute_url_expression_files.ng_deps.dart;
import 'hello.dart';
export 'hello.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
@@ -1,6 +1,7 @@
library dinner.package_soup.ng_deps.dart;
import 'package_soup.dart';
export 'package_soup.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:soup/soup.dart';
@@ -1,6 +1,7 @@
library dinner.relative_soup.ng_deps.dart;
import 'relative_soup.dart';
export 'relative_soup.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'annotations/soup.dart';
@@ -1,6 +1,7 @@
library examples.src.hello_world.index_common_dart.ng_deps.dart;
import 'hello.dart';
export 'hello.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
@@ -1,6 +1,7 @@
library dinner.soup.ng_deps.dart;
import 'soup.dart';
export 'soup.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
@@ -1,6 +1,7 @@
library dinner.soup.ng_deps.dart;
import 'soup.dart';
export 'soup.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
@@ -1,6 +1,7 @@
library test.transform.directive_processor.invalid_url_files.hello.ng_deps.dart;
import 'hello.dart';
export 'hello.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
@@ -1,6 +1,7 @@
library examples.src.hello_world.multiple_style_urls_files.ng_deps.dart;
import 'hello.dart';
export 'hello.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
@@ -1,6 +1,7 @@
library examples.src.hello_world.multiple_style_urls_not_inlined_files.ng_deps.dart;
import 'hello.dart';
export 'hello.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
@@ -1,6 +1,7 @@
library dinner.soup.ng_deps.dart;
import 'soup.dart';
export 'soup.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
@@ -1,6 +1,7 @@
library examples.src.hello_world.split_url_expression_files.ng_deps.dart;
import 'hello.dart';
export 'hello.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
@@ -1,6 +1,7 @@
library static_function_files.hello.ng_deps.dart;
import 'hello.dart';
export 'hello.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/angular2.dart';
@@ -1,6 +1,7 @@
library dinner.soup.ng_deps.dart;
import 'soup.dart';
export 'soup.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
@@ -1,6 +1,7 @@
library examples.src.hello_world.url_expression_files.ng_deps.dart;
import 'hello.dart';
export 'hello.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
@@ -1,6 +1,7 @@
library bar.ng_deps.dart;
import 'bar.dart';
export 'bar.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
import 'foo.dart';
@@ -1,6 +1,7 @@
library bar.ng_deps.dart;
import 'bar.dart';
export 'bar.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
@@ -1,6 +1,7 @@
library web_foo.ng_deps.dart;
import 'index.dart';
export 'index.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection.dart';
@@ -1,6 +1,7 @@
library bar.ng_deps.dart;
import 'bar.dart';
export 'bar.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
@@ -4,6 +4,7 @@ import 'package:angular2/src/change_detection/pregen_proto_change_detector.dart'
as _gen;
import 'bar.dart';
export 'bar.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
import 'package:angular2/src/core/annotations_impl/view.dart';
@@ -1,6 +1,7 @@
library bar.ng_deps.dart;
import 'bar.dart';
export 'bar.dart';
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
import 'package:angular2/src/core/annotations_impl/annotations.dart';
import 'foo.dart' as prefix;
@@ -6,6 +6,7 @@ import 'package:unittest/vm_config.dart';
import 'common/async_string_writer_tests.dart' as asyncStringWriter;
import 'bind_generator/all_tests.dart' as bindGenerator;
import 'deferred_rewriter/all_tests.dart' as deferredRewriter;
import 'directive_linker/all_tests.dart' as directiveLinker;
import 'directive_metadata_extractor/all_tests.dart' as directiveMeta;
import 'directive_processor/all_tests.dart' as directiveProcessor;
@@ -22,6 +23,7 @@ main() {
describe('Directive Processor', directiveProcessor.allTests);
describe('Reflection Remover', reflectionRemover.allTests);
describe('Template Compiler', templateCompiler.allTests);
describe('Deferred Rewriter', deferredRewriter.allTests);
// NOTE(kegluneq): These use `code_transformers#testPhases`, which is not
// designed to work with `guinness`.
group('Transformer Pipeline', integration.allTests);