feat(dart/transform) Remove import of dart:mirrors

+ Precede the call to `new ReflectionCapabilities()` with our generated
code which populates the reflection map statically.
+ Add the import of our generated code.
+ Once we are generating all necessary code, we will remove the
import of reflection_capabilities.dart and the instantiation of
`ReflectionCapabilities`, cutting the dependency on dart:mirrors.

Closes #761
This commit is contained in:
Tim Blasi 2015-02-20 15:16:59 -08:00 committed by Misko Hevery
parent fad25c2b10
commit 3b6aaf9054
25 changed files with 339 additions and 187 deletions

View File

@ -54,7 +54,7 @@ class AnnotationMatcher {
}
}
/// [ConstructorElement] / [ElementAnnotation] pair, where the Constructor
/// [ClassElement] / [ElementAnnotation] pair.
class AnnotationMatch {
/// The resolved element corresponding to [node].
final ClassElement element;

View File

@ -60,6 +60,12 @@ abstract class DirectiveRegistry {
void register(AnnotationMatch entry);
}
const setupReflectionMethodName = 'setupReflection';
const _libraryDeclaration = '''
library angular2.src.transform.generated;
''';
const _reflectorImport = '''
import 'package:angular2/src/reflection/reflection.dart' show reflector;
''';
@ -70,18 +76,17 @@ AssetId _assetIdFromLibraryElement(LibraryElement el) {
return (el.source as dynamic).assetId;
}
String codegenEntryPoint(Context context,
{LibraryElement entryPoint, AssetId newEntryPoint}) {
// This must be called prior to [codegenImports] or the entry point
// library will not be imported.
var entryPointPrefix = context._getPrefixDot(entryPoint);
String codegenEntryPoint(Context context, {AssetId newEntryPoint}) {
if (newEntryPoint == null) {
throw new ArgumentError.notNull('newEntryPoint');
}
// TODO(jakemac): copyright and library declaration
var outBuffer = new StringBuffer(_reflectorImport);
var outBuffer = new StringBuffer()
..write(_libraryDeclaration)
..write(_reflectorImport);
_codegenImports(context, newEntryPoint, outBuffer);
outBuffer
..write('main() {')
..write(context.directiveRegistry.toString())
..write('${entryPointPrefix}main();}');
.write('${setupReflectionMethodName}() {${context.directiveRegistry}}');
return new DartFormatter().format(outBuffer.toString());
}

View File

@ -1,3 +1,5 @@
library angular2.src.transform;
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:code_transformers/resolver.dart';
@ -60,8 +62,8 @@ class _ParseBootstrapTypeVisitor extends SimpleAstVisitor<Object> {
// TODO(kegluneq): Allow non-SimpleIdentifier expressions.
@override
Object visitSimpleIdentifier(SimpleIdentifier e) {
bootstrapType = (e.bestElement as ClassElement);
Object visitSimpleIdentifier(SimpleIdentifier node) {
bootstrapType = (node.bestElement as ClassElement);
if (!_types.isComponent(bootstrapType)) {
throw new ArgumentError('Class passed to `${bootstrapMethodName}` must '
'be a @${_types.componentAnnotation.name}');
@ -71,7 +73,7 @@ class _ParseBootstrapTypeVisitor extends SimpleAstVisitor<Object> {
/// Recursively visits all nodes in an Ast structure, recording all encountered
/// calls to the provided [FunctionElement].
class _FindFunctionVisitor extends UnifyingAstVisitor<Object> {
class _FindFunctionVisitor extends RecursiveAstVisitor<Object> {
final FunctionElement _target;
_FindFunctionVisitor(this._target);

View File

@ -0,0 +1,152 @@
library angular2.src.transform;
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:barback/barback.dart';
import 'package:code_transformers/resolver.dart';
import 'package:dart_style/dart_style.dart';
import 'package:path/path.dart' as path;
import 'codegen.dart';
import 'logging.dart';
import 'resolvers.dart';
/// Finds all calls to the Angular2 [ReflectionCapabilities] constructor
/// defined in [library].
/// This only searches the code defined in the file
// represented by [library], not `part`s, `import`s, `export`s, etc.
String findReflectionCapabilities(
Resolver resolver, AssetId reflectionEntryPoint, AssetId newEntryPoint) {
var types = new Angular2Types(resolver);
if (types.reflectionCapabilities == null) {
throw new ArgumentError(
'Could not find class for ${reflectionCapabilitiesTypeName}.');
}
var codegen = new _SetupReflectionCodegen(
resolver, reflectionEntryPoint, newEntryPoint);
var writer = new PrintStringWriter();
var visitor = new _RewriteReflectionEntryPointVisitor(
writer, types.reflectionCapabilities, codegen);
// TODO(kegluneq): Determine how to get nodes without querying Element#node.
// Root of file defining that library (main part).
resolver.getLibrary(reflectionEntryPoint).definingCompilationUnit.node
.accept(visitor);
return new DartFormatter().format(writer.toString());
}
class _SetupReflectionCodegen {
static const _prefixBase = 'ngStaticInit';
final String prefix;
final String importUri;
_SetupReflectionCodegen._internal(this.prefix, this.importUri);
factory _SetupReflectionCodegen(
Resolver resolver, AssetId reflectionEntryPoint, AssetId newEntryPoint) {
var lib = resolver.getLibrary(reflectionEntryPoint);
var prefix = _prefixBase;
var idx = 0;
while (lib.imports.any((import) {
return import.prefix != null && import.prefix == prefix;
})) {
prefix = '${_prefixBase}${idx++}';
}
var importPath = path.relative(newEntryPoint.path,
from: path.dirname(reflectionEntryPoint.path));
return new _SetupReflectionCodegen._internal(prefix, importPath);
}
/// Generates code to import the library containing the method which sets up
/// Angular2 reflection statically.
///
/// The code generated here should follow the example of code generated for
/// an [ImportDirective] node.
String codegenImport() {
return 'import \'${importUri}\' as ${prefix};';
}
/// Generates code to call the method which sets up Angular2 reflection
/// statically.
///
/// The code generated here should follow the example of code generated for
/// a [MethodInvocation] node, that is, it should be prefixed as necessary
/// and not be followed by a ';'.
String codegenSetupReflectionCall() {
return '${prefix}.${setupReflectionMethodName}()';
}
}
class _RewriteReflectionEntryPointVisitor extends ToSourceVisitor {
final PrintWriter _writer;
final ClassElement _forbiddenClass;
final _SetupReflectionCodegen _codegen;
_RewriteReflectionEntryPointVisitor(
PrintWriter writer, this._forbiddenClass, this._codegen)
: _writer = writer,
super(writer);
bool _isNewReflectionCapabilities(InstanceCreationExpression node) {
var typeElement = node.constructorName.type.name.bestElement;
return typeElement != null && typeElement == _forbiddenClass;
}
bool _isReflectionCapabilitiesImport(ImportDirective node) {
return node.uriElement == _forbiddenClass.library;
}
@override
Object visitImportDirective(ImportDirective node) {
if (_isReflectionCapabilitiesImport(node)) {
// TODO(kegluneq): Remove newlines once dart_style bug is fixed.
// https://github.com/dart-lang/dart_style/issues/178
// _writer.print('\n/* ReflectionCapabilities import removed */\n');
_writer.print(_codegen.codegenImport());
// TODO(kegluneq): Remove once we generate all needed code.
{
super.visitImportDirective(node);
}
return null;
}
return super.visitImportDirective(node);
}
@override
Object visitAssignmentExpression(AssignmentExpression node) {
if (node.rightHandSide is InstanceCreationExpression &&
_isNewReflectionCapabilities(node.rightHandSide)) {
// TODO(kegluneq): Remove newlines once dart_style bug is fixed.
// https://github.com/dart-lang/dart_style/issues/178
// _writer.print('/* Creation of ReflectionCapabilities removed */\n');
_writer.print(_codegen.codegenSetupReflectionCall());
// TODO(kegluneq): Remove once we generate all needed code.
{
_writer.print(';');
node.leftHandSide.accept(this);
_writer.print(' ${node.operator.lexeme} ');
super.visitInstanceCreationExpression(node.rightHandSide);
}
return null;
}
return super.visitAssignmentExpression(node);
}
@override
Object visitInstanceCreationExpression(InstanceCreationExpression node) {
if (_isNewReflectionCapabilities(node)) {
logger.error('Unexpected format in creation of '
'${reflectionCapabilitiesTypeName}');
} else {
return super.visitInstanceCreationExpression(node);
}
return null;
}
}

View File

@ -1,52 +0,0 @@
library angular2.src.transform;
import 'dart:async';
import 'package:barback/barback.dart';
import 'package:html5lib/dom.dart' as dom;
import 'package:html5lib/parser.dart' show parse;
import 'package:path/path.dart' as path;
import 'options.dart';
Future transformHtmlEntryPoint(
TransformerOptions options, Transform transform) {
// For now at least, [options.htmlEntryPoint], [options.entryPoint], and
// [options.newEntryPoint] need to be in the same folder.
// TODO(jakemac): support package urls with [options.entryPoint] or
// [options.newEntryPoint] in `lib`, and [options.htmlEntryPoint] in another
// directory.
var _expectedDir = path.split(options.htmlEntryPoint)[0];
if (!options.inSameTopLevelDir()) {
transform.logger.error(
'${options.htmlEntryPointParam}, ${options.entryPointParam}, and '
'${options.newEntryPointParam} (if supplied) all must be in the '
'same top level directory.');
}
// The relative path from [options.htmlEntryPoint] to [dartEntry]. You must
// ensure that neither of these is null before calling this function.
String _relativeDartEntryPath(String dartEntry) =>
path.relative(dartEntry, from: path.dirname(options.htmlEntryPoint));
// Checks if the src of this script tag is pointing at `options.entryPoint`.
bool _isEntryPointScript(dom.Element script) =>
path.normalize(script.attributes['src']) ==
_relativeDartEntryPath(options.entryPoint);
return transform.primaryInput.readAsString().then((String html) {
var found = false;
var doc = parse(html);
var scripts = doc.querySelectorAll('script[type="application/dart"]');
for (dom.Element script in scripts) {
if (!_isEntryPointScript(script)) continue;
script.attributes['src'] = _relativeDartEntryPath(options.newEntryPoint);
found = true;
}
if (!found) {
transform.logger.error('Unable to find script for ${options.entryPoint} '
'in ${options.htmlEntryPoint}.');
}
return transform.addOutput(
new Asset.fromString(transform.primaryInput.id, doc.outerHtml));
});
}

View File

@ -1,28 +1,41 @@
library angular2.src.transform;
import 'package:path/path.dart' as path;
const entryPointParam = 'entry_point';
const reflectionEntryPointParam = 'reflection_entry_point';
const newEntryPointParam = 'new_entry_point';
/// Provides information necessary to transform an Angular2 app.
class TransformerOptions {
/// The file where the application's call to [bootstrap] is.
// TODO(kegluenq): Allow multiple bootstrap entry points.
final String bootstrapEntryPoint;
/// The Dart entry point, that is, where the initial call to [main] occurs.
// TODO(kegluneq): Allow multiple entry points.
final String entryPoint;
/// The reflection entry point, that is, where the
/// application's [ReflectionCapabilities] are set.
final String reflectionEntryPoint;
/// The path where we should generate code.
final String newEntryPoint;
/// The html file that includes [entryPoint].
final String htmlEntryPoint;
TransformerOptions._internal(
this.entryPoint, this.reflectionEntryPoint, this.newEntryPoint);
TransformerOptions(this.bootstrapEntryPoint, this.entryPoint,
this.newEntryPoint, this.htmlEntryPoint);
bool inSameTopLevelDir() {
var expectedDir = path.split(htmlEntryPoint)[0];
return (expectedDir == path.split(entryPoint)[0] &&
expectedDir == path.split(newEntryPoint)[0]);
factory TransformerOptions(String entryPoint,
{String reflectionEntryPoint, String newEntryPoint}) {
if (entryPoint == null || entryPoint.isEmpty) {
throw new ArgumentError.notNull(entryPointParam);
}
if (reflectionEntryPoint == null || entryPoint.isEmpty) {
reflectionEntryPoint = entryPoint;
}
if (newEntryPoint == null || newEntryPoint.isEmpty) {
newEntryPoint =
reflectionEntryPoint.replaceFirst('.dart', '.bootstrap.dart');
if (newEntryPoint == reflectionEntryPoint) {
newEntryPoint = 'bootstrap.${newEntryPoint}';
}
}
return new TransformerOptions._internal(
entryPoint, reflectionEntryPoint, newEntryPoint);
}
}

View File

@ -47,6 +47,7 @@ Resolvers createResolvers() {
}
const bootstrapMethodName = 'bootstrap';
const reflectionCapabilitiesTypeName = 'ReflectionCapabilities';
/// Provides resolved [Elements] for well-known Angular2 symbols.
class Angular2Types {
@ -57,6 +58,8 @@ class Angular2Types {
new AssetId('angular2', 'lib/src/core/application.dart');
static final _templateLibAssetId =
new AssetId('angular2', 'lib/src/core/annotations/template.dart');
static final _reflectionCapabilitiesLibAssetId = new AssetId(
'angular2', 'lib/src/reflection/reflection_capabilities.dart');
final Resolver _resolver;
FunctionElement _bootstrapMethod;
@ -84,6 +87,12 @@ class Angular2Types {
ClassElement get templateAnnotation => _getTypeSafe(templateLib, 'Template');
LibraryElement get reflectionCapabilitiesLib =>
_resolver.getLibrary(_reflectionCapabilitiesLibAssetId);
ClassElement get reflectionCapabilities =>
_getTypeSafe(reflectionCapabilitiesLib, reflectionCapabilitiesTypeName);
LibraryElement get applicationLib =>
_resolver.getLibrary(_applicationLibAssetId);

View File

@ -9,7 +9,7 @@ import 'package:code_transformers/resolver.dart';
import 'annotation_processor.dart';
import 'codegen.dart' as codegen;
import 'find_bootstrap.dart';
import 'html_transform.dart';
import 'find_reflection_capabilities.dart';
import 'logging.dart' as log;
import 'options.dart';
import 'resolvers.dart';
@ -25,61 +25,72 @@ class AngularTransformer extends Transformer {
AngularTransformer(this.options) : _resolvers = createResolvers();
static const _bootstrapEntryPointParam = 'bootstrap_entry_point';
static const _entryPointParam = 'entry_point';
static const _newEntryPointParam = 'new_entry_point';
static const _htmlEntryPointParam = 'html_entry_point';
factory AngularTransformer.asPlugin(BarbackSettings settings) {
var bootstrapEntryPoint = settings.configuration[_bootstrapEntryPointParam];
var entryPoint = settings.configuration[_entryPointParam];
var newEntryPoint = settings.configuration[_newEntryPointParam];
if (newEntryPoint == null) {
newEntryPoint = entryPoint.replaceFirst('.dart', '.bootstrap.dart');
}
var htmlEntryPoint = settings.configuration[_htmlEntryPointParam];
var config = settings.configuration;
return new AngularTransformer(new TransformerOptions(
bootstrapEntryPoint, entryPoint, newEntryPoint, htmlEntryPoint));
config[entryPointParam],
reflectionEntryPoint: config[reflectionEntryPointParam],
newEntryPoint: config[newEntryPointParam]));
}
bool isPrimary(AssetId id) =>
options.entryPoint == id.path || options.htmlEntryPoint == id.path;
bool isPrimary(AssetId id) => options.reflectionEntryPoint == id.path;
Future apply(Transform transform) {
log.init(transform);
if (transform.primaryInput.id.path == options.entryPoint) {
return _buildBootstrapFile(transform);
} else if (transform.primaryInput.id.path == options.htmlEntryPoint) {
return transformHtmlEntryPoint(options, transform);
}
return null;
}
Future _buildBootstrapFile(Transform transform) {
var bootstrapEntryPointId = new AssetId(
transform.primaryInput.id.package, options.bootstrapEntryPoint);
var entryPointId =
new AssetId(transform.primaryInput.id.package, options.entryPoint);
var reflectionEntryPointId = new AssetId(
transform.primaryInput.id.package, options.reflectionEntryPoint);
var newEntryPointId =
new AssetId(transform.primaryInput.id.package, options.newEntryPoint);
return transform.hasInput(newEntryPointId).then((exists) {
if (exists) {
var reflectionExists = transform.hasInput(reflectionEntryPointId);
var newEntryPointExists = transform.hasInput(newEntryPointId);
Resolver myResolver;
return Future
.wait([reflectionExists, newEntryPointExists])
.then((existsList) {
if (!existsList[0]) {
log.logger.error('Reflection entry point file '
'${reflectionEntryPointId} does not exist.');
} else if (existsList[1]) {
log.logger
.error('New entry point file $newEntryPointId already exists.');
} else {
return _resolvers.get(transform).then((resolver) {
return _resolvers
.get(transform, [entryPointId, reflectionEntryPointId])
.then((resolver) {
myResolver = resolver;
try {
new _BootstrapFileBuilder(resolver, transform,
transform.primaryInput.id, bootstrapEntryPointId,
newEntryPointId).run();
String reflectionCapabilitiesCreation = findReflectionCapabilities(
resolver, reflectionEntryPointId, newEntryPointId);
transform.addOutput(new Asset.fromString(
reflectionEntryPointId, reflectionCapabilitiesCreation));
// Find the call to `new ReflectionCapabilities()`
// Generate new source.
} catch (err, stackTrace) {
log.logger.error('${err}: ${stackTrace}',
asset: bootstrapEntryPointId);
asset: reflectionEntryPointId);
rethrow;
}
try {
new _BootstrapFileBuilder(
resolver, transform, entryPointId, newEntryPointId).run();
} catch (err, stackTrace) {
log.logger.error('${err}: ${stackTrace}',
asset: transform.primaryInput.id);
rethrow;
} finally {
resolver.release();
}
});
}
}).whenComplete(() {
if (myResolver != null) {
myResolver.release();
}
});
}
}
@ -87,21 +98,18 @@ class AngularTransformer extends Transformer {
class _BootstrapFileBuilder {
final Resolver _resolver;
final Transform _transform;
final AssetId _bootstrapEntryPoint;
final AssetId _entryPoint;
final AssetId _newEntryPoint;
_BootstrapFileBuilder(Resolver resolver, Transform transform,
this._entryPoint, this._bootstrapEntryPoint, this._newEntryPoint)
this._entryPoint, this._newEntryPoint)
: _resolver = resolver,
_transform = transform;
/// Adds the new entry point file to the transform. Should only be ran once.
void run() {
var entryLib = _resolver.getLibrary(_entryPoint);
Set<BootstrapCallInfo> bootstrapCalls = findBootstrapCalls(
_resolver, _resolver.getLibrary(_bootstrapEntryPoint));
Set<BootstrapCallInfo> bootstrapCalls =
findBootstrapCalls(_resolver, _resolver.getLibrary(_entryPoint));
log.logger.info('found ${bootstrapCalls.length} call(s) to `bootstrap`');
bootstrapCalls.forEach((BootstrapCallInfo info) {
@ -123,8 +131,7 @@ class _BootstrapFileBuilder {
matcher.matchQueue
.forEach((entry) => context.directiveRegistry.register(entry));
_transform.addOutput(new Asset.fromString(_newEntryPoint, codegen
.codegenEntryPoint(context,
entryPoint: entryLib, newEntryPoint: _newEntryPoint)));
_transform.addOutput(new Asset.fromString(_newEntryPoint,
codegen.codegenEntryPoint(context, newEntryPoint: _newEntryPoint)));
}
}

View File

@ -1,3 +0,0 @@
<html><head></head><body>
<script type="application/dart" src="index.dart"></script>
</body></html>

View File

@ -1,3 +0,0 @@
<html><head></head><body>
<script type="application/dart" src="index.bootstrap.dart"></script>
</body></html>

View File

@ -1,6 +0,0 @@
library web_foo;
import 'package:angular2/src/core/annotations/annotations.dart';
import 'package:angular2/src/core/application.dart';
void main() {}

View File

@ -1,10 +1,11 @@
library angular2.src.transform.generated;
import 'package:angular2/src/reflection/reflection.dart' show reflector;
import 'bar.dart' as i0;
import 'foo.dart' as i1;
import 'package:angular2/src/core/annotations/annotations.dart' as i2;
import 'index.dart' as i3;
main() {
setupReflection() {
reflector
..registerType(i0.MyComponent, {
"factory": (i1.MyContext c) => new i0.MyComponent(c),
@ -13,5 +14,4 @@ main() {
const i2.Component(componentServices: const [i1.MyContext])
]
});
i3.main();
}

View File

@ -1,8 +1,10 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'bar.dart';
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}

View File

@ -0,0 +1,9 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library angular2.test.transform;
/// Mocked out version of [ReflectionCapabilities], defined in
/// src/reflection/reflection_capabilities.dart. Importing the actual file in
/// tests causes issues with resolution due to transitive dependencies.
class ReflectionCapabilities {}

View File

@ -1,14 +1,14 @@
library angular2.src.transform.generated;
import 'package:angular2/src/reflection/reflection.dart' show reflector;
import 'bar.dart' as i0;
import 'package:angular2/src/core/annotations/annotations.dart' as i1;
import 'index.dart' as i2;
main() {
setupReflection() {
reflector
..registerType(i0.MyComponent, {
"factory": () => new i0.MyComponent(),
"parameters": const [const []],
"annotations": const [const i1.Component(selector: '[soup]')]
});
i2.main();
}

View File

@ -0,0 +1,13 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection.dart';
import 'index.bootstrap.dart' as ngStaticInit;
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'bar.dart';
void main() {
ngStaticInit.setupReflection();
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}

View File

@ -1,8 +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 'bar.dart';
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}

View File

@ -1,14 +1,14 @@
library angular2.src.transform.generated;
import 'package:angular2/src/reflection/reflection.dart' show reflector;
import 'bar.dart' as i0;
import 'package:angular2/src/core/annotations/annotations.dart' as i1;
import 'index.dart' as i2;
main() {
setupReflection() {
reflector
..registerType(i0.MyComponent, {
"factory": () => new i0.MyComponent(),
"parameters": const [const []],
"annotations": const [const i1.Component(selector: '[soup]')]
});
i2.main();
}

View File

@ -1,8 +1,10 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'bar.dart';
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}

View File

@ -18,7 +18,8 @@ main() {
var formatter = new DartFormatter();
var transform = new AngularTransformer(new TransformerOptions('web/index.dart',
'web/index.dart', 'web/index.bootstrap.dart', 'web/index.html'));
reflectionEntryPoint: 'web/index.dart',
newEntryPoint: 'web/index.bootstrap.dart'));
class TestConfig {
final String name;
@ -32,42 +33,37 @@ class TestConfig {
}
void _runTests() {
// Each test has its own directory for inputs & an `expected` directory for
// expected outputs.
/*
* Each test has its own directory for inputs & an `expected` directory for
* expected outputs.
*
* In addition to these declared inputs, we inject a set of common inputs for
* every test.
*/
var commonInputs = {
'angular2|lib/src/core/annotations/annotations.dart':
'../../lib/src/core/annotations/annotations.dart',
'angular2|lib/src/core/application.dart': 'common.dart',
'angular2|lib/src/reflection/reflection_capabilities.dart':
'reflection_capabilities.dart'
};
var tests = [
new TestConfig('Html entry point',
inputs: {
'a|web/index.html': 'common.html',
'a|web/index.dart': 'html_entry_point_files/index.dart',
'angular2|lib/src/core/annotations/annotations.dart':
'../../lib/src/core/annotations/annotations.dart',
'angular2|lib/src/core/application.dart': 'common.dart'
},
outputs: {
'a|web/index.html': 'html_entry_point_files/expected/index.html'
}),
new TestConfig('Simple',
inputs: {
'a|web/index.html': 'common.html',
'a|web/index.dart': 'simple_annotation_files/index.dart',
'a|web/bar.dart': 'simple_annotation_files/bar.dart',
'angular2|lib/src/core/annotations/annotations.dart':
'../../lib/src/core/annotations/annotations.dart',
'angular2|lib/src/core/application.dart': 'common.dart'
'a|web/bar.dart': 'simple_annotation_files/bar.dart'
},
outputs: {
'a|web/index.bootstrap.dart':
'simple_annotation_files/expected/index.bootstrap.dart'
'simple_annotation_files/expected/index.bootstrap.dart',
'a|web/index.dart': 'simple_annotation_files/expected/index.dart',
}),
new TestConfig('Two injected dependencies',
inputs: {
'a|web/index.html': 'common.html',
'a|web/index.dart': 'two_deps_files/index.dart',
'a|web/foo.dart': 'two_deps_files/foo.dart',
'a|web/bar.dart': 'two_deps_files/bar.dart',
'angular2|lib/src/core/annotations/annotations.dart':
'../../lib/src/core/annotations/annotations.dart',
'angular2|lib/src/core/application.dart': 'common.dart'
'a|web/bar.dart': 'two_deps_files/bar.dart'
},
outputs: {
'a|web/index.bootstrap.dart':
@ -75,7 +71,6 @@ void _runTests() {
}),
new TestConfig('List of types',
inputs: {
'a|web/index.html': 'common.html',
'a|web/index.dart': 'list_of_types_files/index.dart',
'a|web/foo.dart': 'list_of_types_files/foo.dart',
'a|web/bar.dart': 'list_of_types_files/bar.dart',
@ -89,7 +84,6 @@ void _runTests() {
}),
new TestConfig('Component with synthetic Constructor',
inputs: {
'a|web/index.html': 'common.html',
'a|web/index.dart': 'synthetic_ctor_files/index.dart',
'a|web/bar.dart': 'synthetic_ctor_files/bar.dart',
'angular2|lib/src/core/annotations/annotations.dart':
@ -102,7 +96,6 @@ void _runTests() {
}),
new TestConfig('Component with two annotations',
inputs: {
'a|web/index.html': 'common.html',
'a|web/index.dart': 'two_annotations_files/index.dart',
'a|web/bar.dart': 'two_annotations_files/bar.dart',
'angular2|lib/src/core/annotations/annotations.dart':
@ -114,17 +107,20 @@ void _runTests() {
outputs: {
'a|web/index.bootstrap.dart':
'two_annotations_files/expected/index.bootstrap.dart'
}),
})
];
var cache = {};
for (var config in tests) {
// Read in input & output files.
config.assetPathToInputPath.forEach((key, value) {
config.assetPathToInputPath[key] =
cache.putIfAbsent(value, () => new File('test/transform/${value}').readAsStringSync());
});
config.assetPathToInputPath
..addAll(commonInputs)
..forEach((key, value) {
config.assetPathToInputPath[key] = cache.putIfAbsent(value,
() => new File('test/transform/${value}').readAsStringSync());
});
config.assetPathToExpectedOutputPath.forEach((key, value) {
config.assetPathToExpectedOutputPath[key] = cache.putIfAbsent(value, () {
var code = new File('test/transform/${value}').readAsStringSync();

View File

@ -1,10 +1,11 @@
library angular2.src.transform.generated;
import 'package:angular2/src/reflection/reflection.dart' show reflector;
import 'bar.dart' as i0;
import 'package:angular2/src/core/annotations/annotations.dart' as i1;
import 'package:angular2/src/core/annotations/template.dart' as i2;
import 'index.dart' as i3;
main() {
setupReflection() {
reflector
..registerType(i0.MyComponent, {
"factory": () => new i0.MyComponent(),
@ -14,5 +15,4 @@ main() {
const i2.Template(inline: 'Salad')
]
});
i3.main();
}

View File

@ -1,8 +1,10 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'bar.dart';
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}

View File

@ -1,10 +1,11 @@
library angular2.src.transform.generated;
import 'package:angular2/src/reflection/reflection.dart' show reflector;
import 'bar.dart' as i0;
import 'foo.dart' as i1;
import 'package:angular2/src/core/annotations/annotations.dart' as i2;
import 'index.dart' as i3;
main() {
setupReflection() {
reflector
..registerType(i0.MyComponent, {
"factory":
@ -12,5 +13,4 @@ main() {
"parameters": const [const [i1.MyContext, String]],
"annotations": const [const i2.Component(selector: i1.preDefinedSelector)]
});
i3.main();
}

View File

@ -1,8 +1,10 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'bar.dart';
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}

View File

@ -11,9 +11,8 @@ dev_dependencies:
path: ../benchpress
transformers:
- angular2:
bootstrap_entry_point: web/src/hello_world/index_common.dart
entry_point: web/src/hello_world/index.dart
html_entry_point: web/src/hello_world/index.html
entry_point: web/src/hello_world/index_common.dart
reflection_entry_point: web/src/hello_world/index.dart
- $dart2js:
minify: true
commandLineOptions: [--trust-type-annotations, --trust-primitives, --dump-info]