| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 // This code was auto-generated, is not intended to be edited, and is subject to |
| 6 // significant change. Please see the README file for more information. |
| 7 |
| 8 library services.hierarchy; |
| 9 |
| 10 import 'dart:async'; |
| 11 import 'dart:collection'; |
| 12 |
| 13 import 'package:analysis_services/search/search_engine.dart'; |
| 14 import 'package:analyzer/src/generated/element.dart'; |
| 15 |
| 16 |
| 17 /** |
| 18 * Returns direct children of [parent]. |
| 19 */ |
| 20 List<Element> getChildren(Element parent, [String name]) { |
| 21 List<Element> children = <Element>[]; |
| 22 parent.visitChildren(new _ElementVisitorAdapter((Element element) { |
| 23 if (name == null || element.displayName == name) { |
| 24 children.add(element); |
| 25 } |
| 26 })); |
| 27 return children; |
| 28 } |
| 29 |
| 30 |
| 31 /** |
| 32 * Returns direct non-synthetic children of the given [ClassElement]. |
| 33 * |
| 34 * Includes: fields, accessors and methods. |
| 35 * Excludes: constructors and synthetic elements. |
| 36 */ |
| 37 List<Element> getClassMembers(ClassElement clazz, [String name]) { |
| 38 List<Element> members = <Element>[]; |
| 39 clazz.visitChildren(new _ElementVisitorAdapter((Element element) { |
| 40 if (element.isSynthetic) { |
| 41 return; |
| 42 } |
| 43 if (element is ConstructorElement) { |
| 44 return; |
| 45 } |
| 46 if (name != null && element.displayName != name) { |
| 47 return; |
| 48 } |
| 49 if (element is ExecutableElement) { |
| 50 members.add(element); |
| 51 } |
| 52 if (element is FieldElement) { |
| 53 members.add(element); |
| 54 } |
| 55 })); |
| 56 return members; |
| 57 } |
| 58 |
| 59 |
| 60 /** |
| 61 * Returns a [Set] with direct subclasses of [seed]. |
| 62 */ |
| 63 Future<Set<ClassElement>> getDirectSubClasses(SearchEngine searchEngine, |
| 64 ClassElement seed) { |
| 65 return searchEngine.searchSubtypes(seed).then((List<SearchMatch> matches) { |
| 66 Set<ClassElement> subClasses = new HashSet<ClassElement>(); |
| 67 for (SearchMatch match in matches) { |
| 68 ClassElement subClass = match.element; |
| 69 if (subClass.context == seed.context) { |
| 70 subClasses.add(subClass); |
| 71 } |
| 72 } |
| 73 return subClasses; |
| 74 }); |
| 75 } |
| 76 |
| 77 |
| 78 /** |
| 79 * @return all implementations of the given {@link ClassMemberElement} is its su
perclasses and |
| 80 * their subclasses. |
| 81 */ |
| 82 Future<Set<ClassMemberElement>> getHierarchyMembers(SearchEngine searchEngine, |
| 83 ClassMemberElement member) { |
| 84 Set<ClassMemberElement> result = new HashSet<ClassMemberElement>(); |
| 85 // constructor |
| 86 if (member is ConstructorElement) { |
| 87 result.add(member); |
| 88 return new Future.value(result); |
| 89 } |
| 90 // method, field, etc |
| 91 String name = member.displayName; |
| 92 ClassElement memberClass = member.enclosingElement; |
| 93 List<Future> futures = <Future>[]; |
| 94 Set<ClassElement> searchClasses = getSuperClasses(memberClass); |
| 95 searchClasses.add(memberClass); |
| 96 for (ClassElement superClass in searchClasses) { |
| 97 // ignore if super- class does not declare member |
| 98 if (getClassMembers(superClass, name).isEmpty) { |
| 99 continue; |
| 100 } |
| 101 // check all sub- classes |
| 102 var subClassFuture = getSubClasses(searchEngine, superClass); |
| 103 var membersFuture = subClassFuture.then((Set<ClassElement> subClasses) { |
| 104 subClasses.add(superClass); |
| 105 for (ClassElement subClass in subClasses) { |
| 106 List<Element> subClassMembers = getChildren(subClass, name); |
| 107 for (Element member in subClassMembers) { |
| 108 if (member is ClassMemberElement) { |
| 109 result.add(member); |
| 110 } |
| 111 } |
| 112 } |
| 113 }); |
| 114 futures.add(membersFuture); |
| 115 } |
| 116 return Future.wait(futures).then((_) { |
| 117 return result; |
| 118 }); |
| 119 } |
| 120 |
| 121 |
| 122 /** |
| 123 * Returns a [Set] with all direct and indirect subclasses of [seed]. |
| 124 */ |
| 125 Future<Set<ClassElement>> getSubClasses(SearchEngine searchEngine, |
| 126 ClassElement seed) { |
| 127 Set<ClassElement> subs = new HashSet<ClassElement>(); |
| 128 // prepare queue |
| 129 List<ClassElement> queue = new List<ClassElement>(); |
| 130 queue.add(seed); |
| 131 // schedule subclasss search |
| 132 addSubClasses() { |
| 133 // add direct subclasses of the next class |
| 134 while (queue.isNotEmpty) { |
| 135 ClassElement clazz = queue.removeLast(); |
| 136 if (subs.add(clazz)) { |
| 137 return getDirectSubClasses(searchEngine, clazz).then((directSubs) { |
| 138 queue.addAll(directSubs); |
| 139 return new Future(addSubClasses); |
| 140 }); |
| 141 } |
| 142 } |
| 143 // done |
| 144 subs.remove(seed); |
| 145 return subs; |
| 146 } |
| 147 return new Future(addSubClasses); |
| 148 } |
| 149 |
| 150 |
| 151 /** |
| 152 * Returns a [Set] with all direct and indirect superclasses of [seed]. |
| 153 */ |
| 154 Set<ClassElement> getSuperClasses(ClassElement seed) { |
| 155 Set<ClassElement> result = new HashSet<ClassElement>(); |
| 156 // prepare queue |
| 157 List<ClassElement> queue = new List<ClassElement>(); |
| 158 queue.add(seed); |
| 159 // process queue |
| 160 while (!queue.isEmpty) { |
| 161 ClassElement current = queue.removeLast(); |
| 162 // add if not checked already |
| 163 if (!result.add(current)) { |
| 164 continue; |
| 165 } |
| 166 // append supertype |
| 167 { |
| 168 InterfaceType superType = current.supertype; |
| 169 if (superType != null) { |
| 170 queue.add(superType.element); |
| 171 } |
| 172 } |
| 173 // append interfaces |
| 174 for (InterfaceType intf in current.interfaces) { |
| 175 queue.add(intf.element); |
| 176 } |
| 177 } |
| 178 // we don't need "seed" itself |
| 179 result.remove(seed); |
| 180 return result; |
| 181 } |
| 182 |
| 183 |
| 184 typedef void ElementProcessor(Element element); |
| 185 |
| 186 /** |
| 187 * A [GeneralizingElementVisitor] adapter for [ElementProcessor]. |
| 188 */ |
| 189 class _ElementVisitorAdapter extends GeneralizingElementVisitor { |
| 190 final ElementProcessor processor; |
| 191 |
| 192 _ElementVisitorAdapter(this.processor); |
| 193 |
| 194 @override |
| 195 void visitElement(Element element) { |
| 196 processor(element); |
| 197 } |
| 198 } |
| OLD | NEW |