| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'dart:collection'; | 5 import 'dart:collection'; |
| 6 | 6 |
| 7 import 'package:analyzer/dart/ast/ast.dart'; | 7 import 'package:analyzer/dart/ast/ast.dart'; |
| 8 import 'package:analyzer/dart/ast/token.dart'; | 8 import 'package:analyzer/dart/ast/token.dart'; |
| 9 import 'package:analyzer/dart/element/element.dart'; | 9 import 'package:analyzer/dart/element/element.dart'; |
| 10 import 'package:analyzer/dart/element/type.dart'; | 10 import 'package:analyzer/dart/element/type.dart'; |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 * [ClassElement] superclass hierarchy, and the associated [Executable
Element] | 255 * [ClassElement] superclass hierarchy, and the associated [Executable
Element] |
| 256 */ | 256 */ |
| 257 Map<String, ExecutableElement> _computeClassChainLookupMap( | 257 Map<String, ExecutableElement> _computeClassChainLookupMap( |
| 258 ClassElement classElt, Set<ClassElement> visitedClasses) { | 258 ClassElement classElt, Set<ClassElement> visitedClasses) { |
| 259 Map<String, ExecutableElement> resultMap = _classLookup[classElt]; | 259 Map<String, ExecutableElement> resultMap = _classLookup[classElt]; |
| 260 if (resultMap != null) { | 260 if (resultMap != null) { |
| 261 return resultMap; | 261 return resultMap; |
| 262 } else { | 262 } else { |
| 263 resultMap = new Map<String, ExecutableElement>(); | 263 resultMap = new Map<String, ExecutableElement>(); |
| 264 } | 264 } |
| 265 ClassElement superclassElt = null; | |
| 266 InterfaceType supertype = classElt.supertype; | 265 InterfaceType supertype = classElt.supertype; |
| 267 if (supertype != null) { | 266 if (supertype == null) { |
| 268 superclassElt = supertype.element; | |
| 269 } else { | |
| 270 // classElt is Object | 267 // classElt is Object |
| 271 _classLookup[classElt] = resultMap; | 268 _classLookup[classElt] = resultMap; |
| 272 return resultMap; | 269 return resultMap; |
| 273 } | 270 } |
| 271 ClassElement superclassElt = supertype.element; |
| 274 if (superclassElt != null) { | 272 if (superclassElt != null) { |
| 275 if (!visitedClasses.contains(superclassElt)) { | 273 if (!visitedClasses.contains(superclassElt)) { |
| 276 visitedClasses.add(superclassElt); | 274 visitedClasses.add(superclassElt); |
| 277 try { | 275 try { |
| 278 resultMap = new Map<String, ExecutableElement>.from( | 276 resultMap = new Map<String, ExecutableElement>.from( |
| 279 _computeClassChainLookupMap(superclassElt, visitedClasses)); | 277 _computeClassChainLookupMap(superclassElt, visitedClasses)); |
| 280 // | 278 // |
| 281 // Substitute the super types down the hierarchy. | 279 // Substitute the super types down the hierarchy. |
| 282 // | 280 // |
| 283 _substituteTypeParametersDownHierarchy(supertype, resultMap); | 281 _substituteTypeParametersDownHierarchy(supertype, resultMap); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 302 // mixins will overwrite identically-named methods in earlier mixins. | 300 // mixins will overwrite identically-named methods in earlier mixins. |
| 303 // | 301 // |
| 304 List<InterfaceType> mixins = classElt.mixins; | 302 List<InterfaceType> mixins = classElt.mixins; |
| 305 for (InterfaceType mixin in mixins) { | 303 for (InterfaceType mixin in mixins) { |
| 306 ClassElement mixinElement = mixin.element; | 304 ClassElement mixinElement = mixin.element; |
| 307 if (mixinElement != null) { | 305 if (mixinElement != null) { |
| 308 if (!visitedClasses.contains(mixinElement)) { | 306 if (!visitedClasses.contains(mixinElement)) { |
| 309 visitedClasses.add(mixinElement); | 307 visitedClasses.add(mixinElement); |
| 310 try { | 308 try { |
| 311 Map<String, ExecutableElement> map = | 309 Map<String, ExecutableElement> map = |
| 312 new Map<String, ExecutableElement>.from( | 310 new Map<String, ExecutableElement>(); |
| 313 _computeClassChainLookupMap(mixinElement, visitedClasses)); | |
| 314 // | 311 // |
| 315 // Substitute the super types down the hierarchy. | 312 // Include the members from the mixin in the resultMap. |
| 316 // | |
| 317 _substituteTypeParametersDownHierarchy(mixin, map); | |
| 318 // | |
| 319 // Include the members from the superclass in the resultMap. | |
| 320 // | 313 // |
| 321 _recordMapWithClassMembers(map, mixin, false); | 314 _recordMapWithClassMembers(map, mixin, false); |
| 322 // | 315 // |
| 323 // Add the members from map into result map. | 316 // Add the members from map into result map. |
| 324 // | 317 // |
| 325 for (String memberName in map.keys) { | 318 for (String memberName in map.keys) { |
| 326 ExecutableElement value = map[memberName]; | 319 ExecutableElement value = map[memberName]; |
| 327 ClassElement definingClass = value | 320 ClassElement definingClass = value |
| 328 .getAncestor((Element element) => element is ClassElement); | 321 .getAncestor((Element element) => element is ClassElement); |
| 329 if (!definingClass.type.isObject) { | 322 if (!definingClass.type.isObject) { |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 * Record the passed map with the set of all members (methods, getters and set
ters) in the type | 594 * Record the passed map with the set of all members (methods, getters and set
ters) in the type |
| 602 * into the passed map. | 595 * into the passed map. |
| 603 * | 596 * |
| 604 * @param map some non-`null` map to put the methods and accessors from the pa
ssed | 597 * @param map some non-`null` map to put the methods and accessors from the pa
ssed |
| 605 * [ClassElement] into | 598 * [ClassElement] into |
| 606 * @param type the type that will be recorded into the passed map | 599 * @param type the type that will be recorded into the passed map |
| 607 * @param doIncludeAbstract `true` if abstract members will be put into the ma
p | 600 * @param doIncludeAbstract `true` if abstract members will be put into the ma
p |
| 608 */ | 601 */ |
| 609 void _recordMapWithClassMembers(Map<String, ExecutableElement> map, | 602 void _recordMapWithClassMembers(Map<String, ExecutableElement> map, |
| 610 InterfaceType type, bool doIncludeAbstract) { | 603 InterfaceType type, bool doIncludeAbstract) { |
| 604 Set<InterfaceType> seenTypes = new HashSet<InterfaceType>(); |
| 605 while (type.element.isMixinApplication) { |
| 606 List<InterfaceType> mixins = type.mixins; |
| 607 if (!seenTypes.add(type) || mixins.isEmpty) { |
| 608 // In the case of a circularity in the type hierarchy, just don't add |
| 609 // any members to the map. |
| 610 return; |
| 611 } |
| 612 type = mixins.last; |
| 613 } |
| 611 List<MethodElement> methods = type.methods; | 614 List<MethodElement> methods = type.methods; |
| 612 for (MethodElement method in methods) { | 615 for (MethodElement method in methods) { |
| 613 if (method.isAccessibleIn(_library) && | 616 if (method.isAccessibleIn(_library) && |
| 614 !method.isStatic && | 617 !method.isStatic && |
| 615 (doIncludeAbstract || !method.isAbstract)) { | 618 (doIncludeAbstract || !method.isAbstract)) { |
| 616 map[method.name] = method; | 619 map[method.name] = method; |
| 617 } | 620 } |
| 618 } | 621 } |
| 619 List<PropertyAccessorElement> accessors = type.accessors; | 622 List<PropertyAccessorElement> accessors = type.accessors; |
| 620 for (PropertyAccessorElement accessor in accessors) { | 623 for (PropertyAccessorElement accessor in accessors) { |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 843 * @param lookupMaps the maps to be unioned together. | 846 * @param lookupMaps the maps to be unioned together. |
| 844 * @return the resulting union map. | 847 * @return the resulting union map. |
| 845 */ | 848 */ |
| 846 HashMap<String, List<ExecutableElement>> _unionInterfaceLookupMaps( | 849 HashMap<String, List<ExecutableElement>> _unionInterfaceLookupMaps( |
| 847 List<Map<String, ExecutableElement>> lookupMaps) { | 850 List<Map<String, ExecutableElement>> lookupMaps) { |
| 848 HashMap<String, List<ExecutableElement>> unionMap = | 851 HashMap<String, List<ExecutableElement>> unionMap = |
| 849 new HashMap<String, List<ExecutableElement>>(); | 852 new HashMap<String, List<ExecutableElement>>(); |
| 850 for (Map<String, ExecutableElement> lookupMap in lookupMaps) { | 853 for (Map<String, ExecutableElement> lookupMap in lookupMaps) { |
| 851 for (String memberName in lookupMap.keys) { | 854 for (String memberName in lookupMap.keys) { |
| 852 // Get the list value out of the unionMap | 855 // Get the list value out of the unionMap |
| 853 List<ExecutableElement> list = unionMap[memberName]; | 856 List<ExecutableElement> list = unionMap.putIfAbsent( |
| 854 // If we haven't created such a map for this key yet, do create it and | 857 memberName, () => new List<ExecutableElement>()); |
| 855 // put the list entry into the unionMap. | |
| 856 if (list == null) { | |
| 857 list = new List<ExecutableElement>(); | |
| 858 unionMap[memberName] = list; | |
| 859 } | |
| 860 // Fetch the entry out of this lookupMap | 858 // Fetch the entry out of this lookupMap |
| 861 ExecutableElement newExecutableElementEntry = lookupMap[memberName]; | 859 ExecutableElement newExecutableElementEntry = lookupMap[memberName]; |
| 862 if (list.isEmpty) { | 860 if (list.isEmpty) { |
| 863 // If the list is empty, just the new value | 861 // If the list is empty, just the new value |
| 864 list.add(newExecutableElementEntry); | 862 list.add(newExecutableElementEntry); |
| 865 } else { | 863 } else { |
| 866 // Otherwise, only add the newExecutableElementEntry if it isn't | 864 // Otherwise, only add the newExecutableElementEntry if it isn't |
| 867 // already in the list, this covers situation where a class inherits | 865 // already in the list, this covers situation where a class inherits |
| 868 // two methods (or two getters) that are identical. | 866 // two methods (or two getters) that are identical. |
| 869 bool alreadyInList = false; | 867 bool alreadyInList = false; |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1229 } | 1227 } |
| 1230 | 1228 |
| 1231 /** | 1229 /** |
| 1232 * Initializes [keys] and [values]. | 1230 * Initializes [keys] and [values]. |
| 1233 */ | 1231 */ |
| 1234 void _initArrays(int initialCapacity) { | 1232 void _initArrays(int initialCapacity) { |
| 1235 _keys = new List<String>(initialCapacity); | 1233 _keys = new List<String>(initialCapacity); |
| 1236 _values = new List<ExecutableElement>(initialCapacity); | 1234 _values = new List<ExecutableElement>(initialCapacity); |
| 1237 } | 1235 } |
| 1238 } | 1236 } |
| OLD | NEW |