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

Commit

Permalink
feat(template_cache_transformer): Implement template cache as a trans…
Browse files Browse the repository at this point in the history
…former

Implement the template cache generation as a transformer. This is implemented
as an optional transformer option generate_template_cache.

Closes #1646
  • Loading branch information
Ted Sander authored and rkirov committed Feb 2, 2015
1 parent 6c4d52b commit ec7de20
Show file tree
Hide file tree
Showing 6 changed files with 427 additions and 19 deletions.
9 changes: 7 additions & 2 deletions lib/tools/transformer/options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,19 @@ class TransformOptions {
*/
final di.TransformOptions diOptions;

/// Option to generate the template cache.
final bool generateTemplateCache;

TransformOptions({String sdkDirectory, List<String> htmlFiles,
Map<String, String> templateUriRewrites,
di.TransformOptions diOptions}) :
di.TransformOptions diOptions, bool generateTemplateCache}) :
sdkDirectory = sdkDirectory,
htmlFiles = htmlFiles != null ? htmlFiles : [],
templateUriRewrites = templateUriRewrites != null ?
templateUriRewrites : {},
diOptions = diOptions {
diOptions = diOptions,
generateTemplateCache = generateTemplateCache != null ?
generateTemplateCache : false {
if (sdkDirectory == null)
throw new ArgumentError('sdkDirectory must be provided.');
}
Expand Down
18 changes: 16 additions & 2 deletions lib/tools/transformer/static_angular_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class StaticAngularGenerator extends Transformer with ResolverTransformer {
}
}

var dynamicToStatic = new _NgDynamicToStaticVisitor(dynamicApp, transaction);
var dynamicToStatic = new _NgDynamicToStaticVisitor(
dynamicApp, transaction, options.generateTemplateCache);
unit.accept(dynamicToStatic);

var generatedFilePrefix = '${path.url.basenameWithoutExtension(id.path)}';
Expand All @@ -53,6 +54,11 @@ class StaticAngularGenerator extends Transformer with ResolverTransformer {
_addImport(transaction, unit,
'${generatedFilePrefix}_static_type_to_uri_mapper.dart',
'generated_static_type_to_uri_mapper');
if (options.generateTemplateCache) {
_addImport(transaction, unit,
'${generatedFilePrefix}_generated_template_cache.dart',
'generated_template_cache');
}

var printer = transaction.commit();
var url = id.path.startsWith('lib/')
Expand All @@ -72,7 +78,9 @@ void _addImport(TextEditTransaction transaction, CompilationUnit unit,
class _NgDynamicToStaticVisitor extends GeneralizingAstVisitor {
final Element ngDynamicFn;
final TextEditTransaction transaction;
_NgDynamicToStaticVisitor(this.ngDynamicFn, this.transaction);
final bool generateTemplateCache;
_NgDynamicToStaticVisitor(this.ngDynamicFn, this.transaction,
this.generateTemplateCache);

visitMethodInvocation(MethodInvocation m) {
if (m.methodName.bestElement == ngDynamicFn) {
Expand All @@ -90,6 +98,12 @@ class _NgDynamicToStaticVisitor extends GeneralizingAstVisitor {
'generated_static_type_to_uri_mapper.typeToUriMapper'
].join(', ')
);
if (generateTemplateCache) {
transaction.edit(
m.end,
m.end,
'..addModule(generated_template_cache.templateCacheModule)');
}
}
super.visitMethodInvocation(m);
}
Expand Down
71 changes: 71 additions & 0 deletions lib/tools/transformer/template_cache_generator.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
library angular_transformers.template_cache_generator;

import 'dart:async';

import 'package:angular/tools/transformer/options.dart';
import 'package:angular/tools/transformer/referenced_uris.dart';
import 'package:barback/barback.dart';
import 'package:code_transformers/resolver.dart';
import 'package:path/path.dart' as path;

/// Transformer which gathers all templates from the Angular application and
/// adds to the Template Cache.
class TemplateCacheGenerator extends Transformer with ResolverTransformer {
static const String generatedFilename = '_generated_template_cache.dart';

final TransformOptions options;

TemplateCacheGenerator(this.options, Resolvers resolvers) {
this.resolvers = resolvers;
}

Future applyResolver(Transform transform, Resolver resolver) {
if (!options.generateTemplateCache) return new Future.value();

var asset = transform.primaryInput;
var id = asset.id;
var outputFilename = '${path.url.basenameWithoutExtension(id.path)}'
'$generatedFilename';
var outputPath = path.url.join(path.url.dirname(id.path), outputFilename);
var outputId = new AssetId(id.package, outputPath);
var outputBuffer = new StringBuffer();

return gatherReferencedUris(transform, resolver, options,
templatesOnly: false).then((templates) {
_writeTemplateCacheHeader(asset.id, outputBuffer);
templates.forEach((uri, contents) {
contents = contents.replaceAll("'''", r"\'\'\'");
outputBuffer.write(" r'$uri' : r'''\n$contents''',\n");
});
_writeTemplateCacheFooter(outputBuffer);
transform.addOutput(
new Asset.fromString(outputId, outputBuffer.toString()));
});
}

void _writeTemplateCacheHeader(AssetId id, StringSink sink) {
var libPath = path.url.withoutExtension(id.path).replaceAll('/', '.');
sink.write('''
library ${id.package}.$libPath.generated_template_cache;
import 'package:angular/angular.dart';
import 'package:di/di.dart' show Module;
Module get templateCacheModule =>
new Module()..bind(TemplateCache, toFactory: () {
var templateCache = new TemplateCache();
_cache.forEach((key, value) {
templateCache.put(key, new HttpResponse(200, value));
});
return templateCache;
});
const Map<String, String> _cache = const <String, String> {
''');
}

void _writeTemplateCacheFooter(StringSink sink) {
sink.write('''};
''');
}
}
23 changes: 22 additions & 1 deletion lib/transformer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:angular/tools/transformer/expression_generator.dart';
import 'package:angular/tools/transformer/metadata_generator.dart';
import 'package:angular/tools/transformer/static_angular_generator.dart';
import 'package:angular/tools/transformer/html_dart_references_generator.dart';
import 'package:angular/tools/transformer/template_cache_generator.dart';
import 'package:angular/tools/transformer/type_relative_uri_generator.dart';
import 'package:angular/tools/transformer/options.dart';
import 'package:barback/barback.dart';
Expand Down Expand Up @@ -59,7 +60,26 @@ TransformOptions _parseSettings(Map args) {
htmlFiles: _readStringListValue(args, 'html_files'),
sdkDirectory: sdkDir,
templateUriRewrites: _readStringMapValue(args, 'template_uri_rewrites'),
diOptions: diOptions);
diOptions: diOptions,
generateTemplateCache:
_readBoolValue(args, 'generate_template_cache', required: false));
}

