OLD | NEW |
---|---|
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/src/generated/ast.dart'; |
9 import 'package:analyzer/src/generated/element.dart'; | 9 import 'package:analyzer/src/generated/element.dart'; |
10 import 'package:barback/barback.dart'; | 10 import 'package:barback/barback.dart'; |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
344 for (var interface in type.interfaces) { | 344 for (var interface in type.interfaces) { |
345 if (_isInitializer(interface)) return true; | 345 if (_isInitializer(interface)) return true; |
346 } | 346 } |
347 return false; | 347 return false; |
348 } | 348 } |
349 | 349 |
350 /// Retrieves all top-level methods that are visible if you were to import | 350 /// Retrieves all top-level methods that are visible if you were to import |
351 /// [lib]. This includes exported methods from other libraries too. | 351 /// [lib]. This includes exported methods from other libraries too. |
352 List<FunctionElement> _topLevelMethodsOfLibrary( | 352 List<FunctionElement> _topLevelMethodsOfLibrary( |
353 LibraryElement library, Set<LibraryElement> seen) { | 353 LibraryElement library, Set<LibraryElement> seen) { |
354 var result = []; | 354 var methods = []; |
355 result.addAll(library.units.expand((u) => u.functions)); | 355 |
356 for (var export in library.exports) { | 356 var orderedExports = new List.from(library.exports) |
357 ..sort((a, b) => a.uriOffset.compareTo(b.uriOffset)); | |
Siggi Cherem (dart-lang)
2015/03/17 19:50:29
I wonder if analyzer by default returns them in or
jakemac
2015/03/17 21:54:03
I would rather not rely on it
| |
358 for (var export in orderedExports) { | |
357 if (seen.contains(export.exportedLibrary)) continue; | 359 if (seen.contains(export.exportedLibrary)) continue; |
358 var exported = _topLevelMethodsOfLibrary(export.exportedLibrary, seen); | 360 methods.addAll(_topLevelMethodsOfLibrary(export.exportedLibrary, seen)); |
359 _filter(exported, export.combinators); | |
360 result.addAll(exported); | |
361 } | 361 } |
362 result.sort((a, b) => a.name.compareTo(b.name)); | 362 |
363 return result; | 363 var orderedUnits = new List.from(library.units) |
364 ..sort((a, b) => a.uriOffset.compareTo(b.uriOffset)); | |
Siggi Cherem (dart-lang)
2015/03/17 19:50:29
is the uriOffset here the uri where it is imported
jakemac
2015/03/17 21:54:03
This now does alphabetical order, to be consistent
| |
365 for (CompilationUnitElement unit in orderedUnits) { | |
366 methods.addAll(new List.from(unit.functions) | |
367 ..sort((a, b) => a.nameOffset.compareTo(b.nameOffset))); | |
368 } | |
369 | |
370 return methods; | |
364 } | 371 } |
365 | 372 |
366 /// Retrieves all classes that are visible if you were to import [lib]. This | 373 /// Retrieves all classes that are visible if you were to import [lib]. This |
367 /// includes exported classes from other libraries. | 374 /// includes exported classes from other libraries. |
368 List<ClassElement> _classesOfLibrary( | 375 List<ClassElement> _classesOfLibrary( |
369 LibraryElement library, Set<LibraryElement> seen) { | 376 LibraryElement library, Set<LibraryElement> seen) { |
370 var result = []; | 377 var classes = []; |
371 result.addAll(library.units.expand((u) => u.types)); | 378 |
372 for (var export in library.exports) { | 379 var orderedExports = new List.from(library.exports) |
380 ..sort((a, b) => a.uriOffset.compareTo(b.uriOffset)); | |
381 for (var export in orderedExports) { | |
373 if (seen.contains(export.exportedLibrary)) continue; | 382 if (seen.contains(export.exportedLibrary)) continue; |
374 var exported = _classesOfLibrary(export.exportedLibrary, seen); | 383 classes.addAll(_classesOfLibrary(export.exportedLibrary, seen)); |
375 _filter(exported, export.combinators); | |
376 result.addAll(exported); | |
377 } | 384 } |
378 result.sort((a, b) => a.name.compareTo(b.name)); | |
379 return result; | |
380 } | |
381 | 385 |
382 /// Filters [elements] that come from an export, according to its show/hide | 386 var orderedUnits = new List.from(library.units) |
383 /// combinators. This modifies [elements] in place. | 387 ..sort((a, b) => a.uriOffset.compareTo(b.uriOffset)); |
384 void _filter(List<Element> elements, List<NamespaceCombinator> combinators) { | 388 for (CompilationUnitElement unit in orderedUnits) { |
385 for (var c in combinators) { | 389 classes.addAll(new List.from(unit.types) |
386 if (c is ShowElementCombinator) { | 390 ..sort((a, b) => a.nameOffset.compareTo(b.nameOffset))); |
387 var show = c.shownNames.toSet(); | |
388 elements.retainWhere((e) => show.contains(e.displayName)); | |
389 } else if (c is HideElementCombinator) { | |
390 var hide = c.hiddenNames.toSet(); | |
391 elements.removeWhere((e) => hide.contains(e.displayName)); | |
392 } | |
393 } | 391 } |
392 | |
393 return classes; | |
394 } | 394 } |
395 | 395 |
396 Iterable<LibraryElement> _sortedLibraryDependencies(LibraryElement library) { | 396 Iterable<LibraryElement> _sortedLibraryDependencies(LibraryElement library) { |
397 // TODO(jakemac): Investigate supporting annotations on part-of directives. | 397 // TODO(jakemac): Investigate supporting annotations on part-of directives. |
398 getLibrary(UriReferencedElement element) { | 398 getLibrary(UriReferencedElement element) { |
399 if (element is ImportElement) return element.importedLibrary; | 399 if (element is ImportElement) return element.importedLibrary; |
400 if (element is ExportElement) return element.exportedLibrary; | 400 if (element is ExportElement) return element.exportedLibrary; |
401 } | 401 } |
402 | 402 |
403 return (new List.from(library.imports) | 403 return (new List.from(library.imports) |
404 ..addAll(library.exports) | 404 ..addAll(library.exports) |
405 ..sort((a, b) { | 405 ..sort((a, b) => a.nameOffset.compareTo(b.nameOffset))).map(getLibrary); |
406 // dart: imports don't have a uri | |
407 if (a.uri == null && b.uri != null) return -1; | |
408 if (b.uri == null && a.uri != null) return 1; | |
409 if (a.uri == null && b.uri == null) { | |
410 return getLibrary(a).name.compareTo(getLibrary(b).name); | |
411 } | |
412 | |
413 // package: imports next | |
414 var aIsPackage = a.uri.startsWith('package:'); | |
415 var bIsPackage = b.uri.startsWith('package:'); | |
416 if (aIsPackage && !bIsPackage) { | |
417 return -1; | |
418 } else if (bIsPackage && !aIsPackage) { | |
419 return 1; | |
420 } else if (bIsPackage && aIsPackage) { | |
421 return a.uri.compareTo(b.uri); | |
422 } | |
423 | |
424 // And finally compare based on the relative uri if both are file paths. | |
425 var aUri = path.url.relative(a.source.uri.path, | |
426 from: path.url.dirname(library.source.uri.path)); | |
427 var bUri = path.url.relative(b.source.uri.path, | |
428 from: path.url.dirname(library.source.uri.path)); | |
429 return aUri.compareTo(bUri); | |
430 })).map(getLibrary); | |
431 } | 406 } |
432 } | 407 } |
433 | 408 |
434 /// An [Initializer] annotation and the target of that annotation. | 409 /// An [Initializer] annotation and the target of that annotation. |
435 class InitializerData { | 410 class InitializerData { |
436 /// The target [AstNode] of the annotation. | 411 /// The target [AstNode] of the annotation. |
437 final AstNode targetNode; | 412 final AstNode targetNode; |
438 | 413 |
439 /// The [Annotation] representing the annotation itself. | 414 /// The [Annotation] representing the annotation itself. |
440 final Annotation annotationNode; | 415 final Annotation annotationNode; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
472 error = false; | 447 error = false; |
473 } else { | 448 } else { |
474 error = true; | 449 error = true; |
475 } | 450 } |
476 if (error) { | 451 if (error) { |
477 print('Bad value for "$field" in the initialize transformer. ' | 452 print('Bad value for "$field" in the initialize transformer. ' |
478 'Expected either one String or a list of Strings.'); | 453 'Expected either one String or a list of Strings.'); |
479 } | 454 } |
480 return files; | 455 return files; |
481 } | 456 } |
OLD | NEW |