Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Commit ec7de20

Browse files
Ted Sanderrkirov
authored andcommitted
feat(template_cache_transformer): Implement template cache as a transformer
Implement the template cache generation as a transformer. This is implemented as an optional transformer option generate_template_cache. Closes #1646
1 parent 6c4d52b commit ec7de20

File tree

6 files changed

+427
-19
lines changed

6 files changed

+427
-19
lines changed

lib/tools/transformer/options.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,19 @@ class TransformOptions {
2727
*/
2828
final di.TransformOptions diOptions;
2929

30+
/// Option to generate the template cache.
31+
final bool generateTemplateCache;
32+
3033
TransformOptions({String sdkDirectory, List<String> htmlFiles,
3134
Map<String, String> templateUriRewrites,
32-
di.TransformOptions diOptions}) :
35+
di.TransformOptions diOptions, bool generateTemplateCache}) :
3336
sdkDirectory = sdkDirectory,
3437
htmlFiles = htmlFiles != null ? htmlFiles : [],
3538
templateUriRewrites = templateUriRewrites != null ?
3639
templateUriRewrites : {},
37-
diOptions = diOptions {
40+
diOptions = diOptions,
41+
generateTemplateCache = generateTemplateCache != null ?
42+
generateTemplateCache : false {
3843
if (sdkDirectory == null)
3944
throw new ArgumentError('sdkDirectory must be provided.');
4045
}

lib/tools/transformer/static_angular_generator.dart

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ class StaticAngularGenerator extends Transformer with ResolverTransformer {
3939
}
4040
}
4141

42-
var dynamicToStatic = new _NgDynamicToStaticVisitor(dynamicApp, transaction);
42+
var dynamicToStatic = new _NgDynamicToStaticVisitor(
43+
dynamicApp, transaction, options.generateTemplateCache);
4344
unit.accept(dynamicToStatic);
4445

