Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1357)

Unified Diff: third_party/pkg/angular/lib/tools/transformer/expression_generator.dart

Issue 257423008: Update all Angular libs (run update_all.sh). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/pkg/angular/lib/tools/transformer/expression_generator.dart
diff --git a/third_party/pkg/angular/lib/tools/transformer/expression_generator.dart b/third_party/pkg/angular/lib/tools/transformer/expression_generator.dart
new file mode 100644
index 0000000000000000000000000000000000000000..911aa1abfa23278fd57427411129d1ca53fa3a63
--- /dev/null
+++ b/third_party/pkg/angular/lib/tools/transformer/expression_generator.dart
@@ -0,0 +1,199 @@
+library angular.tools.transformer.expression_generator;
+
+import 'dart:async';
+import 'package:analyzer/src/generated/element.dart';
+import 'package:angular/core/parser/parser.dart';
+import 'package:angular/tools/html_extractor.dart';
+import 'package:angular/tools/parser_getter_setter/generator.dart';
+import 'package:angular/tools/source_crawler.dart';
+import 'package:angular/tools/source_metadata_extractor.dart';
+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:di/di.dart';
+import 'package:di/dynamic_injector.dart';
+import 'package:path/path.dart' as path;
+
+/**
+ * Transformer which gathers all expressions from the HTML source files and
+ * Dart source files of an application and packages them for static evaluation.
+ *
+ * This will also modify the main Dart source file to import the generated
+ * expressions and modify all references to NG_EXPRESSION_MODULE to refer to
+ * the generated expressions.
+ */
+class ExpressionGenerator extends Transformer with ResolverTransformer {
+ final TransformOptions options;
+
+ ExpressionGenerator(this.options, Resolvers resolvers) {
+ this.resolvers = resolvers;
+ }
+
+ Future applyResolver(Transform transform, Resolver resolver) {
+ var asset = transform.primaryInput;
+ var outputBuffer = new StringBuffer();
+
+ _writeStaticExpressionHeader(asset.id, outputBuffer);
+
+ var sourceMetadataExtractor = new SourceMetadataExtractor();
+ var directives =
+ sourceMetadataExtractor.gatherDirectiveInfo(null,
+ new _LibrarySourceCrawler(resolver.libraries));
+
+ var htmlExtractor = new HtmlExpressionExtractor(directives);
+ return _getHtmlSources(transform, resolver)
+ .forEach(htmlExtractor.parseHtml)
+ .then((_) {
+ var module = new Module()
+ ..type(Parser, implementedBy: DynamicParser)
+ ..type(ParserBackend, implementedBy: DartGetterSetterGen);
+ var injector =
+ new DynamicInjector(modules: [module], allowImplicitInjection: true);
+
+ injector.get(_ParserGetterSetter).generateParser(
+ htmlExtractor.expressions.toList(), outputBuffer);
+
+ var id = transform.primaryInput.id;
+ var outputFilename = '${path.url.basenameWithoutExtension(id.path)}'
+ '_static_expressions.dart';
+ var outputPath = path.url.join(path.url.dirname(id.path), outputFilename);
+ var outputId = new AssetId(id.package, outputPath);
+ transform.addOutput(
+ new Asset.fromString(outputId, outputBuffer.toString()));
+
+ transform.addOutput(asset);
+ });
+ }
+
+ /**
+ * Gets a stream consisting of the contents of all HTML source files to be
+ * scoured for expressions.
+ */
+ Stream<String> _getHtmlSources(Transform transform, Resolver resolver) {
+ var id = transform.primaryInput.id;
+
+ var controller = new StreamController<String>();
+ var assets = options.htmlFiles
+ .map((path) => _uriToAssetId(path, transform))
+ .where((id) => id != null)
+ .toList();
+
+ // Get all of the contents of templates in @Component(templateUrl:'...')
+ gatherReferencedUris(transform, resolver, options,
+ templatesOnly: true).then((templates) {
+ templates.values.forEach(controller.add);
+ }).then((_) {
+ // Add any HTML files referencing this Dart file.
+ return _findHtmlEntry(transform);
+ }).then((htmlRefId) {
+ if (htmlRefId != null) {
+ assets.add(htmlRefId);
+ }
+ Future.wait(
+ // Add any manually specified HTML files.
+ assets.map((id) => transform.readInputAsString(id))
+ .map((future) =>
+ future.then(controller.add).catchError((e) {
+ transform.logger.warning('Unable to find $id from html_files '
+ 'in pubspec.yaml.');
+ }))
+ ).then((_) {
+ controller.close();
+ });
+ });
+
+ return controller.stream;
+ }
+
+ AssetId _uriToAssetId(String uri, Transform transform) {
+ if (path.url.isAbsolute(uri)) {
+ var parts = path.url.split(uri);
+ if (parts[1] == 'packages') {
+ var pkgPath = path.url.join('lib', path.url.joinAll(parts.skip(3)));
+ return new AssetId(parts[2], pkgPath);
+ }
+ transform.logger.warning('Cannot cache non-package absolute URIs. $uri');
+ return null;
+ }
+ return new AssetId(transform.primaryInput.id.package, uri);
+ }
+
+ /// Finds any HTML files referencing the primary input of the transform.
+ Future<AssetId> _findHtmlEntry(Transform transform) {
+ var id = transform.primaryInput.id;
+ // Magic file generated by HtmlDartReferencesGenerator
+ var htmlRefId = new AssetId(id.package, id.path + '.html_reference');
+
+ return transform.readInputAsString(htmlRefId).then((path) {
+ return new AssetId(id.package, path);
+ }, onError: (e, s) => null); // swallow not-found errors.
+ }
+}
+
+void _writeStaticExpressionHeader(AssetId id, StringSink sink) {
+ var libPath = path.withoutExtension(id.path).replaceAll('/', '.');
+ sink.write('''
+library ${id.package}.$libPath.generated_expressions;
+
+import 'package:angular/change_detection/change_detection.dart';
+
+''');
+}
+
+class _LibrarySourceCrawler implements SourceCrawler {
+ final Iterable<LibraryElement> libraries;
+ _LibrarySourceCrawler(this.libraries);
+
+ void crawl(String entryPoint, CompilationUnitVisitor visitor) {
+ libraries.expand((lib) => lib.units)
+ .map((compilationUnitElement) => compilationUnitElement.node)
+ .forEach(visitor);
+ }
+}
+
+class _ParserGetterSetter {
+ final Parser parser;
+ final ParserBackend backend;
+ _ParserGetterSetter(this.parser, this.backend);
+
+ generateParser(List<String> exprs, StringSink sink) {
+ exprs.forEach((expr) {
+ try {
+ parser(expr);
+ } catch (e) {
+ // Ignore exceptions.
+ }
+ });
+
+ DartGetterSetterGen backend = this.backend;
+ sink.write(generateClosures(backend.properties, backend.calls, backend.symbols));
+ }
+
+ String generateClosures(Set<String> properties,
+ Set<String> calls,
+ Set<String> symbols) {
+ var getters = new Set.from(properties)..addAll(calls);
+ return '''
+final Map<String, FieldGetter> getters = ${generateGetterMap(getters)};
+final Map<String, FieldSetter> setters = ${generateSetterMap(properties)};
+final Map<String, Symbol> symbols = ${generateSymbolMap(symbols)};
+''';
+ }
+
+ generateGetterMap(Iterable<String> keys) {
+ var lines = keys.map((key) => ' r"${key}": (o) => o.$key');
+ return '{\n${lines.join(",\n")}\n}';
+ }
+
+ generateSetterMap(Iterable<String> keys) {
+ var lines = keys.map((key) => ' r"${key}": (o, v) => o.$key = v');
+ return '{\n${lines.join(",\n")}\n}';
+ }
+
+ generateSymbolMap(Set<String> symbols) {
+ var lines = symbols.map((key) => ' r"${key}": #$key');
+ return '{\n${lines.join(",\n")}\n}';
+ }
+}
+

Powered by Google App Engine
This is Rietveld 408576698