feat(dart/transform): Use the render Compiler and the DirectiveParser

Update the `TemplateCompile` step to use the full render `Compiler`.

Provide `DirectiveMetadata` for `ViewDefinition` objects and use it to
run the `DirectiveParser` step of the render compile pipeline.
This commit is contained in:
Tim Blasi 2015-05-05 10:31:21 -07:00 committed by Misko Hevery
parent 401c9efad7
commit 44f829dbc6
24 changed files with 576 additions and 93 deletions

View File

@ -83,7 +83,16 @@ class Html5LibDomAdapter implements DomAdapter {
throw 'not implemented';
}
String nodeName(node) {
throw 'not implemented';
switch (node.nodeType) {
case Node.ELEMENT_NODE:
return (node as Element).localName;
case Node.TEXT_NODE:
return '#text';
default:
throw 'not implemented for type ${node.nodeType}. '
'See http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-1950641247'
' for node types definitions.';
}
}
String nodeValue(node) => node.data;
String type(node) {
@ -179,9 +188,8 @@ class Html5LibDomAdapter implements DomAdapter {
getElementsByTagName(element, String name) {
throw 'not implemented';
}
List classList(element) {
throw 'not implemented';
}
List classList(element) => element.classes.toList();
addClass(element, String classname) {
element.classes.add(classname);
}

View File

@ -9,6 +9,9 @@ import 'parser.dart';
DirectiveMetadata readDirectiveMetadata(RegisteredType t) {
var visitor = new _DirectiveMetadataVisitor();
t.annotations.accept(visitor);
if (visitor.meta != null) {
visitor.meta.id = '${t.typeName}';
}
return visitor.meta;
}

View File

@ -68,7 +68,8 @@ class NgDeps {
final List<ImportDirective> imports = [];
final List<ExportDirective> exports = [];
final List<RegisteredType> registeredTypes = [];
FunctionDeclaration setupMethod;
LibraryDirective lib = null;
FunctionDeclaration setupMethod = null;
NgDeps(this.code);
}
@ -76,6 +77,12 @@ class NgDeps {
class _ParseNgDepsVisitor extends Object with RecursiveAstVisitor<Object> {
NgDeps ngDeps = null;
@override
Object visitLibraryDirective(LibraryDirective node) {
ngDeps.lib = node;
return null;
}
@override
Object visitImportDirective(ImportDirective node) {
ngDeps.imports.add(node);

View File

@ -6,6 +6,7 @@ import 'package:angular2/src/render/api.dart';
import 'package:angular2/src/render/dom/compiler/compile_step.dart';
import 'package:angular2/src/render/dom/compiler/compile_step_factory.dart'
as base;
import 'package:angular2/src/render/dom/compiler/directive_parser.dart';
import 'package:angular2/src/render/dom/compiler/property_binding_parser.dart';
import 'package:angular2/src/render/dom/compiler/text_interpolation_parser.dart';
import 'package:angular2/src/render/dom/compiler/view_splitter.dart';
@ -20,6 +21,7 @@ class CompileStepFactory implements base.CompileStepFactory {
return [
new ViewSplitter(_parser),
new PropertyBindingParser(_parser),
new DirectiveParser(_parser, template.directives),
new TextInterpolationParser(_parser)
];
}

View File

@ -2,24 +2,22 @@ library angular2.transform.template_compiler.generator;
import 'dart:async';
import 'package:analyzer/analyzer.dart';
import 'package:angular2/src/change_detection/parser/lexer.dart' as ng;
import 'package:angular2/src/change_detection/parser/parser.dart' as ng;
import 'package:angular2/src/render/api.dart';
import 'package:angular2/src/render/dom/compiler/compile_pipeline.dart';
import 'package:angular2/src/render/dom/compiler/compiler.dart';
import 'package:angular2/src/render/dom/compiler/template_loader.dart';
import "package:angular2/src/services/xhr.dart" show XHR;
import 'package:angular2/src/reflection/reflection.dart';
import 'package:angular2/src/services/url_resolver.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/parser.dart';
import 'package:angular2/src/transform/common/property_utils.dart' as prop;
import 'package:barback/barback.dart';
import 'compile_step_factory.dart';
import 'recording_reflection_capabilities.dart';
import 'view_definition_creator.dart';
import 'xhr_impl.dart';
/// Reads the `.ng_deps.dart` file represented by `entryPoint` and parses any
@ -28,42 +26,40 @@ import 'xhr_impl.dart';
///
/// This method assumes a {@link DomAdapter} has been registered.
Future<String> processTemplates(AssetReader reader, AssetId entryPoint) async {
var parser = new Parser(reader);
NgDeps ngDeps = await parser.parse(entryPoint);
var viewDefResults = await createViewDefinitions(reader, entryPoint);
var extractor = new _TemplateExtractor(new XhrImpl(reader, entryPoint));
var registrations = new StringBuffer();
for (var rType in ngDeps.registeredTypes) {
var values = await extractor.extractTemplates(rType);
for (var viewDef in viewDefResults.viewDefinitions.values) {
var values = await extractor.extractTemplates(viewDef);
if (values == null) continue;
var calls = _generateGetters('${rType.typeName}', values.getterNames);
var calls = _generateGetters(values.getterNames);
if (calls.isNotEmpty) {
registrations.write('..${REGISTER_GETTERS_METHOD_NAME}'
'({${calls.join(', ')}})');
}
calls = _generateSetters('${rType.typeName}', values.setterNames);
calls = _generateSetters(values.setterNames);
if (calls.isNotEmpty) {
registrations.write('..${REGISTER_SETTERS_METHOD_NAME}'
'({${calls.join(', ')}})');
}
calls = _generateMethods('${rType.typeName}', values.methodNames);
calls = _generateMethods(values.methodNames);
if (calls.isNotEmpty) {
registrations.write('..${REGISTER_METHODS_METHOD_NAME}'
'({${calls.join(', ')}})');
}
}
var code = ngDeps.code;
var code = viewDefResults.ngDeps.code;
if (registrations.length == 0) return code;
var codeInjectIdx = ngDeps.registeredTypes.last.registerMethod.end;
var codeInjectIdx =
viewDefResults.ngDeps.registeredTypes.last.registerMethod.end;
return '${code.substring(0, codeInjectIdx)}'
'${registrations}'
'${code.substring(codeInjectIdx)}';
}
Iterable<String> _generateGetters(
String typeName, Iterable<String> getterNames) {
// TODO(kegluneq): Include `typeName` where possible.
Iterable<String> _generateGetters(Iterable<String> getterNames) {
return getterNames.map((getterName) {
if (!prop.isValid(getterName)) {
// TODO(kegluenq): Eagerly throw here once #1295 is addressed.
@ -74,8 +70,7 @@ Iterable<String> _generateGetters(
});
}
Iterable<String> _generateSetters(
String typeName, Iterable<String> setterName) {
Iterable<String> _generateSetters(Iterable<String> setterName) {
return setterName.map((setterName) {
if (!prop.isValid(setterName)) {
// TODO(kegluenq): Eagerly throw here once #1295 is addressed.
@ -87,8 +82,7 @@ Iterable<String> _generateSetters(
});
}
Iterable<String> _generateMethods(
String typeName, Iterable<String> methodNames) {
Iterable<String> _generateMethods(Iterable<String> methodNames) {
return methodNames.map((methodName) {
if (!prop.isValid(methodName)) {
// TODO(kegluenq): Eagerly throw here once #1295 is addressed.
@ -104,85 +98,25 @@ Iterable<String> _generateMethods(
/// template code if necessary, and determines what values will be
/// reflectively accessed from that template.
class _TemplateExtractor {
final CompileStepFactory _factory;
final _TemplateExtractVisitor _visitor = new _TemplateExtractVisitor();
final TemplateLoader _loader;
final RenderCompiler _compiler;
_TemplateExtractor(XHR xhr)
: _loader = new TemplateLoader(xhr, new UrlResolver()),
_factory = new CompileStepFactory(new ng.Parser(new ng.Lexer()));
_TemplateExtractor(XHR xhr) : _compiler = new DomCompiler(
new CompileStepFactory(new ng.Parser(new ng.Lexer())),
new TemplateLoader(xhr, new UrlResolver()));
Future<RecordingReflectionCapabilities> extractTemplates(RegisteredType t) {
return _processTemplate(_processRegisteredType(t));
}
Future<RecordingReflectionCapabilities> _processTemplate(
Future<RecordingReflectionCapabilities> extractTemplates(
ViewDefinition viewDef) async {
// Check for "imperative views".
if (viewDef.template == null && viewDef.absUrl == null) return null;
var recordingCapabilities = new RecordingReflectionCapabilities();
var savedReflectionCapabilities = reflector.reflectionCapabilities;
var recordingCapabilities = new RecordingReflectionCapabilities();
reflector.reflectionCapabilities = recordingCapabilities;
// TODO(kegluneq): Rewrite url to inline `template` where possible.
// See [https://github.com/angular/angular/issues/1035].
var domNode = await _loader.load(viewDef);
new CompilePipeline(_factory.createSteps(viewDef, [])).process(
domNode, '$domNode');
await _compiler.compile(viewDef);
reflector.reflectionCapabilities = savedReflectionCapabilities;
return recordingCapabilities;
}
ViewDefinition _processRegisteredType(RegisteredType t) {
_visitor.reset();
t.annotations.accept(_visitor);
return _visitor.viewDef;
}
}
/// Visitor responsible for processing the `annotations` property of a
/// {@link RegisterType} object and pulling out template information.
class _TemplateExtractVisitor extends Object with RecursiveAstVisitor<Object> {
ViewDefinition viewDef = new ViewDefinition();
void reset() {
viewDef = new ViewDefinition();
}
@override
Object visitNamedExpression(NamedExpression node) {
// TODO(kegluneq): Remove this limitation.
if (node.name is! Label || node.name.label is! SimpleIdentifier) {
logger.error(
'Angular 2 currently only supports simple identifiers in directives.'
' Source: ${node}');
return null;
}
var keyString = '${node.name.label}';
if (keyString == 'template' || keyString == 'templateUrl') {
if (node.expression is! SimpleStringLiteral) {
logger.error(
'Angular 2 currently only supports string literals in directives.'
' Source: ${node}');
return null;
}
var valueString = stringLiteralToString(node.expression);
if (keyString == 'templateUrl') {
if (viewDef.absUrl != null) {
logger.error(
'Found multiple values for "templateUrl". Source: ${node}');
}
viewDef.absUrl = valueString;
} else {
if (viewDef.template != null) {
logger.error('Found multiple values for "template". Source: ${node}');
}
viewDef.template = valueString;
}
}
return null;
}
}

View File

@ -0,0 +1,232 @@
library angular2.transform.template_compiler.view_definition_creator;
import 'dart:async';
import 'dart:convert';
import 'package:analyzer/analyzer.dart';
import 'package:angular2/src/render/api.dart';
import 'package:angular2/src/render/dom/convert.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/parser.dart';
import 'package:barback/barback.dart';
import 'package:code_transformers/assets.dart';
/// Creates [ViewDefinition] objects for all `View` `Directive`s defined in
/// `entryPoint`.
Future<ViewDefinitionResults> createViewDefinitions(
AssetReader reader, AssetId entryPoint) async {
return await new _ViewDefinitionCreator(reader, entryPoint).createViewDefs();
}
class ViewDefinitionResults {
final NgDeps ngDeps;
final Map<RegisteredType, ViewDefinition> viewDefinitions;
ViewDefinitionResults._(this.ngDeps, this.viewDefinitions);
}
String _getComponentId(AssetId assetId, String className) =>
'$assetId:$className';
/// Creates [ViewDefinition] objects for all `View` `Directive`s defined in
/// `entryPoint`.
class _ViewDefinitionCreator {
final AssetReader reader;
final AssetId entryPoint;
final Future<NgDeps> ngDepsFuture;
_ViewDefinitionCreator(AssetReader reader, AssetId entryPoint)
: this.reader = reader,
this.entryPoint = entryPoint,
ngDepsFuture = new Parser(reader).parse(entryPoint);
Future<ViewDefinitionResults> createViewDefs() async {
var ngDeps = await ngDepsFuture;
var retVal = <RegisteredType, ViewDefinition>{};
var visitor = new _TemplateExtractVisitor(await _createMetadataMap());
ngDeps.registeredTypes.forEach((rType) {
visitor.reset();
rType.annotations.accept(visitor);
if (visitor.viewDef != null) {
var typeName = '${rType.typeName}';
if (visitor._metadataMap.containsKey(typeName)) {
visitor.viewDef.componentId = visitor._metadataMap[typeName].id;
} else {
logger.warning('Missing component "$typeName" in metadata map',
asset: entryPoint);
visitor.viewDef.componentId = _getComponentId(entryPoint, typeName);
}
retVal[rType] = visitor.viewDef;
}
});
return new ViewDefinitionResults._(ngDeps, retVal);
}
/// Creates a map from [AssetId] to import prefix for `.dart` libraries
/// imported by `entryPoint`, excluding any `.ng_deps.dart` files it imports.
/// Unprefixed imports have `null` as their value. `entryPoint` is included
/// in the map with no prefix.
Future<Map<AssetId, String>> _createImportAssetToPrefixMap() async {
// TODO(kegluneq): Support `part` directives.
var ngDeps = await ngDepsFuture;
var importAssetToPrefix = <AssetId, String>{};
// Include the `.ng_meta.dart` file associated with `entryPoint`.
importAssetToPrefix[new AssetId(
entryPoint.package, toMetaExtension(entryPoint.path))] = null;
for (ImportDirective node in ngDeps.imports) {
var uri = stringLiteralToString(node.uri);
if (uri.endsWith('.dart') && !uri.endsWith(DEPS_EXTENSION)) {
var prefix = node.prefix != null && node.prefix.name != null
? '${node.prefix.name}'
: null;
importAssetToPrefix[
uriToAssetId(entryPoint, uri, logger, null /* span */)] = prefix;
}
}
return importAssetToPrefix;
}
/// Reads the `.ng_meta.json` files associated with all of `entryPoint`'s
/// imports and creates a map `Type` name, prefixed if appropriate to the
/// associated [DirectiveMetadata].
///
/// For example, if in `entryPoint` we have:
///
/// ```
/// import 'component.dart' as prefix;
/// ```
///
/// and in 'component.dart' we have:
///
/// ```
/// @Component(...)
/// class MyComponent {...}
/// ```
///
/// This method will look for `component.ng_meta.json`to contain the
/// serialized [DirectiveMetadata] `MyComponent` and any other `Directive`s
/// declared in `component.dart`. We use this information to build a map:
///
/// ```
/// {
/// "prefix.MyComponent": [DirectiveMetadata for MyComponent],
/// ...<any other entries>...
/// }
/// ```
Future<Map<String, DirectiveMetadata>> _createMetadataMap() async {
var importAssetToPrefix = await _createImportAssetToPrefixMap();
var retVal = <String, DirectiveMetadata>{};
for (var importAssetId in importAssetToPrefix.keys) {
var metaAssetId = new AssetId(
importAssetId.package, toMetaExtension(importAssetId.path));
if (await reader.hasInput(metaAssetId)) {
try {
var json = await reader.readAsString(metaAssetId);
var jsonMap = JSON.decode(json);
jsonMap.forEach((className, metaDataMap) {
var prefixStr = importAssetToPrefix[importAssetId];
var key = prefixStr != null ? '$prefixStr.$className' : className;
var value = directiveMetadataFromMap(metaDataMap)
..id = _getComponentId(importAssetId, className);
retVal[key] = value;
});
} catch (ex, stackTrace) {
logger.warning('Failed to decode: $ex, $stackTrace',
asset: metaAssetId);
}
}
}
return retVal;
}
}
/// Visitor responsible for processing the `annotations` property of a
/// {@link RegisterType} object and pulling out [ViewDefinition] information.
class _TemplateExtractVisitor extends Object with RecursiveAstVisitor<Object> {
ViewDefinition viewDef = null;
final Map<String, DirectiveMetadata> _metadataMap;
_TemplateExtractVisitor(this._metadataMap);
void reset() {
viewDef = null;
}
/// These correspond to the annotations themselves.
@override
Object visitInstanceCreationExpression(InstanceCreationExpression node) {
if ('${node.constructorName.type}' == 'View') {
viewDef = new ViewDefinition(directives: <DirectiveMetadata>[]);
node.visitChildren(this);
}
return null;
}
/// These correspond to the annotation parameters.
@override
Object visitNamedExpression(NamedExpression node) {
// TODO(kegluneq): Remove this limitation.
if (node.name is! Label || node.name.label is! SimpleIdentifier) {
logger.error(
'Angular 2 currently only supports simple identifiers in directives.'
' Source: ${node}');
return null;
}
var keyString = '${node.name.label}';
if (keyString == 'directives') {
_readDirectives(node.expression);
}
if (keyString == 'template' || keyString == 'templateUrl') {
if (node.expression is! SimpleStringLiteral) {
logger.error(
'Angular 2 currently only supports string literals in directives.'
' Source: ${node}');
return null;
}
var valueString = stringLiteralToString(node.expression);
if (keyString == 'templateUrl') {
if (viewDef.absUrl != null) {
logger.error(
'Found multiple values for "templateUrl". Source: ${node}');
}
viewDef.absUrl = valueString;
} else {
// keyString == 'template'
if (viewDef.template != null) {
logger.error('Found multiple values for "template". Source: ${node}');
}
viewDef.template = valueString;
}
}
return null;
}
void _readDirectives(Expression node) {
if (node is! ListLiteral) {
logger.error(
'Angular 2 currently only supports list literals as values for'
' "directives". Source: $node');
return;
}
var directiveList = (node as ListLiteral);
for (var node in directiveList.elements) {
if (node is! SimpleIdentifier && node is! PrefixedIdentifier) {
logger.error(
'Angular 2 currently only supports simple and prefixed identifiers '
'as values for "directives". Source: $node');
return;
}
var name = '$node';
if (_metadataMap.containsKey(name)) {
viewDef.directives.add(_metadataMap[name]);
} else {
logger.warning('Could not find Directive entry for $name');
}
}
}
}

View File

@ -57,6 +57,8 @@ void allTests() {
outputs: {
'a|web/bar.ng_deps.dart':
'simple_annotation_files/expected/bar.ng_deps.dart',
'a|web/bar.ng_meta.json':
'simple_annotation_files/expected/bar.ng_meta.json',
'a|web/index.ng_deps.dart':
'simple_annotation_files/expected/index.ng_deps.dart'
}),

View File

@ -0,0 +1 @@
{"MyComponent":{"id":"MyComponent","selector":"[soup]","compileChildren":true,"hostListeners":{},"hostProperties":{},"properties":{},"readAttributes":[],"type":1,"version":1}}

View File

@ -58,6 +58,32 @@ void allTests() {
var output = await processTemplates(reader, new AssetId('a', inputPath));
_formatThenExpectEquals(output, expected);
});
it('should parse `View` directives with a single dependency.', () async {
var inputPath = 'template_compiler/one_directive_files/hello.ng_deps.dart';
var expected = readFile(
'template_compiler/one_directive_files/expected/hello.ng_deps.dart');
var output = await processTemplates(reader, new AssetId('a', inputPath));
_formatThenExpectEquals(output, expected);
});
it('should parse `View` directives with a single prefixed dependency.',
() async {
var inputPath = 'template_compiler/with_prefix_files/hello.ng_deps.dart';
var expected = readFile(
'template_compiler/with_prefix_files/expected/hello.ng_deps.dart');
var output = await processTemplates(reader, new AssetId('a', inputPath));
_formatThenExpectEquals(output, expected);
inputPath = 'template_compiler/with_prefix_files/goodbye.ng_deps.dart';
expected = readFile(
'template_compiler/with_prefix_files/expected/goodbye.ng_deps.dart');
output = await processTemplates(reader, new AssetId('a', inputPath));
_formatThenExpectEquals(output, expected);
});
}
void _formatThenExpectEquals(String actual, String expected) {

View File

@ -0,0 +1,14 @@
{
"HelloCmp":
{
"id":"HelloCmp",
"selector":"hello-app",
"compileChildren":true,
"hostListeners":{},
"hostProperties":{},
"properties":{},
"readAttributes":[],
"type":1,
"version":1
}
}

View File

@ -0,0 +1,14 @@
{
"HelloCmp":
{
"id":"HelloCmp",
"selector":"hello-app",
"compileChildren":true,
"hostListeners":{},
"hostProperties":{},
"properties":{},
"readAttributes":[],
"type":1,
"version":1
}
}

View File

@ -0,0 +1,14 @@
{
"HelloCmp":
{
"id":"HelloCmp",
"selector":"hello-app",
"compileChildren":true,
"hostListeners":{},
"hostProperties":{},
"properties":{},
"readAttributes":[],
"type":1,
"version":1
}
}

View File

@ -0,0 +1,28 @@
library examples.hello_world.index_common_dart.ng_deps.dart;
import 'hello.dart';
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
var _visited = false;
void initReflector(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(HelloCmp, {
'factory': () => new HelloCmp(),
'parameters': const [const []],
'annotations': const [
const Component(selector: 'hello-app'),
const View(template: 'goodbye-app', directives: const [GoodbyeCmp])
]
})
..registerType(GoodbyeCmp, {
'factory': () => new GoodbyeCmp(),
'parameters': const [const []],
'annotations': const [
const Component(selector: 'goodbye-app'),
const View(template: 'Goodbye')
]
});
}

View File

@ -0,0 +1,28 @@
library examples.hello_world.index_common_dart.ng_deps.dart;
import 'hello.dart';
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
var _visited = false;
void initReflector(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(HelloCmp, {
'factory': () => new HelloCmp(),
'parameters': const [const []],
'annotations': const [
const Component(selector: 'hello-app'),
const View(template: 'goodbye-app', directives: const [GoodbyeCmp])
]
})
..registerType(GoodbyeCmp, {
'factory': () => new GoodbyeCmp(),
'parameters': const [const []],
'annotations': const [
const Component(selector: 'goodbye-app'),
const View(template: 'Goodbye')
]
});
}

View File

@ -0,0 +1,25 @@
{
"HelloCmp":
{
"id":"HelloCmp",
"selector":"hello-app",
"compileChildren":true,
"hostListeners":{},
"hostProperties":{},
"properties":{},
"readAttributes":[],
"type":1,
"version":1
},
"GoodbyeCmp":{
"id":"GoodbyeCmp",
"selector":"goodbye-app",
"compileChildren":true,
"hostListeners":{},
"hostProperties":{},
"properties":{},
"readAttributes":[],
"type":1,
"version":1
}
}

View File

@ -0,0 +1,14 @@
{
"HelloCmp":
{
"id":"HelloCmp",
"selector":"hello-app",
"compileChildren":true,
"hostListeners":{},
"hostProperties":{},
"properties":{},
"readAttributes":[],
"type":1,
"version":1
}
}

View File

@ -0,0 +1,14 @@
{
"HelloCmp":
{
"id":"HelloCmp",
"selector":"hello-app",
"compileChildren":true,
"hostListeners":{},
"hostProperties":{},
"properties":{},
"readAttributes":[],
"type":1,
"version":1
}
}

View File

@ -0,0 +1,22 @@
library examples.hello_world.index_common_dart.ng_deps.dart;
import 'goodbye.dart';
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
var _visited = false;
void initReflector(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(GoodbyeCmp, {
'factory': () => new GoodbyeCmp(),
'parameters': const [const []],
'annotations': const [
const Component(selector: 'goodbye-app'),
const View(template: 'Goodbye {{name}}')
]
})
..registerGetters({'name': (o) => o.name})
..registerSetters({'name': (o, v) => o.name = v});
}

View File

@ -0,0 +1,24 @@
library examples.hello_world.index_common_dart.ng_deps.dart;
import 'hello.dart';
import 'goodbye.dart' as prefix;
import 'goodbye.ng_deps.dart' as i0;
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
var _visited = false;
void initReflector(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(HelloCmp, {
'factory': () => new HelloCmp(),
'parameters': const [const []],
'annotations': const [
const Component(selector: 'hello-app'),
const View(
template: 'goodbye-app', directives: const [prefix.GoodbyeCmp])
]
});
i0.initReflector(reflector);
}

View File

@ -0,0 +1,20 @@
library examples.hello_world.index_common_dart.ng_deps.dart;
import 'goodbye.dart';
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
var _visited = false;
void initReflector(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(GoodbyeCmp, {
'factory': () => new GoodbyeCmp(),
'parameters': const [const []],
'annotations': const [
const Component(selector: 'goodbye-app'),
const View(template: 'Goodbye {{name}}')
]
});
}

View File

@ -0,0 +1,13 @@
{
"GoodbyeCmp":{
"id":"GoodbyeCmp",
"selector":"goodbye-app",
"compileChildren":true,
"hostListeners":{},
"hostProperties":{},
"properties":{},
"readAttributes":[],
"type":1,
"version":1
}
}

View File

@ -0,0 +1,24 @@
library examples.hello_world.index_common_dart.ng_deps.dart;
import 'hello.dart';
import 'goodbye.dart' as prefix;
import 'goodbye.ng_deps.dart' as i0;
import 'package:angular2/angular2.dart'
show bootstrap, Component, Directive, View, NgElement;
var _visited = false;
void initReflector(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(HelloCmp, {
'factory': () => new HelloCmp(),
'parameters': const [const []],
'annotations': const [
const Component(selector: 'hello-app'),
const View(
template: 'goodbye-app', directives: const [prefix.GoodbyeCmp])
]
});
i0.initReflector(reflector);
}

View File

@ -0,0 +1,14 @@
{
"HelloCmp":
{
"id":"HelloCmp",
"selector":"hello-app",
"compileChildren":true,
"hostListeners":{},
"hostProperties":{},
"properties":{},
"readAttributes":[],
"type":1,
"version":1
}
}

View File

@ -46,7 +46,7 @@ function getSourceTree() {
var tsInputTree = modulesFunnel(['**/*.js', '**/*.ts', '**/*.dart'], ['rtts_assert/**/*']);
var transpiled = ts2dart.transpile(tsInputTree);
// Native sources, dart only examples, etc.
var dartSrcs = modulesFunnel(['**/*.dart']);
var dartSrcs = modulesFunnel(['**/*.dart', '**/*.ng_meta.json']);
return mergeTrees([transpiled, dartSrcs]);
}