4546
var generatedFilePrefix = '${path.url.basenameWithoutExtension(id.path)}';
@@ -53,6 +54,11 @@ class StaticAngularGenerator extends Transformer with ResolverTransformer {
5354
_addImport(transaction, unit,
5455
'${generatedFilePrefix}_static_type_to_uri_mapper.dart',
5556
'generated_static_type_to_uri_mapper');
57+
if (options.generateTemplateCache) {
58+
_addImport(transaction, unit,
59+
'${generatedFilePrefix}_generated_template_cache.dart',
60+
'generated_template_cache');
61+
}
5662

5763
var printer = transaction.commit();
5864
var url = id.path.startsWith('lib/')
@@ -72,7 +78,9 @@ void _addImport(TextEditTransaction transaction, CompilationUnit unit,
7278
class _NgDynamicToStaticVisitor extends GeneralizingAstVisitor {
7379
final Element ngDynamicFn;
7480
final TextEditTransaction transaction;
75-
_NgDynamicToStaticVisitor(this.ngDynamicFn, this.transaction);
81+
final bool generateTemplateCache;
82+
_NgDynamicToStaticVisitor(this.ngDynamicFn, this.transaction,
83+
this.generateTemplateCache);
7684

7785
visitMethodInvocation(MethodInvocation m) {
7886
if (m.methodName.bestElement == ngDynamicFn) {
@@ -90,6 +98,12 @@ class _NgDynamicToStaticVisitor extends GeneralizingAstVisitor {
9098
'generated_static_type_to_uri_mapper.typeToUriMapper'
9199
].join(', ')
92100
);
101+
if (generateTemplateCache) {
102+
transaction.edit(
103+
m.end,
104+
m.end,
105+
'..addModule(generated_template_cache.templateCacheModule)');
106+
}
93107
}
94108
super.visitMethodInvocation(m);
95109
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
library angular_transformers.template_cache_generator;
2+
3+
import 'dart:async';
4+
5+
import 'package:angular/tools/transformer/options.dart';
6+
import 'package:angular/tools/transformer/referenced_uris.dart';
7+
import 'package:barback/barback.dart';
8+
import 'package:code_transformers/resolver.dart';
9+
import 'package:path/path.dart' as path;
10+
11+
/// Transformer which gathers all templates from the Angular application and
12+
/// adds to the Template Cache.
13+
class TemplateCacheGenerator extends Transformer with ResolverTransformer {
14+
static const String generatedFilename = '_generated_template_cache.dart';
15+
16+
final TransformOptions options;
17+
18+
TemplateCacheGenerator(this.options, Resolvers resolvers) {
19+
this.resolvers = resolvers;
20+
}
21+
22+
Future applyResolver(Transform transform, Resolver resolver) {
23+
if (!options.generateTemplateCache) return new Future.value();
24+
25+
var asset = transform.primaryInput;
26+
var id = asset.id;
27+
var outputFilename = '${path.url.basenameWithoutExtension(id.path)}'
28+
'$generatedFilename';
29+
var outputPath = path.url.join(path.url.dirname(id.path), outputFilename);
30+
var outputId = new AssetId(id.package, outputPath);
31+
var outputBuffer = new StringBuffer();
32+
33+
return gatherReferencedUris(transform, resolver, options,
34+
templatesOnly: false).then((templates) {
35+
_writeTemplateCacheHeader(asset.id, outputBuffer);
36+
templates.forEach((uri, contents) {
37+
contents = contents.replaceAll("'''", r"\'\'\'");
38+
outputBuffer.write(" r'$uri' : r'''\n$contents''',\n");
39+
});
40+
_writeTemplateCacheFooter(outputBuffer);
41+
transform.addOutput(
42+
new Asset.fromString(outputId, outputBuffer.toString()));
43+
});
44+
}
45+
46+
void _writeTemplateCacheHeader(AssetId id, StringSink sink) {
47+
var libPath = path.url.withoutExtension(id.path).replaceAll('/', '.');
48+
sink.write('''
49+
library ${id.package}.$libPath.generated_template_cache;
50+
51+
import 'package:angular/angular.dart';
52+
import 'package:di/di.dart' show Module;
53+
54+
Module get templateCacheModule =>
55+
new Module()..bind(TemplateCache, toFactory: () {
56+
var templateCache = new TemplateCache();
57+
_cache.forEach((key, value) {
58+
templateCache.put(key, new HttpResponse(200, value));
59+
});
60+
return templateCache;
61+
});
62+
63+
const Map<String, String> _cache = const <String, String> {
64+
''');
65+
}
66+
67+
void _writeTemplateCacheFooter(StringSink sink) {
68+
sink.write('''};
69+
''');
70+
}
71+
}

lib/transformer.dart

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:angular/tools/transformer/expression_generator.dart';
66
import 'package:angular/tools/transformer/metadata_generator.dart';
77
import 'package:angular/tools/transformer/static_angular_generator.dart';
88
import 'package:angular/tools/transformer/html_dart_references_generator.dart';
9+
import 'package:angular/tools/transformer/template_cache_generator.dart';
910
import 'package:angular/tools/transformer/type_relative_uri_generator.dart';
1011
import 'package:angular/tools/transformer/options.dart';
1112
import 'package:barback/barback.dart';
@@ -59,7 +60,26 @@ TransformOptions _parseSettings(Map args) {
5960
htmlFiles: _readStringListValue(args, 'html_files'),
6061
sdkDirectory: sdkDir,
6162
templateUriRewrites: _readStringMapValue(args, 'template_uri_rewrites'),
62-
diOptions: diOptions);
63+
diOptions: diOptions,
64+
generateTemplateCache:
65+
_readBoolValue(args, 'generate_template_cache', required: false));
66+
}
67+
68+
_readBoolValue(Map args, String name, {bool required: true}) {
69+
var value = args[name];
70+
if (value == null) {
71+
if (required) {
72+
print('Angular transformer parameter "$name" '
73+
'has no value in pubspec.yaml.');
74+
}
75+
return null;
76+
}
77+
if (value is! bool) {
78+
print('Angular transformer parameter "$name" value '
79+
'is not a bool in pubspec.yaml.');
80+
return null;
81+
}
82+
return value;
6383
}
6484

6585
_readStringValue(Map args, String name, {bool required: true}) {
@@ -123,6 +143,7 @@ Transformer _staticGenerator(TransformOptions options) {
123143
new TypeRelativeUriGenerator(options, resolvers),
124144
new ExpressionGenerator(options, resolvers),
125145
new MetadataGenerator(options, resolvers),
146+
new TemplateCacheGenerator(options, resolvers),
126147
new StaticAngularGenerator(options, resolvers)
127148
]);
128149
}

test/tools/transformer/static_angular_generator_spec.dart

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,18 @@ library angular.test.tools.transformer.static_angular_generator_spec;
22

33
import 'package:angular/tools/transformer/options.dart';
44
import 'package:angular/tools/transformer/static_angular_generator.dart';
5+
import 'package:barback/barback.dart';
56
import 'package:code_transformers/resolver.dart';
67
import 'package:code_transformers/tests.dart' as tests;
78

8-
import 'package:unittest/unittest.dart' hide expect;
99
import 'package:guinness/guinness.dart';
1010

