refactor(dart/transform): Use render Compiler concepts
Update `TemplateCompiler` transform step to use abstractions used by the render `Compiler`. For example, template code is now loaded via an instance of `TemplateLoader` and external resources are fetched via an instance of `XHR`.
This commit is contained in:
parent
abc3de7efe
commit
169e4e862d
|
@ -296,7 +296,9 @@ class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
|||
}
|
||||
String getEventKey(KeyboardEvent event) {
|
||||
int keyCode = event.keyCode;
|
||||
return _keyCodeToKeyMap.containsKey(keyCode) ? _keyCodeToKeyMap[keyCode] : 'Unidentified';
|
||||
return _keyCodeToKeyMap.containsKey(keyCode)
|
||||
? _keyCodeToKeyMap[keyCode]
|
||||
: 'Unidentified';
|
||||
}
|
||||
getGlobalEventTarget(String target) {
|
||||
if (target == "window") {
|
||||
|
|
|
@ -168,9 +168,8 @@ class Html5LibDomAdapter implements DomAdapter {
|
|||
getHost(el) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
clone(node) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
clone(node) => node.clone(true);
|
||||
|
||||
hasProperty(element, String name) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
library angular2.transform.template_compiler.compile_step_factory;
|
||||
|
||||
import 'dart:async';
|
||||
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_step.dart';
|
||||
import 'package:angular2/src/render/dom/compiler/compile_step_factory.dart'
|
||||
as base;
|
||||
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';
|
||||
|
||||
class CompileStepFactory implements base.CompileStepFactory {
|
||||
final ng.Parser _parser;
|
||||
CompileStepFactory(this._parser);
|
||||
|
||||
List<CompileStep> createSteps(
|
||||
ViewDefinition template, List<Future> subTaskPromises) {
|
||||
// TODO(kegluneq): Add other compile steps from default_steps.dart.
|
||||
return [
|
||||
new ViewSplitter(_parser),
|
||||
new PropertyBindingParser(_parser),
|
||||
new TextInterpolationParser(_parser)
|
||||
];
|
||||
}
|
||||
}
|
|
@ -5,22 +5,22 @@ 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/compile_step.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';
|
||||
import 'package:angular2/src/dom/dom_adapter.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 'package:code_transformers/assets.dart';
|
||||
|
||||
import 'compile_step_factory.dart';
|
||||
import 'recording_reflection_capabilities.dart';
|
||||
import 'xhr_impl.dart';
|
||||
|
||||
/// Reads the `.ng_deps.dart` file represented by `entryPoint` and parses any
|
||||
/// Angular 2 `View` annotations it declares to generate `getter`s,
|
||||
|
@ -30,28 +30,27 @@ import 'recording_reflection_capabilities.dart';
|
|||
Future<String> processTemplates(AssetReader reader, AssetId entryPoint) async {
|
||||
var parser = new Parser(reader);
|
||||
NgDeps ngDeps = await parser.parse(entryPoint);
|
||||
var extractor = new _TemplateExtractor(reader, entryPoint);
|
||||
var extractor = new _TemplateExtractor(new XhrImpl(reader, entryPoint));
|
||||
|
||||
var registrations = new StringBuffer();
|
||||
for (var rType in ngDeps.registeredTypes) {
|
||||
(await extractor.extractTemplates(rType))
|
||||
.forEach((RecordingReflectionCapabilities values) {
|
||||
var calls = _generateGetters('${rType.typeName}', values.getterNames);
|
||||
if (calls.isNotEmpty) {
|
||||
registrations.write('..${REGISTER_GETTERS_METHOD_NAME}'
|
||||
'({${calls.join(', ')}})');
|
||||
}
|
||||
calls = _generateSetters('${rType.typeName}', values.setterNames);
|
||||
if (calls.isNotEmpty) {
|
||||
registrations.write('..${REGISTER_SETTERS_METHOD_NAME}'
|
||||
'({${calls.join(', ')}})');
|
||||
}
|
||||
calls = _generateMethods('${rType.typeName}', values.methodNames);
|
||||
if (calls.isNotEmpty) {
|
||||
registrations.write('..${REGISTER_METHODS_METHOD_NAME}'
|
||||
'({${calls.join(', ')}})');
|
||||
}
|
||||
});
|
||||
var values = await extractor.extractTemplates(rType);
|
||||
if (values == null) continue;
|
||||
var calls = _generateGetters('${rType.typeName}', values.getterNames);
|
||||
if (calls.isNotEmpty) {
|
||||
registrations.write('..${REGISTER_GETTERS_METHOD_NAME}'
|
||||
'({${calls.join(', ')}})');
|
||||
}
|
||||
calls = _generateSetters('${rType.typeName}', values.setterNames);
|
||||
if (calls.isNotEmpty) {
|
||||
registrations.write('..${REGISTER_SETTERS_METHOD_NAME}'
|
||||
'({${calls.join(', ')}})');
|
||||
}
|
||||
calls = _generateMethods('${rType.typeName}', values.methodNames);
|
||||
if (calls.isNotEmpty) {
|
||||
registrations.write('..${REGISTER_METHODS_METHOD_NAME}'
|
||||
'({${calls.join(', ')}})');
|
||||
}
|
||||
}
|
||||
|
||||
var code = ngDeps.code;
|
||||
|
@ -105,75 +104,52 @@ Iterable<String> _generateMethods(
|
|||
/// template code if necessary, and determines what values will be
|
||||
/// reflectively accessed from that template.
|
||||
class _TemplateExtractor {
|
||||
final AssetReader _reader;
|
||||
final AssetId _entryPoint;
|
||||
final CompilePipeline _pipeline;
|
||||
final CompileStepFactory _factory;
|
||||
final _TemplateExtractVisitor _visitor = new _TemplateExtractVisitor();
|
||||
final TemplateLoader _loader;
|
||||
|
||||
_TemplateExtractor(this._reader, this._entryPoint)
|
||||
: _pipeline = new CompilePipeline(_createCompileSteps());
|
||||
_TemplateExtractor(XHR xhr)
|
||||
: _loader = new TemplateLoader(xhr, new UrlResolver()),
|
||||
_factory = new CompileStepFactory(new ng.Parser(new ng.Lexer()));
|
||||
|
||||
static List<CompileStep> _createCompileSteps() {
|
||||
var parser = new ng.Parser(new ng.Lexer());
|
||||
// TODO(kegluneq): Add other compile steps from default_steps.dart.
|
||||
return [
|
||||
new ViewSplitter(parser),
|
||||
new PropertyBindingParser(parser),
|
||||
new TextInterpolationParser(parser)
|
||||
];
|
||||
Future<RecordingReflectionCapabilities> extractTemplates(RegisteredType t) {
|
||||
return _processTemplate(_processRegisteredType(t));
|
||||
}
|
||||
|
||||
Future<List<RecordingReflectionCapabilities>> extractTemplates(
|
||||
RegisteredType t) async {
|
||||
return (await _processRegisteredType(t)).map(_processTemplate).toList();
|
||||
}
|
||||
Future<RecordingReflectionCapabilities> _processTemplate(
|
||||
ViewDefinition viewDef) async {
|
||||
// Check for "imperative views".
|
||||
if (viewDef.template == null && viewDef.absUrl == null) return null;
|
||||
|
||||
RecordingReflectionCapabilities _processTemplate(String templateCode) {
|
||||
var recordingCapabilities = new RecordingReflectionCapabilities();
|
||||
var savedReflectionCapabilities = reflector.reflectionCapabilities;
|
||||
reflector.reflectionCapabilities = recordingCapabilities;
|
||||
|
||||
_pipeline.process(DOM.createTemplate(templateCode), templateCode);
|
||||
// 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');
|
||||
|
||||
reflector.reflectionCapabilities = savedReflectionCapabilities;
|
||||
return recordingCapabilities;
|
||||
}
|
||||
|
||||
Future<List<String>> _processRegisteredType(RegisteredType t) async {
|
||||
ViewDefinition _processRegisteredType(RegisteredType t) {
|
||||
_visitor.reset();
|
||||
t.annotations.accept(_visitor);
|
||||
var toReturn = _visitor.inlineValues;
|
||||
for (var url in _visitor.urlValues) {
|
||||
var templateText = await _readUrlTemplate(url);
|
||||
if (templateText != null) {
|
||||
toReturn.add(templateText);
|
||||
}
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
// TODO(kegluneq): Rewrite these to `template` where possible.
|
||||
// See [https://github.com/angular/angular/issues/1035].
|
||||
Future<String> _readUrlTemplate(String url) async {
|
||||
var assetId = uriToAssetId(_entryPoint, url, logger, null);
|
||||
var templateExists = await _reader.hasInput(assetId);
|
||||
if (!templateExists) {
|
||||
logger.error('Could not read template at uri $url from $_entryPoint');
|
||||
return null;
|
||||
}
|
||||
return await _reader.readAsString(assetId);
|
||||
return _visitor.viewDef;
|
||||
}
|
||||
}
|
||||
|
||||
/// Visitor responsible for processing the `annotations` property of a
|
||||
/// {@link RegisterType} object and pulling out template text.
|
||||
/// {@link RegisterType} object and pulling out template information.
|
||||
class _TemplateExtractVisitor extends Object with RecursiveAstVisitor<Object> {
|
||||
final List<String> inlineValues = [];
|
||||
final List<String> urlValues = [];
|
||||
ViewDefinition viewDef = new ViewDefinition();
|
||||
|
||||
void reset() {
|
||||
inlineValues.clear();
|
||||
urlValues.clear();
|
||||
viewDef = new ViewDefinition();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -195,9 +171,16 @@ class _TemplateExtractVisitor extends Object with RecursiveAstVisitor<Object> {
|
|||
}
|
||||
var valueString = stringLiteralToString(node.expression);
|
||||
if (keyString == 'templateUrl') {
|
||||
urlValues.add(valueString);
|
||||
if (viewDef.absUrl != null) {
|
||||
logger.error(
|
||||
'Found multiple values for "templateUrl". Source: ${node}');
|
||||
}
|
||||
viewDef.absUrl = valueString;
|
||||
} else {
|
||||
inlineValues.add(valueString);
|
||||
if (viewDef.template != null) {
|
||||
logger.error('Found multiple values for "template". Source: ${node}');
|
||||
}
|
||||
viewDef.template = valueString;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
library angular2.transform.template_compiler.xhr_impl;
|
||||
|
||||
import 'dart:async';
|
||||
import 'package:angular2/src/services/xhr.dart' show XHR;
|
||||
import 'package:angular2/src/transform/common/asset_reader.dart';
|
||||
import 'package:angular2/src/transform/common/logging.dart';
|
||||
import 'package:barback/barback.dart';
|
||||
import 'package:code_transformers/assets.dart';
|
||||
|
||||
class XhrImpl implements XHR {
|
||||
final AssetReader _reader;
|
||||
final AssetId _entryPoint;
|
||||
|
||||
XhrImpl(this._reader, this._entryPoint);
|
||||
|
||||
Future<String> get(String url) async {
|
||||
var assetId = uriToAssetId(_entryPoint, url, logger, null);
|
||||
var templateExists = await _reader.hasInput(assetId);
|
||||
if (!templateExists) {
|
||||
logger.error('Could not read template at uri $url from $_entryPoint');
|
||||
return null;
|
||||
}
|
||||
return await _reader.readAsString(assetId);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue