Skip to content

Commit 169e4e8

Browse files
author
Tim Blasi
committed
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`.
1 parent abc3de7 commit 169e4e8

File tree

5 files changed

+112
-77
lines changed

5 files changed

+112
-77
lines changed

modules/angular2/src/dom/browser_adapter.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,9 @@ class BrowserDomAdapter extends GenericBrowserDomAdapter {
296296
}
297297
String getEventKey(KeyboardEvent event) {
298298
int keyCode = event.keyCode;
299-
return _keyCodeToKeyMap.containsKey(keyCode) ? _keyCodeToKeyMap[keyCode] : 'Unidentified';
299+
return _keyCodeToKeyMap.containsKey(keyCode)
300+
? _keyCodeToKeyMap[keyCode]
301+
: 'Unidentified';
300302
}
301303
getGlobalEventTarget(String target) {
302304
if (target == "window") {

modules/angular2/src/dom/html_adapter.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,8 @@ class Html5LibDomAdapter implements DomAdapter {
168168
getHost(el) {
169169
throw 'not implemented';
170170
}
171-
clone(node) {
172-
throw 'not implemented';
173-
}
171+
clone(node) => node.clone(true);
172+
174173
hasProperty(element, String name) {
175174
throw 'not implemented';
176175
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
library angular2.transform.template_compiler.compile_step_factory;
2+
3+
import 'dart:async';
4+
import 'package:angular2/src/change_detection/parser/parser.dart' as ng;
5+
import 'package:angular2/src/render/api.dart';
6+
import 'package:angular2/src/render/dom/compiler/compile_step.dart';
7+
import 'package:angular2/src/render/dom/compiler/compile_step_factory.dart'
8+
as base;
9+
import 'package:angular2/src/render/dom/compiler/property_binding_parser.dart';
10+
import 'package:angular2/src/render/dom/compiler/text_interpolation_parser.dart';
11+
import 'package:angular2/src/render/dom/compiler/view_splitter.dart';
12+
13+
class CompileStepFactory implements base.CompileStepFactory {
14+
final ng.Parser _parser;
15+
CompileStepFactory(this._parser);
16+
17+
List<CompileStep> createSteps(
18+
ViewDefinition template, List<Future> subTaskPromises) {
19+
// TODO(kegluneq): Add other compile steps from default_steps.dart.
20+
return [
21+
new ViewSplitter(_parser),
22+
new PropertyBindingParser(_parser),
23+
new TextInterpolationParser(_parser)
24+
];
25+
}
26+
}

modules/angular2/src/transform/template_compiler/generator.dart

Lines changed: 56 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,22 @@ import 'dart:async';
55
import 'package:analyzer/analyzer.dart';
66
import 'package:angular2/src/change_detection/parser/lexer.dart' as ng;
77
import 'package:angular2/src/change_detection/parser/parser.dart' as ng;
8+
import 'package:angular2/src/render/api.dart';
89
import 'package:angular2/src/render/dom/compiler/compile_pipeline.dart';
9-
import 'package:angular2/src/render/dom/compiler/compile_step.dart';
10-
import 'package:angular2/src/render/dom/compiler/property_binding_parser.dart';
11-
import 'package:angular2/src/render/dom/compiler/text_interpolation_parser.dart';
12-
import 'package:angular2/src/render/dom/compiler/view_splitter.dart';
13-
import 'package:angular2/src/dom/dom_adapter.dart';
10+
import 'package:angular2/src/render/dom/compiler/template_loader.dart';
11+
import "package:angular2/src/services/xhr.dart" show XHR;
1412
import 'package:angular2/src/reflection/reflection.dart';
13+
import 'package:angular2/src/services/url_resolver.dart';
1514
import 'package:angular2/src/transform/common/asset_reader.dart';
1615
import 'package:angular2/src/transform/common/logging.dart';
1716
import 'package:angular2/src/transform/common/names.dart';
1817
import 'package:angular2/src/transform/common/parser.dart';
1918
import 'package:angular2/src/transform/common/property_utils.dart' as prop;
2019
import 'package:barback/barback.dart';
21-
import 'package:code_transformers/assets.dart';
2220

21+
import 'compile_step_factory.dart';
2322
import 'recording_reflection_capabilities.dart';
23+
import 'xhr_impl.dart';
2424

2525
/// Reads the `.ng_deps.dart` file represented by `entryPoint` and parses any
2626
/// Angular 2 `View` annotations it declares to generate `getter`s,
@@ -30,28 +30,27 @@ import 'recording_reflection_capabilities.dart';
3030
Future<String> processTemplates(AssetReader reader, AssetId entryPoint) async {
3131
var parser = new Parser(reader);
3232
NgDeps ngDeps = await parser.parse(entryPoint);
33-
var extractor = new _TemplateExtractor(reader, entryPoint);
33+
var extractor = new _TemplateExtractor(new XhrImpl(reader, entryPoint));
3434

3535
var registrations = new StringBuffer();
3636
for (var rType in ngDeps.registeredTypes) {
37-
(await extractor.extractTemplates(rType))
38-
.forEach((RecordingReflectionCapabilities values) {
39-
var calls = _generateGetters('${rType.typeName}', values.getterNames);
40-
if (calls.isNotEmpty) {
41-
registrations.write('..${REGISTER_GETTERS_METHOD_NAME}'
42-
'({${calls.join(', ')}})');
43-
}
44-
calls = _generateSetters('${rType.typeName}', values.setterNames);
45-
if (calls.isNotEmpty) {
46-
registrations.write('..${REGISTER_SETTERS_METHOD_NAME}'
47-
'({${calls.join(', ')}})');
48-
}
49-
calls = _generateMethods('${rType.typeName}', values.methodNames);
50-
if (calls.isNotEmpty) {
51-
registrations.write('..${REGISTER_METHODS_METHOD_NAME}'
52-
'({${calls.join(', ')}})');
53-
}
54-
});
37+
var values = await extractor.extractTemplates(rType);
38+
if (values == null) continue;
39+
var calls = _generateGetters('${rType.typeName}', values.getterNames);
40+
if (calls.isNotEmpty) {
41+
registrations.write('..${REGISTER_GETTERS_METHOD_NAME}'
42+
'({${calls.join(', ')}})');
43+
}
44+
calls = _generateSetters('${rType.typeName}', values.setterNames);
45+
if (calls.isNotEmpty) {
46+
registrations.write('..${REGISTER_SETTERS_METHOD_NAME}'
47+
'({${calls.join(', ')}})');
48+
}
49+
calls = _generateMethods('${rType.typeName}', values.methodNames);
50+
if (calls.isNotEmpty) {
51+
registrations.write('..${REGISTER_METHODS_METHOD_NAME}'
52+
'({${calls.join(', ')}})');
53+
}
5554
}
5655

5756
var code = ngDeps.code;
@@ -105,75 +104,52 @@ Iterable<String> _generateMethods(
105104
/// template code if necessary, and determines what values will be
106105
/// reflectively accessed from that template.
107106
class _TemplateExtractor {
108-
final AssetReader _reader;
109-
final AssetId _entryPoint;
110-
final CompilePipeline _pipeline;
107+
final CompileStepFactory _factory;
111108
final _TemplateExtractVisitor _visitor = new _TemplateExtractVisitor();
109+
final TemplateLoader _loader;
112110

113-
_TemplateExtractor(this._reader, this._entryPoint)
114-
: _pipeline = new CompilePipeline(_createCompileSteps());
115-
116-
static List<CompileStep> _createCompileSteps() {
117-
var parser = new ng.Parser(new ng.Lexer());
118-
// TODO(kegluneq): Add other compile steps from default_steps.dart.
119-
return [
120-
new ViewSplitter(parser),
121-
new PropertyBindingParser(parser),
122-
new TextInterpolationParser(parser)
123-
];
124-
}
111+
_TemplateExtractor(XHR xhr)
112+
: _loader = new TemplateLoader(xhr, new UrlResolver()),
113+
_factory = new CompileStepFactory(new ng.Parser(new ng.Lexer()));
125114

126-
Future<List<RecordingReflectionCapabilities>> extractTemplates(
127-
RegisteredType t) async {
128-
return (await _processRegisteredType(t)).map(_processTemplate).toList();
115+
Future<RecordingReflectionCapabilities> extractTemplates(RegisteredType t) {
116+
return _processTemplate(_processRegisteredType(t));
129117
}
130118

131-
RecordingReflectionCapabilities _processTemplate(String templateCode) {
119+
Future<RecordingReflectionCapabilities> _processTemplate(
120+
ViewDefinition viewDef) async {
121+
// Check for "imperative views".
122+
if (viewDef.template == null && viewDef.absUrl == null) return null;
123+
132124
var recordingCapabilities = new RecordingReflectionCapabilities();
133125
var savedReflectionCapabilities = reflector.reflectionCapabilities;
134126
reflector.reflectionCapabilities = recordingCapabilities;
135127

136-
_pipeline.process(DOM.createTemplate(templateCode), templateCode);
128+
// TODO(kegluneq): Rewrite url to inline `template` where possible.
129+
// See [https://github.com/angular/angular/issues/1035].
130+
var domNode = await _loader.load(viewDef);
131+
132+
new CompilePipeline(_factory.createSteps(viewDef, [])).process(
133+
domNode, '$domNode');
137134

138135
reflector.reflectionCapabilities = savedReflectionCapabilities;
139136
return recordingCapabilities;
140137
}
141138

142-
Future<List<String>> _processRegisteredType(RegisteredType t) async {
139+
ViewDefinition _processRegisteredType(RegisteredType t) {
143140
_visitor.reset();
144141
t.annotations.accept(_visitor);
145-
var toReturn = _visitor.inlineValues;
146-
for (var url in _visitor.urlValues) {
147-
var templateText = await _readUrlTemplate(url);
148-
if (templateText != null) {
149-
toReturn.add(templateText);
150-
}
151-
}
152-
return toReturn;
153-
}
154-
155-
// TODO(kegluneq): Rewrite these to `template` where possible.
156-
// See [https://github.com/angular/angular/issues/1035].
157-
Future<String> _readUrlTemplate(String url) async {
158-
var assetId = uriToAssetId(_entryPoint, url, logger, null);
159-
var templateExists = await _reader.hasInput(assetId);
160-
if (!templateExists) {
161-
logger.error('Could not read template at uri $url from $_entryPoint');
162-
return null;
163-
}
164-
return await _reader.readAsString(assetId);
142+
return _visitor.viewDef;
165143
}
166144
}
167145

168146
/// Visitor responsible for processing the `annotations` property of a
169-
/// {@link RegisterType} object and pulling out template text.
147+
/// {@link RegisterType} object and pulling out template information.
170148
class _TemplateExtractVisitor extends Object with RecursiveAstVisitor<Object> {
171-
final List<String> inlineValues = [];
172-
final List<String> urlValues = [];
149+
ViewDefinition viewDef = new ViewDefinition();
173150

174151
void reset() {
175-
inlineValues.clear();
176-
urlValues.clear();
152+
viewDef = new ViewDefinition();
177153
}
178154

179155
@override
@@ -195,9 +171,16 @@ class _TemplateExtractVisitor extends Object with RecursiveAstVisitor<Object> {
195171
}
196172
var valueString = stringLiteralToString(node.expression);
197173
if (keyString == 'templateUrl') {
198-
urlValues.add(valueString);
174+
if (viewDef.absUrl != null) {
175+
logger.error(
176+
'Found multiple values for "templateUrl". Source: ${node}');
177+
}
178+
viewDef.absUrl = valueString;
199179
} else {
200-
inlineValues.add(valueString);
180+
if (viewDef.template != null) {
181+
logger.error('Found multiple values for "template". Source: ${node}');
182+
}
183+
viewDef.template = valueString;
201184
}
202185
}
203186
return null;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
library angular2.transform.template_compiler.xhr_impl;
2+
3+
import 'dart:async';
4+
import 'package:angular2/src/services/xhr.dart' show XHR;
5+
import 'package:angular2/src/transform/common/asset_reader.dart';
6+
import 'package:angular2/src/transform/common/logging.dart';
7+
import 'package:barback/barback.dart';
8+
import 'package:code_transformers/assets.dart';
9+
10+
class XhrImpl implements XHR {
11+
final AssetReader _reader;
12+
final AssetId _entryPoint;
13+
14+
XhrImpl(this._reader, this._entryPoint);
15+
16+
Future<String> get(String url) async {
17+
var assetId = uriToAssetId(_entryPoint, url, logger, null);
18+
var templateExists = await _reader.hasInput(assetId);
19+
if (!templateExists) {
20+
logger.error('Could not read template at uri $url from $_entryPoint');
21+
return null;
22+
}
23+
return await _reader.readAsString(assetId);
24+
}
25+
}

0 commit comments

Comments
 (0)