1111
main() {
1212
describe('StaticAngularGenerator', () {
13-
var options = new TransformOptions(
14-
sdkDirectory: dartSdkDirectory);
15-
16-
var resolvers = new Resolvers(dartSdkDirectory);
17-
18-
var phases = [
19-
[new StaticAngularGenerator(options, resolvers)]
20-
];
2113

2214
it('should modify applicationFactory', () {
23-
return tests.applyTransformers(phases,
15+
return tests.applyTransformers(
16+
setupPhases(generateTemplateCache:false),
2417
inputs: {
2518
'angular|lib/application_factory.dart': libAngularDynamic,
2619
'di|lib/di.dart': libDI,
@@ -56,8 +49,46 @@ main() {
5649
});
5750
});
5851

52+
it('should modify applicationFactory with template cache', () {
53+
return tests.applyTransformers(setupPhases(),
54+
inputs: {
55+
'angular|lib/application_factory.dart': libAngularDynamic,
56+
'di|lib/di.dart': libDI,
57+
'a|web/main.dart': '''
58+
import 'package:angular/application_factory.dart';
59+
import 'package:di/di.dart' show Module;
60+
61+
class MyModule extends Module {}
62+
63+
main() {
64+
var app = applicationFactory()
65+
.addModule(new MyModule())
66+
.run();
67+
}
68+
'''
69+
},
70+
results: {
71+
'a|web/main.dart': '''
72+
import 'package:angular/application_factory_static.dart';
73+
import 'package:di/di.dart' show Module;
74+
import 'main_static_expressions.dart' as generated_static_expressions;
75+
import 'main_static_metadata.dart' as generated_static_metadata;
76+
import 'main_static_type_to_uri_mapper.dart' as generated_static_type_to_uri_mapper;
77+
import 'main_generated_template_cache.dart' as generated_template_cache;
78+
79+
class MyModule extends Module {}
80+
81+
main() {
82+
var app = staticApplicationFactory(generated_static_metadata.typeAnnotations, generated_static_expressions.getters, generated_static_expressions.setters, generated_static_expressions.symbols, generated_static_type_to_uri_mapper.typeToUriMapper)..addModule(generated_template_cache.templateCacheModule)
83+
.addModule(new MyModule())
84+
.run();
85+
}
86+
'''
87+
});
88+
});
89+
5990
it('handles prefixed app imports', () {
60-
return tests.applyTransformers(phases,
91+
return tests.applyTransformers(setupPhases(),
6192
inputs: {
6293
'angular|lib/application_factory.dart': libAngularDynamic,
6394
'di|lib/di.dart': libDI,
@@ -81,11 +112,12 @@ import 'package:di/di.dart' show Module;
81112
import 'main_static_expressions.dart' as generated_static_expressions;
82113
import 'main_static_metadata.dart' as generated_static_metadata;
83114
import 'main_static_type_to_uri_mapper.dart' as generated_static_type_to_uri_mapper;
115+
import 'main_generated_template_cache.dart' as generated_template_cache;
84116
85117
class MyModule extends Module {}
86118
87119
main() {
88-
var app = ng.staticApplicationFactory(generated_static_metadata.typeAnnotations, generated_static_expressions.getters, generated_static_expressions.setters, generated_static_expressions.symbols, generated_static_type_to_uri_mapper.typeToUriMapper)
120+
var app = ng.staticApplicationFactory(generated_static_metadata.typeAnnotations, generated_static_expressions.getters, generated_static_expressions.setters, generated_static_expressions.symbols, generated_static_type_to_uri_mapper.typeToUriMapper)..addModule(generated_template_cache.templateCacheModule)
89121
.addModule(new MyModule())
90122
.run();
91123
}
@@ -95,8 +127,6 @@ main() {
95127
});
96128
}
97129

98-
99-
100130
const String libAngularDynamic = '''
101131
library angular.app.factory;
102132
class _NgDynamicApp {}
@@ -107,3 +137,14 @@ applicationFactory() => new _DynamicApplication();
107137
const String libDI = '''
108138
class Module {}
109139
''';
140+
141+
List<List<Transformer>> setupPhases({bool generateTemplateCache: true}) {
142+
var options = new TransformOptions(sdkDirectory: dartSdkDirectory,
143+
generateTemplateCache: generateTemplateCache);
144+
145+
var resolvers = new Resolvers(dartSdkDirectory);
146+
147+
return [
148+
[new StaticAngularGenerator(options, resolvers)]
149+
];
150+
}

0 commit comments

Comments
 (0)