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

Side by Side Diff: packages/initialize/lib/transformer.dart

Issue 2989763002: Update charted to 0.4.8 and roll (Closed)
Patch Set: Removed Cutch from list of reviewers Created 3 years, 4 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
« no previous file with comments | « packages/initialize/lib/src/mirror_loader.dart ('k') | packages/initialize/pubspec.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 library initialize.transformer; 4 library initialize.transformer;
5 5
6 import 'dart:async'; 6 import 'dart:async';
7 import 'dart:collection' show Queue; 7 import 'dart:collection' show Queue;
8 import 'package:analyzer/src/generated/ast.dart'; 8 import 'package:analyzer/dart/ast/ast.dart';
9 import 'package:analyzer/src/generated/element.dart'; 9 import 'package:analyzer/dart/element/element.dart';
10 import 'package:analyzer/dart/element/type.dart';
10 import 'package:barback/barback.dart'; 11 import 'package:barback/barback.dart';
11 import 'package:code_transformers/assets.dart'; 12 import 'package:code_transformers/assets.dart';
12 import 'package:code_transformers/resolver.dart'; 13 import 'package:code_transformers/resolver.dart';
13 import 'package:code_transformers/src/dart_sdk.dart' as dart_sdk; 14 import 'package:code_transformers/src/dart_sdk.dart' as dart_sdk;
14 import 'package:dart_style/dart_style.dart'; 15 import 'package:dart_style/dart_style.dart';
15 import 'package:glob/glob.dart'; 16 import 'package:glob/glob.dart';
16 import 'package:html/dom.dart' as dom; 17 import 'package:html/dom.dart' as dom;
17 import 'package:html/parser.dart' show parse; 18 import 'package:html/parser.dart' show parse;
18 import 'package:path/path.dart' as path; 19 import 'package:path/path.dart' as path;
19 20
20 import 'build/initializer_plugin.dart'; 21 import 'build/initializer_plugin.dart';
21 export 'build/initializer_plugin.dart'; 22 export 'build/initializer_plugin.dart';
22 23
23 /// Create a new [Asset] which inlines your [Initializer] annotations into 24 /// Create a new [Asset] which inlines your [Initializer] annotations into
24 /// a new file that bootstraps your application. 25 /// a new file that bootstraps your application.
25 Asset generateBootstrapFile(Resolver resolver, Transform transform, 26 Asset generateBootstrapFile(Resolver resolver, Transform transform,
26 AssetId primaryAssetId, AssetId newEntryPointId, 27 AssetId primaryAssetId, AssetId newEntryPointId,
27 {bool errorIfNotFound: true, List<InitializerPlugin> plugins, 28 {bool errorIfNotFound: true,
29 List<InitializerPlugin> plugins,
28 bool appendDefaultPlugin: true}) { 30 bool appendDefaultPlugin: true}) {
29 if (appendDefaultPlugin) { 31 if (appendDefaultPlugin) {
30 if (plugins == null) plugins = []; 32 if (plugins == null) plugins = [];
31 plugins.add(const DefaultInitializerPlugin()); 33 plugins.add(const DefaultInitializerPlugin());
32 } 34 }
33 return new _BootstrapFileBuilder( 35 return new _BootstrapFileBuilder(
34 resolver, transform, primaryAssetId, newEntryPointId, errorIfNotFound, 36 resolver, transform, primaryAssetId, newEntryPointId, errorIfNotFound,
35 plugins: plugins).run(); 37 plugins: plugins)
38 .run();
36 } 39 }
37 40
38 /// Transformer which removes the mirror-based initialization logic and replaces 41 /// Transformer which removes the mirror-based initialization logic and replaces
39 /// it with static logic. 42 /// it with static logic.
40 class InitializeTransformer extends Transformer { 43 class InitializeTransformer extends Transformer {
41 final Resolvers _resolvers; 44 final Resolvers _resolvers;
42 final Iterable<Glob> _entryPointGlobs; 45 final Iterable<Glob> _entryPointGlobs;
43 final bool _errorIfNotFound; 46 final bool _errorIfNotFound;
44 final List<InitializerPlugin> plugins; 47 final List<InitializerPlugin> plugins;
45 48
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 94
92 return _resolvers.get(transform, [primaryId]).then((resolver) { 95 return _resolvers.get(transform, [primaryId]).then((resolver) {
93 transform.addOutput(generateBootstrapFile( 96 transform.addOutput(generateBootstrapFile(
94 resolver, transform, primaryId, newEntryPointId, 97 resolver, transform, primaryId, newEntryPointId,
95 errorIfNotFound: _errorIfNotFound, plugins: plugins)); 98 errorIfNotFound: _errorIfNotFound, plugins: plugins));
96 resolver.release(); 99 resolver.release();
97 return newEntryPointId; 100 return newEntryPointId;
98 }); 101 });
99 }); 102 });
100 } 103 }
104
101 // Finds the first (and only) dart script on an html page and returns the 105 // Finds the first (and only) dart script on an html page and returns the
102 // [AssetId] that points to it 106 // [AssetId] that points to it
103 AssetId _findMainScript( 107 AssetId _findMainScript(
104 dom.Document document, AssetId entryPoint, Transform transform) { 108 dom.Document document, AssetId entryPoint, Transform transform) {
105 var scripts = document.querySelectorAll('script[type="application/dart"]'); 109 var scripts = _getScripts(document);
106 if (scripts.length != 1) { 110 if (scripts.length != 1) {
107 transform.logger.error('Expected exactly one dart script in $entryPoint ' 111 transform.logger.error('Expected exactly one dart script in $entryPoint '
108 'but found ${scripts.length}.'); 112 'but found ${scripts.length}.');
109 return null; 113 return null;
110 } 114 }
111 115
112 var src = scripts[0].attributes['src']; 116 var src = _getScriptAttribute(scripts[0]);
113 if (src == null) { 117 if (src == null) {
114 // TODO(jakemac): Support inline scripts, 118 // TODO(jakemac): Support inline scripts,
115 transform.logger.error('Inline scripts are not supported at this time, ' 119 transform.logger.error('Inline scripts are not supported at this time, '
116 'see https://github.com/dart-lang/initialize/issues/20.'); 120 'see https://github.com/dart-lang/initialize/issues/20.');
117 return null; 121 return null;
118 } 122 }
119 123
120 return uriToAssetId( 124 return uriToAssetId(
121 entryPoint, src, transform.logger, scripts[0].sourceSpan); 125 entryPoint, src, transform.logger, scripts[0].sourceSpan);
122 } 126 }
123 127
124 // Replaces script tags pointing to [originalDartFile] with [newDartFile] in 128 // Replaces script tags pointing to [originalDartFile] with [newDartFile] in
125 // [entryPoint]. 129 // [entryPoint].
126 void _replaceEntryWithBootstrap(Transform transform, dom.Document document, 130 void _replaceEntryWithBootstrap(Transform transform, dom.Document document,
127 AssetId entryPoint, AssetId originalDartFile, AssetId newDartFile) { 131 AssetId entryPoint, AssetId originalDartFile, AssetId newDartFile) {
128 var found = false; 132 var scripts = _getScripts(document)
129
130 var scripts = document
131 .querySelectorAll('script[type="application/dart"]')
132 .where((script) { 133 .where((script) {
133 var assetId = uriToAssetId(entryPoint, script.attributes['src'], 134 var assetId = uriToAssetId(entryPoint, _getScriptAttribute(script),
134 transform.logger, script.sourceSpan); 135 transform.logger, script.sourceSpan);
135 return assetId == originalDartFile; 136 return assetId == originalDartFile;
136 }).toList(); 137 }).toList();
137 138
138 if (scripts.length != 1) { 139 if (scripts.length != 1) {
139 transform.logger.error( 140 transform.logger
140 'Expected exactly one script pointing to $originalDartFile in ' 141 .error('Expected exactly one script pointing to $originalDartFile in '
141 '$entryPoint, but found ${scripts.length}.'); 142 '$entryPoint, but found ${scripts.length}.');
142 return; 143 return;
143 } 144 }
144 scripts[0].attributes['src'] = path.url.relative(newDartFile.path, 145 _setScriptAttribute(
145 from: path.dirname(entryPoint.path)); 146 scripts[0],
147 path.url
148 .relative(newDartFile.path, from: path.dirname(entryPoint.path)));
146 transform.addOutput(new Asset.fromString(entryPoint, document.outerHtml)); 149 transform.addOutput(new Asset.fromString(entryPoint, document.outerHtml));
147 } 150 }
151
152 String _getScriptAttribute(dom.Element element) {
153 switch (element.localName) {
154 case 'script':
155 return element.attributes['src'];
156 case 'link':
157 return element.attributes['href'];
158 default:
159 throw 'Unrecognized element $element';
160 }
161 }
162
163 void _setScriptAttribute(dom.Element element, String path) {
164 switch (element.localName) {
165 case 'script':
166 element.attributes['src'] = path;
167 break;
168 case 'link':
169 element.attributes['href'] = path;
170 break;
171 }
172 }
173
174 List<dom.Element> _getScripts(dom.Document document) =>
175 document.querySelectorAll(
176 'script[type="application/dart"], link[rel="x-dart-test"]');
148 } 177 }
149 178
150 // Class which builds a bootstrap file. 179 // Class which builds a bootstrap file.
151 class _BootstrapFileBuilder { 180 class _BootstrapFileBuilder {
152 final Resolver _resolver; 181 final Resolver _resolver;
153 final Transform _transform; 182 final Transform _transform;
154 final bool _errorIfNotFound; 183 final bool _errorIfNotFound;
155 AssetId _entryPoint; 184 AssetId _entryPoint;
156 AssetId _newEntryPoint; 185 AssetId _newEntryPoint;
157 186
158 /// The resolved initialize library. 187 /// The resolved initialize library.
159 LibraryElement _initializeLibrary; 188 LibraryElement _initializeLibrary;
189
160 /// The resolved Initializer class from the initialize library. 190 /// The resolved Initializer class from the initialize library.
161 ClassElement _initializer; 191 ClassElement _initializer;
162 192
163 /// Queue for intialization annotations. 193 /// Queue for intialization annotations.
164 final _initQueue = new Queue<InitializerData>(); 194 final _initQueue = new Queue<InitializerData>();
195
165 /// All the annotations we have seen for each element 196 /// All the annotations we have seen for each element
166 final _seenAnnotations = new Map<Element, Set<ElementAnnotation>>(); 197 final _seenAnnotations = new Map<Element, Set<ElementAnnotation>>();
167 198
168 /// The list of [InitializerPlugin]s to apply. The first plugin which asks to 199 /// The list of [InitializerPlugin]s to apply. The first plugin which asks to
169 /// be applied to a given initializer is the only one that will apply. 200 /// be applied to a given initializer is the only one that will apply.
170 List<InitializerPlugin> _plugins; 201 List<InitializerPlugin> _plugins;
171 202
172 TransformLogger _logger; 203 TransformLogger _logger;
173 204
174 _BootstrapFileBuilder(this._resolver, this._transform, this._entryPoint, 205 _BootstrapFileBuilder(this._resolver, this._transform, this._entryPoint,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 '(possibly transitive).'); 258 '(possibly transitive).');
228 } 259 }
229 } 260 }
230 readSuperClassAnnotations(clazz.supertype); 261 readSuperClassAnnotations(clazz.supertype);
231 _readAnnotations(clazz); 262 _readAnnotations(clazz);
232 } 263 }
233 } 264 }
234 265
235 bool _readAnnotations(Element element) { 266 bool _readAnnotations(Element element) {
236 var found = false; 267 var found = false;
237 if (element.metadata.isEmpty) return found; 268 // analyzer 0.29 doesn't allow this optimization :
269 //if (element.metadata.isEmpty) return found;
238 270
239 var metaNodes; 271 var metaNodes;
240 var node = element.node; 272 var node = element.computeNode();
241 if (node is SimpleIdentifier && node.parent is LibraryIdentifier) { 273 if (node is SimpleIdentifier && node.parent is LibraryIdentifier) {
242 metaNodes = node.parent.parent.metadata; 274 metaNodes = node.parent.parent.metadata;
243 } else if (node is ClassDeclaration || node is FunctionDeclaration) { 275 } else if (node is ClassDeclaration || node is FunctionDeclaration) {
244 metaNodes = node.metadata; 276 metaNodes = node.metadata;
245 } else { 277 } else {
246 return found; 278 return found;
247 } 279 }
248 280
249 metaNodes.where((Annotation metaNode) { 281 metaNodes.where((Annotation metaNode) {
250 // First filter out anything that is not a Initializer. 282 // First filter out anything that is not a Initializer.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 _writeImport(LibraryElement lib, String prefix, StringBuffer buffer) { 351 _writeImport(LibraryElement lib, String prefix, StringBuffer buffer) {
320 AssetId id = (lib.source as dynamic).assetId; 352 AssetId id = (lib.source as dynamic).assetId;
321 353
322 if (id.path.startsWith('lib/')) { 354 if (id.path.startsWith('lib/')) {
323 var packagePath = id.path.replaceFirst('lib/', ''); 355 var packagePath = id.path.replaceFirst('lib/', '');
324 buffer.write("import 'package:${id.package}/${packagePath}'"); 356 buffer.write("import 'package:${id.package}/${packagePath}'");
325 } else if (id.package != _newEntryPoint.package) { 357 } else if (id.package != _newEntryPoint.package) {
326 _logger.error("Can't import `${id}` from `${_newEntryPoint}`"); 358 _logger.error("Can't import `${id}` from `${_newEntryPoint}`");
327 } else if (path.url.split(id.path)[0] == 359 } else if (path.url.split(id.path)[0] ==
328 path.url.split(_newEntryPoint.path)[0]) { 360 path.url.split(_newEntryPoint.path)[0]) {
329 var relativePath = path.url.relative(id.path, 361 var relativePath = path.url
330 from: path.url.dirname(_newEntryPoint.path)); 362 .relative(id.path, from: path.url.dirname(_newEntryPoint.path));
331 buffer.write("import '${relativePath}'"); 363 buffer.write("import '${relativePath}'");
332 } else { 364 } else {
333 _logger.error("Can't import `${id}` from `${_newEntryPoint}`"); 365 _logger.error("Can't import `${id}` from `${_newEntryPoint}`");
334 } 366 }
335 buffer.writeln(' as $prefix;'); 367 buffer.writeln(' as $prefix;');
336 } 368 }
337 369
338 bool _isInitializer(InterfaceType type) { 370 bool _isInitializer(InterfaceType type) {
339 // If `_initializer` wasn't found then it was never loaded (even 371 // If `_initializer` wasn't found then it was never loaded (even
340 // transitively), and so no annotations can be initializers. 372 // transitively), and so no annotations can be initializers.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 } 434 }
403 435
404 Iterable<LibraryElement> _sortedLibraryDependencies(LibraryElement library) { 436 Iterable<LibraryElement> _sortedLibraryDependencies(LibraryElement library) {
405 // TODO(jakemac): Investigate supporting annotations on part-of directives. 437 // TODO(jakemac): Investigate supporting annotations on part-of directives.
406 getLibrary(UriReferencedElement element) { 438 getLibrary(UriReferencedElement element) {
407 if (element is ImportElement) return element.importedLibrary; 439 if (element is ImportElement) return element.importedLibrary;
408 if (element is ExportElement) return element.exportedLibrary; 440 if (element is ExportElement) return element.exportedLibrary;
409 } 441 }
410 442
411 return (new List.from(library.imports) 443 return (new List.from(library.imports)
412 ..addAll(library.exports) 444 ..addAll(library.exports)
413 ..sort((a, b) => a.nameOffset.compareTo(b.nameOffset))).map(getLibrary); 445 ..sort((a, b) => a.nameOffset.compareTo(b.nameOffset)))
446 .map(getLibrary);
414 } 447 }
415 } 448 }
416 449
417 /// An [Initializer] annotation and the target of that annotation. 450 /// An [Initializer] annotation and the target of that annotation.
418 class InitializerData { 451 class InitializerData {
419 /// The target [AstNode] of the annotation. 452 /// The target [AstNode] of the annotation.
420 final AstNode targetNode; 453 final AstNode targetNode;
421 454
422 /// The [Annotation] representing the annotation itself. 455 /// The [Annotation] representing the annotation itself.
423 final Annotation annotationNode; 456 final Annotation annotationNode;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 error = false; 488 error = false;
456 } else { 489 } else {
457 error = true; 490 error = true;
458 } 491 }
459 if (error) { 492 if (error) {
460 print('Bad value for "$field" in the initialize transformer. ' 493 print('Bad value for "$field" in the initialize transformer. '
461 'Expected either one String or a list of Strings.'); 494 'Expected either one String or a list of Strings.');
462 } 495 }
463 return files; 496 return files;
464 } 497 }
OLDNEW
« no previous file with comments | « packages/initialize/lib/src/mirror_loader.dart ('k') | packages/initialize/pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698