_readBoolValue(Map args, String name, {bool required: true}) {
var value = args[name];
if (value == null) {
if (required) {
print('Angular transformer parameter "$name" '
'has no value in pubspec.yaml.');
}
return null;
}
if (value is! bool) {
print('Angular transformer parameter "$name" value '
'is not a bool in pubspec.yaml.');
return null;
}
return value;
}

_readStringValue(Map args, String name, {bool required: true}) {
Expand Down Expand Up @@ -123,6 +143,7 @@ Transformer _staticGenerator(TransformOptions options) {
new TypeRelativeUriGenerator(options, resolvers),
new ExpressionGenerator(options, resolvers),
new MetadataGenerator(options, resolvers),
new TemplateCacheGenerator(options, resolvers),
new StaticAngularGenerator(options, resolvers)
]);
}
Expand Down
69 changes: 55 additions & 14 deletions test/tools/transformer/static_angular_generator_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,18 @@ library angular.test.tools.transformer.static_angular_generator_spec;

import 'package:angular/tools/transformer/options.dart';
import 'package:angular/tools/transformer/static_angular_generator.dart';
import 'package:barback/barback.dart';
import 'package:code_transformers/resolver.dart';
import 'package:code_transformers/tests.dart' as tests;

import 'package:unittest/unittest.dart' hide expect;
import 'package:guinness/guinness.dart';

main() {
describe('StaticAngularGenerator', () {
var options = new TransformOptions(
sdkDirectory: dartSdkDirectory);

var resolvers = new Resolvers(dartSdkDirectory);

var phases = [
[new StaticAngularGenerator(options, resolvers)]
];

it('should modify applicationFactory', () {
return tests.applyTransformers(phases,
return tests.applyTransformers(
setupPhases(generateTemplateCache:false),
inputs: {
'angular|lib/application_factory.dart': libAngularDynamic,
'di|lib/di.dart': libDI,
Expand Down Expand Up @@ -56,8 +49,46 @@ main() {
});
});

it('should modify applicationFactory with template cache', () {
return tests.applyTransformers(setupPhases(),
inputs: {
'angular|lib/application_factory.dart': libAngularDynamic,
'di|lib/di.dart': libDI,
'a|web/main.dart': '''
import 'package:angular/application_factory.dart';
import 'package:di/di.dart' show Module;
class MyModule extends Module {}
main() {
var app = applicationFactory()
.addModule(new MyModule())
.run();
}
'''
},
results: {
'a|web/main.dart': '''
import 'package:angular/application_factory_static.dart';
import 'package:di/di.dart' show Module;
import 'main_static_expressions.dart' as generated_static_expressions;
import 'main_static_metadata.dart' as generated_static_metadata;
import 'main_static_type_to_uri_mapper.dart' as generated_static_type_to_uri_mapper;
import 'main_generated_template_cache.dart' as generated_template_cache;
class MyModule extends Module {}
main() {
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)
.addModule(new MyModule())
.run();
}
'''
});
});

it('handles prefixed app imports', () {
return tests.applyTransformers(phases,
return tests.applyTransformers(setupPhases(),
inputs: {
'angular|lib/application_factory.dart': libAngularDynamic,
'di|lib/di.dart': libDI,
Expand All @@ -81,11 +112,12 @@ import 'package:di/di.dart' show Module;
import 'main_static_expressions.dart' as generated_static_expressions;
import 'main_static_metadata.dart' as generated_static_metadata;
import 'main_static_type_to_uri_mapper.dart' as generated_static_type_to_uri_mapper;
import 'main_generated_template_cache.dart' as generated_template_cache;
class MyModule extends Module {}
main() {
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)
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)
.addModule(new MyModule())
.run();
}
Expand All @@ -95,8 +127,6 @@ main() {
});
}



const String libAngularDynamic = '''
library angular.app.factory;
class _NgDynamicApp {}
Expand All @@ -107,3 +137,14 @@ applicationFactory() => new _DynamicApplication();
const String libDI = '''
class Module {}
''';

List<List<Transformer>> setupPhases({bool generateTemplateCache: true}) {
var options = new TransformOptions(sdkDirectory: dartSdkDirectory,
generateTemplateCache: generateTemplateCache);

var resolvers = new Resolvers(dartSdkDirectory);

return [
[new StaticAngularGenerator(options, resolvers)]
];
}
Loading

0 comments on commit ec7de20

Please sign in to comment.