Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 import 'package:analyzer/src/generated/element.dart'; | |
| 2 import 'package:path/path.dart' as path; | |
| 3 | |
| 4 import 'annotation_processor.dart'; | |
| 5 | |
| 6 class ImportTraversal { | |
|
jakemac
2015/02/17 23:46:46
ImportTraverser maybe?
tjblasi
2015/02/18 21:18:25
Acknowledged.
| |
| 7 final AnnotationMatcher _annotationMatcher; | |
| 8 | |
| 9 ImportTraversal(this._annotationMatcher); | |
| 10 | |
| 11 /// Reads Initializer annotations on this library and all its dependencies in | |
| 12 /// post-order. | |
| 13 void traverse(LibraryElement library, [Set<LibraryElement> seen]) { | |
|
jakemac
2015/02/18 16:18:50
Looks to me like this is still doing the normal tr
tjblasi
2015/02/18 21:18:25
Discussed offline
| |
| 14 if (seen == null) seen = new Set<LibraryElement>(); | |
| 15 seen.add(library); | |
| 16 | |
| 17 // Visit all our dependencies. | |
| 18 for (var importedLibrary in _sortedLibraryImports(library)) { | |
| 19 // Don't include anything from the sdk. | |
| 20 if (importedLibrary.isInSdk) continue; | |
| 21 if (seen.contains(importedLibrary)) continue; | |
| 22 traverse(importedLibrary, seen); | |
| 23 } | |
| 24 | |
| 25 for (var clazz in _classesOfLibrary(library, seen)) { | |
| 26 var superClass = clazz.supertype; | |
| 27 while (superClass != null) { | |
| 28 if (_annotationMatcher.processAnnotations(superClass.element) && | |
|
jakemac
2015/02/17 23:46:46
I think that for angular this might not matter, as
tjblasi
2015/02/18 21:18:25
Acknowledged.
| |
| 29 superClass.element.library != clazz.library) { | |
| 30 _logger.warning( | |
| 31 'We have detected a cycle in your import graph when running ' | |
| 32 'initializers on ${clazz.name}. This means the super class ' | |
| 33 '${superClass.name} has a dependency on this library ' | |
| 34 '(possibly transitive).'); | |
| 35 } | |
| 36 superClass = superClass.superclass; | |
| 37 } | |
| 38 _annotationMatcher.processAnnotations(clazz); | |
| 39 } | |
| 40 } | |
| 41 | |
| 42 /// Retrieves all classes that are visible if you were to import [lib]. This | |
| 43 /// includes exported classes from other libraries. | |
| 44 List<ClassElement> _classesOfLibrary( | |
| 45 LibraryElement library, Set<LibraryElement> seen) { | |
| 46 var result = []; | |
| 47 result.addAll(library.units.expand((u) => u.types)); | |
| 48 for (var export in library.exports) { | |
| 49 if (seen.contains(export.exportedLibrary)) continue; | |
| 50 var exported = _classesOfLibrary(export.exportedLibrary, seen); | |
| 51 _filter(exported, export.combinators); | |
| 52 result.addAll(exported); | |
| 53 } | |
| 54 result.sort((a, b) => a.name.compareTo(b.name)); | |
| 55 return result; | |
| 56 } | |
| 57 | |
| 58 /// Filters [elements] that come from an export, according to its show/hide | |
| 59 /// combinators. This modifies [elements] in place. | |
| 60 void _filter(List<Element> elements, List<NamespaceCombinator> combinators) { | |
| 61 for (var c in combinators) { | |
| 62 if (c is ShowElementCombinator) { | |
| 63 var show = c.shownNames.toSet(); | |
| 64 elements.retainWhere((e) => show.contains(e.displayName)); | |
| 65 } else if (c is HideElementCombinator) { | |
| 66 var hide = c.hiddenNames.toSet(); | |
| 67 elements.removeWhere((e) => hide.contains(e.displayName)); | |
| 68 } | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 Iterable<LibraryElement> _sortedLibraryImports(LibraryElement library) => | |
| 73 (new List.from(library.imports) | |
| 74 ..sort((ImportElement a, ImportElement b) { | |
| 75 // dart: imports don't have a uri | |
| 76 if (a.uri == null && b.uri != null) return -1; | |
| 77 if (b.uri == null && a.uri != null) return 1; | |
| 78 if (a.uri == null && b.uri == null) { | |
| 79 return a.importedLibrary.name.compareTo(b.importedLibrary.name); | |
| 80 } | |
| 81 | |
| 82 // package: imports next | |
| 83 var aIsPackage = a.uri.startsWith('package:'); | |
| 84 var bIsPackage = b.uri.startsWith('package:'); | |
| 85 if (aIsPackage && !bIsPackage) { | |
| 86 return -1; | |
| 87 } else if (bIsPackage && !aIsPackage) { | |
| 88 return 1; | |
| 89 } else if (bIsPackage && aIsPackage) { | |
| 90 return a.uri.compareTo(b.uri); | |
| 91 } | |
| 92 | |
| 93 // And finally compare based on the relative uri if both are file paths. | |
| 94 var aUri = path.relative(a.source.uri.path, | |
| 95 from: path.dirname(library.source.uri.path)); | |
| 96 var bUri = path.relative(b.source.uri.path, | |
| 97 from: path.dirname(library.source.uri.path)); | |
| 98 return aUri.compareTo(bUri); | |
| 99 })).map((import) => import.importedLibrary); | |
| 100 } | |
| OLD | NEW |