| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 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 | 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 | 4 |
| 5 library services.hierarchy; | 5 library services.hierarchy; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 | 9 |
| 10 import 'package:analysis_server/src/services/search/element_visitors.dart'; | 10 import 'package:analysis_server/src/services/search/element_visitors.dart'; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 } | 51 } |
| 52 return false; | 52 return false; |
| 53 }); | 53 }); |
| 54 return members; | 54 return members; |
| 55 } | 55 } |
| 56 | 56 |
| 57 /** | 57 /** |
| 58 * Returns a [Set] with direct subclasses of [seed]. | 58 * Returns a [Set] with direct subclasses of [seed]. |
| 59 */ | 59 */ |
| 60 Future<Set<ClassElement>> getDirectSubClasses( | 60 Future<Set<ClassElement>> getDirectSubClasses( |
| 61 SearchEngine searchEngine, ClassElement seed) { | 61 SearchEngine searchEngine, ClassElement seed) async { |
| 62 return searchEngine.searchSubtypes(seed).then((List<SearchMatch> matches) { | 62 List<SearchMatch> matches = await searchEngine.searchSubtypes(seed); |
| 63 Set<ClassElement> subClasses = new HashSet<ClassElement>(); | 63 return matches.map((match) => match.element).toSet(); |
| 64 for (SearchMatch match in matches) { | |
| 65 ClassElement subClass = match.element; | |
| 66 subClasses.add(subClass); | |
| 67 } | |
| 68 return subClasses; | |
| 69 }); | |
| 70 } | 64 } |
| 71 | 65 |
| 72 /** | 66 /** |
| 73 * @return all implementations of the given {@link ClassMemberElement} is its su
perclasses and | 67 * @return all implementations of the given {@link ClassMemberElement} is its su
perclasses and |
| 74 * their subclasses. | 68 * their subclasses. |
| 75 */ | 69 */ |
| 76 Future<Set<ClassMemberElement>> getHierarchyMembers( | 70 Future<Set<ClassMemberElement>> getHierarchyMembers( |
| 77 SearchEngine searchEngine, ClassMemberElement member) { | 71 SearchEngine searchEngine, ClassMemberElement member) async { |
| 78 Set<ClassMemberElement> result = new HashSet<ClassMemberElement>(); | 72 Set<ClassMemberElement> result = new HashSet<ClassMemberElement>(); |
| 79 // static elements | 73 // static elements |
| 80 if (member.isStatic || member is ConstructorElement) { | 74 if (member.isStatic || member is ConstructorElement) { |
| 81 result.add(member); | 75 result.add(member); |
| 82 return new Future.value(result); | 76 return new Future.value(result); |
| 83 } | 77 } |
| 84 // method, field, etc | 78 // method, field, etc |
| 85 String name = member.displayName; | 79 String name = member.displayName; |
| 86 ClassElement memberClass = member.enclosingElement; | 80 ClassElement memberClass = member.enclosingElement; |
| 87 List<Future> futures = <Future>[]; | |
| 88 Set<ClassElement> searchClasses = getSuperClasses(memberClass); | 81 Set<ClassElement> searchClasses = getSuperClasses(memberClass); |
| 89 searchClasses.add(memberClass); | 82 searchClasses.add(memberClass); |
| 90 for (ClassElement superClass in searchClasses) { | 83 for (ClassElement superClass in searchClasses) { |
| 91 // ignore if super- class does not declare member | 84 // ignore if super- class does not declare member |
| 92 if (getClassMembers(superClass, name).isEmpty) { | 85 if (getClassMembers(superClass, name).isEmpty) { |
| 93 continue; | 86 continue; |
| 94 } | 87 } |
| 95 // check all sub- classes | 88 // check all sub- classes |
| 96 var subClassFuture = getSubClasses(searchEngine, superClass); | 89 Set<ClassElement> subClasses = |
| 97 var membersFuture = subClassFuture.then((Set<ClassElement> subClasses) { | 90 await getSubClasses(searchEngine, superClass); |
| 98 subClasses.add(superClass); | 91 subClasses.add(superClass); |
| 99 for (ClassElement subClass in subClasses) { | 92 for (ClassElement subClass in subClasses) { |
| 100 List<Element> subClassMembers = getChildren(subClass, name); | 93 List<Element> subClassMembers = getChildren(subClass, name); |
| 101 for (Element member in subClassMembers) { | 94 for (Element member in subClassMembers) { |
| 102 if (member is ClassMemberElement) { | 95 if (member is ClassMemberElement) { |
| 103 result.add(member); | 96 result.add(member); |
| 104 } | |
| 105 } | 97 } |
| 106 } | 98 } |
| 107 }); | 99 } |
| 108 futures.add(membersFuture); | |
| 109 } | 100 } |
| 110 return Future.wait(futures).then((_) { | 101 return result; |
| 111 return result; | |
| 112 }); | |
| 113 } | 102 } |
| 114 | 103 |
| 115 /** | 104 /** |
| 116 * Returns non-synthetic members of the given [ClassElement] and its super | 105 * Returns non-synthetic members of the given [ClassElement] and its super |
| 117 * classes. | 106 * classes. |
| 118 * | 107 * |
| 119 * Includes: fields, accessors and methods. | 108 * Includes: fields, accessors and methods. |
| 120 * Excludes: constructors and synthetic elements. | 109 * Excludes: constructors and synthetic elements. |
| 121 */ | 110 */ |
| 122 List<Element> getMembers(ClassElement clazz) { | 111 List<Element> getMembers(ClassElement clazz) { |
| 123 List<Element> members = <Element>[]; | 112 List<Element> members = <Element>[]; |
| 124 members.addAll(getClassMembers(clazz)); | 113 members.addAll(getClassMembers(clazz)); |
| 125 Set<ClassElement> superClasses = getSuperClasses(clazz); | 114 Set<ClassElement> superClasses = getSuperClasses(clazz); |
| 126 for (ClassElement superClass in superClasses) { | 115 for (ClassElement superClass in superClasses) { |
| 127 members.addAll(getClassMembers(superClass)); | 116 members.addAll(getClassMembers(superClass)); |
| 128 } | 117 } |
| 129 return members; | 118 return members; |
| 130 } | 119 } |
| 131 | 120 |
| 132 /** | 121 /** |
| 133 * Returns a [Set] with all direct and indirect subclasses of [seed]. | 122 * Returns a [Set] with all direct and indirect subclasses of [seed]. |
| 134 */ | 123 */ |
| 135 Future<Set<ClassElement>> getSubClasses( | 124 Future<Set<ClassElement>> getSubClasses( |
| 136 SearchEngine searchEngine, ClassElement seed) { | 125 SearchEngine searchEngine, ClassElement seed) async { |
| 137 return searchEngine.searchAllSubtypes(seed).then((List<SearchMatch> matches) { | 126 List<SearchMatch> matches = await searchEngine.searchAllSubtypes(seed); |
| 138 Set<ClassElement> ancestors = new HashSet<ClassElement>(); | 127 return matches.map((match) => match.element).toSet(); |
| 139 for (SearchMatch match in matches) { | |
| 140 ClassElement ancestor = match.element; | |
| 141 ancestors.add(ancestor); | |
| 142 } | |
| 143 return ancestors; | |
| 144 }); | |
| 145 } | 128 } |
| 146 | 129 |
| 147 /** | 130 /** |
| 148 * Returns a [Set] with all direct and indirect superclasses of [seed]. | 131 * Returns a [Set] with all direct and indirect superclasses of [seed]. |
| 149 */ | 132 */ |
| 150 Set<ClassElement> getSuperClasses(ClassElement seed) { | 133 Set<ClassElement> getSuperClasses(ClassElement seed) { |
| 151 Set<ClassElement> result = new HashSet<ClassElement>(); | 134 Set<ClassElement> result = new HashSet<ClassElement>(); |
| 152 // prepare queue | 135 // prepare queue |
| 153 List<ClassElement> queue = new List<ClassElement>(); | 136 List<ClassElement> queue = new List<ClassElement>(); |
| 154 queue.add(seed); | 137 queue.add(seed); |
| 155 // process queue | 138 // process queue |
| 156 while (!queue.isEmpty) { | 139 while (!queue.isEmpty) { |
| 157 ClassElement current = queue.removeLast(); | 140 ClassElement current = queue.removeLast(); |
| 158 // add if not checked already | 141 // add if not checked already |
| 159 if (!result.add(current)) { | 142 if (!result.add(current)) { |
| 160 continue; | 143 continue; |
| 161 } | 144 } |
| 162 // append supertype | 145 // append supertype |
| 163 { | 146 { |
| 164 InterfaceType superType = current.supertype; | 147 InterfaceType superType = current.supertype; |
| 165 if (superType != null) { | 148 if (superType != null) { |
| 166 queue.add(superType.element); | 149 queue.add(superType.element); |
| 167 } | 150 } |
| 168 } | 151 } |
| 169 // append interfaces | 152 // append interfaces |
| 170 for (InterfaceType intf in current.interfaces) { | 153 for (InterfaceType interface in current.interfaces) { |
| 171 queue.add(intf.element); | 154 queue.add(interface.element); |
| 172 } | 155 } |
| 173 } | 156 } |
| 174 // we don't need "seed" itself | 157 // we don't need "seed" itself |
| 175 result.remove(seed); | 158 result.remove(seed); |
| 176 return result; | 159 return result; |
| 177 } | 160 } |
| 178 | 161 |
| 179 /** | 162 /** |
| 180 * If the given [element] is a synthetic [PropertyAccessorElement] returns | 163 * If the given [element] is a synthetic [PropertyAccessorElement] returns |
| 181 * its variable, otherwise returns [element]. | 164 * its variable, otherwise returns [element]. |
| 182 */ | 165 */ |
| 183 Element getSyntheticAccessorVariable(Element element) { | 166 Element getSyntheticAccessorVariable(Element element) { |
| 184 if (element is PropertyAccessorElement) { | 167 if (element is PropertyAccessorElement) { |
| 185 if (element.isSynthetic) { | 168 if (element.isSynthetic) { |
| 186 return element.variable; | 169 return element.variable; |
| 187 } | 170 } |
| 188 } | 171 } |
| 189 return element; | 172 return element; |
| 190 } | 173 } |
| OLD | NEW |