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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 library angular.tools.transformer.expression_generator;
2
3 import 'dart:async';
4 import 'package:analyzer/src/generated/element.dart';
5 import 'package:angular/core/parser/parser.dart';
6 import 'package:angular/tools/html_extractor.dart';
7 import 'package:angular/tools/parser_getter_setter/generator.dart';
8 import 'package:angular/tools/source_crawler.dart';
9 import 'package:angular/tools/source_metadata_extractor.dart';
10 import 'package:angular/tools/transformer/options.dart';
11 import 'package:angular/tools/transformer/referenced_uris.dart';
12 import 'package:barback/barback.dart';
13 import 'package:code_transformers/resolver.dart';
14 import 'package:di/di.dart';
15 import 'package:di/dynamic_injector.dart';
16 import 'package:path/path.dart' as path;
17
18 /**
19 * Transformer which gathers all expressions from the HTML source files and
20 * Dart source files of an application and packages them for static evaluation.
21 *
22 * This will also modify the main Dart source file to import the generated
23 * expressions and modify all references to NG_EXPRESSION_MODULE to refer to
24 * the generated expressions.
25 */
26 class ExpressionGenerator extends Transformer with ResolverTransformer {
27 final TransformOptions options;
28
29 ExpressionGenerator(this.options, Resolvers resolvers) {
30 this.resolvers = resolvers;
31 }
32
33 Future applyResolver(Transform transform, Resolver resolver) {
34 var asset = transform.primaryInput;
35 var outputBuffer = new StringBuffer();
36
37 _writeStaticExpressionHeader(asset.id, outputBuffer);
38
39 var sourceMetadataExtractor = new SourceMetadataExtractor();
40 var directives =
41 sourceMetadataExtractor.gatherDirectiveInfo(null,
42 new _LibrarySourceCrawler(resolver.libraries));
43
44 var htmlExtractor = new HtmlExpressionExtractor(directives);
45 return _getHtmlSources(transform, resolver)
46 .forEach(htmlExtractor.parseHtml)
47 .then((_) {
48 var module = new Module()
49 ..type(Parser, implementedBy: DynamicParser)
50 ..type(ParserBackend, implementedBy: DartGetterSetterGen);
51 var injector =
52 new DynamicInjector(modules: [module], allowImplicitInjection: true);
53
54 injector.get(_ParserGetterSetter).generateParser(
55 htmlExtractor.expressions.toList(), outputBuffer);
56
57 var id = transform.primaryInput.id;
58 var outputFilename = '${path.url.basenameWithoutExtension(id.path)}'
59 '_static_expressions.dart';
60 var outputPath = path.url.join(path.url.dirname(id.path), outputFilename);
61 var outputId = new AssetId(id.package, outputPath);
62 transform.addOutput(
63 new Asset.fromString(outputId, outputBuffer.toString()));
64
65 transform.addOutput(asset);
66 });
67 }
68
69 /**
70 * Gets a stream consisting of the contents of all HTML source files to be
71 * scoured for expressions.
72 */
73 Stream<String> _getHtmlSources(Transform transform, Resolver resolver) {
74 var id = transform.primaryInput.id;
75
76 var controller = new StreamController<String>();
77 var assets = options.htmlFiles
78 .map((path) => _uriToAssetId(path, transform))
79 .where((id) => id != null)
80 .toList();
81
82 // Get all of the contents of templates in @Component(templateUrl:'...')
83 gatherReferencedUris(transform, resolver, options,
84 templatesOnly: true).then((templates) {
85 templates.values.forEach(controller.add);
86 }).then((_) {
87 // Add any HTML files referencing this Dart file.
88 return _findHtmlEntry(transform);
89 }).then((htmlRefId) {
90 if (htmlRefId != null) {
91 assets.add(htmlRefId);
92 }
93 Future.wait(
94 // Add any manually specified HTML files.
95 assets.map((id) => transform.readInputAsString(id))
96 .map((future) =>
97 future.then(controller.add).catchError((e) {
98 transform.logger.warning('Unable to find $id from html_files '
99 'in pubspec.yaml.');
100 }))
101 ).then((_) {
102 controller.close();
103 });
104 });
105
106 return controller.stream;
107 }
108
109 AssetId _uriToAssetId(String uri, Transform transform) {
110 if (path.url.isAbsolute(uri)) {
111 var parts = path.url.split(uri);
112 if (parts[1] == 'packages') {
113 var pkgPath = path.url.join('lib', path.url.joinAll(parts.skip(3)));
114 return new AssetId(parts[2], pkgPath);
115 }
116 transform.logger.warning('Cannot cache non-package absolute URIs. $uri');
117 return null;
118 }
119 return new AssetId(transform.primaryInput.id.package, uri);
120 }
121
122 /// Finds any HTML files referencing the primary input of the transform.
123 Future<AssetId> _findHtmlEntry(Transform transform) {
124 var id = transform.primaryInput.id;
125 // Magic file generated by HtmlDartReferencesGenerator
126 var htmlRefId = new AssetId(id.package, id.path + '.html_reference');
127
128 return transform.readInputAsString(htmlRefId).then((path) {
129 return new AssetId(id.package, path);
130 }, onError: (e, s) => null); // swallow not-found errors.
131 }
132 }
133
134 void _writeStaticExpressionHeader(AssetId id, StringSink sink) {
135 var libPath = path.withoutExtension(id.path).replaceAll('/', '.');
136 sink.write('''
137 library ${id.package}.$libPath.generated_expressions;
138
139 import 'package:angular/change_detection/change_detection.dart';
140
141 ''');
142 }
143
144 class _LibrarySourceCrawler implements SourceCrawler {
145 final Iterable<LibraryElement> libraries;
146 _LibrarySourceCrawler(this.libraries);
147
148 void crawl(String entryPoint, CompilationUnitVisitor visitor) {
149 libraries.expand((lib) => lib.units)
150 .map((compilationUnitElement) => compilationUnitElement.node)
151 .forEach(visitor);
152 }
153 }
154
155 class _ParserGetterSetter {
156 final Parser parser;
157 final ParserBackend backend;
158 _ParserGetterSetter(this.parser, this.backend);
159
160 generateParser(List<String> exprs, StringSink sink) {
161 exprs.forEach((expr) {
162 try {
163 parser(expr);
164 } catch (e) {
165 // Ignore exceptions.
166 }
167 });
168
169 DartGetterSetterGen backend = this.backend;
170 sink.write(generateClosures(backend.properties, backend.calls, backend.symbo ls));
171 }
172
173 String generateClosures(Set<String> properties,
174 Set<String> calls,
175 Set<String> symbols) {
176 var getters = new Set.from(properties)..addAll(calls);
177 return '''
178 final Map<String, FieldGetter> getters = ${generateGetterMap(getters)};
179 final Map<String, FieldSetter> setters = ${generateSetterMap(properties)};
180 final Map<String, Symbol> symbols = ${generateSymbolMap(symbols)};
181 ''';
182 }
183
184 generateGetterMap(Iterable<String> keys) {
185 var lines = keys.map((key) => ' r"${key}": (o) => o.$key');
186 return '{\n${lines.join(",\n")}\n}';
187 }
188
189 generateSetterMap(Iterable<String> keys) {
190 var lines = keys.map((key) => ' r"${key}": (o, v) => o.$key = v');
191 return '{\n${lines.join(",\n")}\n}';
192 }
193
194 generateSymbolMap(Set<String> symbols) {
195 var lines = symbols.map((key) => ' r"${key}": #$key');
196 return '{\n${lines.join(",\n")}\n}';
197 }
198 }
199
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698