| 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 analyzer.src.generated.resolver; | 5 library analyzer.src.generated.resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
| (...skipping 4825 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4836 class InheritanceManager { | 4836 class InheritanceManager { |
| 4837 /** | 4837 /** |
| 4838 * The [LibraryElement] that is managed by this manager. | 4838 * The [LibraryElement] that is managed by this manager. |
| 4839 */ | 4839 */ |
| 4840 LibraryElement _library; | 4840 LibraryElement _library; |
| 4841 | 4841 |
| 4842 /** | 4842 /** |
| 4843 * This is a mapping between each [ClassElement] and a map between the [String
] member | 4843 * This is a mapping between each [ClassElement] and a map between the [String
] member |
| 4844 * names and the associated [ExecutableElement] in the mixin and superclass ch
ain. | 4844 * names and the associated [ExecutableElement] in the mixin and superclass ch
ain. |
| 4845 */ | 4845 */ |
| 4846 HashMap<ClassElement, MemberMap> _classLookup; | 4846 Map<ClassElement, Map<String, ExecutableElement>> _classLookup; |
| 4847 | 4847 |
| 4848 /** | 4848 /** |
| 4849 * This is a mapping between each [ClassElement] and a map between the [String
] member | 4849 * This is a mapping between each [ClassElement] and a map between the [String
] member |
| 4850 * names and the associated [ExecutableElement] in the interface set. | 4850 * names and the associated [ExecutableElement] in the interface set. |
| 4851 */ | 4851 */ |
| 4852 HashMap<ClassElement, MemberMap> _interfaceLookup; | 4852 Map<ClassElement, Map<String, ExecutableElement>> _interfaceLookup; |
| 4853 | 4853 |
| 4854 /** | 4854 /** |
| 4855 * A map between each visited [ClassElement] and the set of [AnalysisError]s f
ound on | 4855 * A map between each visited [ClassElement] and the set of [AnalysisError]s f
ound on |
| 4856 * the class element. | 4856 * the class element. |
| 4857 */ | 4857 */ |
| 4858 HashMap<ClassElement, HashSet<AnalysisError>> _errorsInClassElement = | 4858 Map<ClassElement, Set<AnalysisError>> _errorsInClassElement = |
| 4859 new HashMap<ClassElement, HashSet<AnalysisError>>(); | 4859 new HashMap<ClassElement, Set<AnalysisError>>(); |
| 4860 | 4860 |
| 4861 /** | 4861 /** |
| 4862 * Initialize a newly created inheritance manager. | 4862 * Initialize a newly created inheritance manager. |
| 4863 * | 4863 * |
| 4864 * @param library the library element context that the inheritance mappings ar
e being generated | 4864 * @param library the library element context that the inheritance mappings ar
e being generated |
| 4865 */ | 4865 */ |
| 4866 InheritanceManager(LibraryElement library) { | 4866 InheritanceManager(LibraryElement library) { |
| 4867 this._library = library; | 4867 this._library = library; |
| 4868 _classLookup = new HashMap<ClassElement, MemberMap>(); | 4868 _classLookup = new HashMap<ClassElement, Map<String, ExecutableElement>>(); |
| 4869 _interfaceLookup = new HashMap<ClassElement, MemberMap>(); | 4869 _interfaceLookup = |
| 4870 new HashMap<ClassElement, Map<String, ExecutableElement>>(); |
| 4870 } | 4871 } |
| 4871 | 4872 |
| 4872 /** | 4873 /** |
| 4873 * Set the new library element context. | 4874 * Set the new library element context. |
| 4874 * | 4875 * |
| 4875 * @param library the new library element | 4876 * @param library the new library element |
| 4876 */ | 4877 */ |
| 4877 void set libraryElement(LibraryElement library) { | 4878 void set libraryElement(LibraryElement library) { |
| 4878 this._library = library; | 4879 this._library = library; |
| 4879 } | 4880 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4890 _errorsInClassElement[classElt]; | 4891 _errorsInClassElement[classElt]; |
| 4891 | 4892 |
| 4892 /** | 4893 /** |
| 4893 * Get and return a mapping between the set of all string names of the members
inherited from the | 4894 * Get and return a mapping between the set of all string names of the members
inherited from the |
| 4894 * passed [ClassElement] superclass hierarchy, and the associated [ExecutableE
lement]. | 4895 * passed [ClassElement] superclass hierarchy, and the associated [ExecutableE
lement]. |
| 4895 * | 4896 * |
| 4896 * @param classElt the class element to query | 4897 * @param classElt the class element to query |
| 4897 * @return a mapping between the set of all members inherited from the passed
[ClassElement] | 4898 * @return a mapping between the set of all members inherited from the passed
[ClassElement] |
| 4898 * superclass hierarchy, and the associated [ExecutableElement] | 4899 * superclass hierarchy, and the associated [ExecutableElement] |
| 4899 */ | 4900 */ |
| 4900 MemberMap getMapOfMembersInheritedFromClasses(ClassElement classElt) => | 4901 Map<String, ExecutableElement> getMapOfMembersInheritedFromClasses( |
| 4902 ClassElement classElt) => |
| 4901 _computeClassChainLookupMap(classElt, new HashSet<ClassElement>()); | 4903 _computeClassChainLookupMap(classElt, new HashSet<ClassElement>()); |
| 4902 | 4904 |
| 4903 /** | 4905 /** |
| 4904 * Get and return a mapping between the set of all string names of the members
inherited from the | 4906 * Get and return a mapping between the set of all string names of the members
inherited from the |
| 4905 * passed [ClassElement] interface hierarchy, and the associated [ExecutableEl
ement]. | 4907 * passed [ClassElement] interface hierarchy, and the associated [ExecutableEl
ement]. |
| 4906 * | 4908 * |
| 4907 * @param classElt the class element to query | 4909 * @param classElt the class element to query |
| 4908 * @return a mapping between the set of all string names of the members inheri
ted from the passed | 4910 * @return a mapping between the set of all string names of the members inheri
ted from the passed |
| 4909 * [ClassElement] interface hierarchy, and the associated [ExecutableE
lement]. | 4911 * [ClassElement] interface hierarchy, and the associated [ExecutableE
lement]. |
| 4910 */ | 4912 */ |
| 4911 MemberMap getMapOfMembersInheritedFromInterfaces(ClassElement classElt) => | 4913 Map<String, ExecutableElement> getMapOfMembersInheritedFromInterfaces( |
| 4914 ClassElement classElt) => |
| 4912 _computeInterfaceLookupMap(classElt, new HashSet<ClassElement>()); | 4915 _computeInterfaceLookupMap(classElt, new HashSet<ClassElement>()); |
| 4913 | 4916 |
| 4914 /** | 4917 /** |
| 4915 * Given some [ClassElement] and some member name, this returns the | 4918 * Given some [ClassElement] and some member name, this returns the |
| 4916 * [ExecutableElement] that the class inherits from the mixins, | 4919 * [ExecutableElement] that the class inherits from the mixins, |
| 4917 * superclasses or interfaces, that has the member name, if no member is inher
ited `null` is | 4920 * superclasses or interfaces, that has the member name, if no member is inher
ited `null` is |
| 4918 * returned. | 4921 * returned. |
| 4919 * | 4922 * |
| 4920 * @param classElt the class element to query | 4923 * @param classElt the class element to query |
| 4921 * @param memberName the name of the executable element to find and return | 4924 * @param memberName the name of the executable element to find and return |
| 4922 * @return the inherited executable element with the member name, or `null` if
no such | 4925 * @return the inherited executable element with the member name, or `null` if
no such |
| 4923 * member exists | 4926 * member exists |
| 4924 */ | 4927 */ |
| 4925 ExecutableElement lookupInheritance( | 4928 ExecutableElement lookupInheritance( |
| 4926 ClassElement classElt, String memberName) { | 4929 ClassElement classElt, String memberName) { |
| 4927 if (memberName == null || memberName.isEmpty) { | 4930 if (memberName == null || memberName.isEmpty) { |
| 4928 return null; | 4931 return null; |
| 4929 } | 4932 } |
| 4930 ExecutableElement executable = | 4933 ExecutableElement executable = _computeClassChainLookupMap( |
| 4931 _computeClassChainLookupMap(classElt, new HashSet<ClassElement>()) | 4934 classElt, new HashSet<ClassElement>())[memberName]; |
| 4932 .get(memberName); | |
| 4933 if (executable == null) { | 4935 if (executable == null) { |
| 4934 return _computeInterfaceLookupMap(classElt, new HashSet<ClassElement>()) | 4936 return _computeInterfaceLookupMap(classElt, new HashSet<ClassElement>())[ |
| 4935 .get(memberName); | 4937 memberName]; |
| 4936 } | 4938 } |
| 4937 return executable; | 4939 return executable; |
| 4938 } | 4940 } |
| 4939 | 4941 |
| 4940 /** | 4942 /** |
| 4941 * Given some [ClassElement] and some member name, this returns the | 4943 * Given some [ClassElement] and some member name, this returns the |
| 4942 * [ExecutableElement] that the class either declares itself, or | 4944 * [ExecutableElement] that the class either declares itself, or |
| 4943 * inherits, that has the member name, if no member is inherited `null` is ret
urned. | 4945 * inherits, that has the member name, if no member is inherited `null` is ret
urned. |
| 4944 * | 4946 * |
| 4945 * @param classElt the class element to query | 4947 * @param classElt the class element to query |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4964 * @param classElt the class to query | 4966 * @param classElt the class to query |
| 4965 * @param memberName the name of the class member to query | 4967 * @param memberName the name of the class member to query |
| 4966 * @return a list of overridden methods | 4968 * @return a list of overridden methods |
| 4967 */ | 4969 */ |
| 4968 List<ExecutableElement> lookupOverrides( | 4970 List<ExecutableElement> lookupOverrides( |
| 4969 ClassElement classElt, String memberName) { | 4971 ClassElement classElt, String memberName) { |
| 4970 List<ExecutableElement> result = new List<ExecutableElement>(); | 4972 List<ExecutableElement> result = new List<ExecutableElement>(); |
| 4971 if (memberName == null || memberName.isEmpty) { | 4973 if (memberName == null || memberName.isEmpty) { |
| 4972 return result; | 4974 return result; |
| 4973 } | 4975 } |
| 4974 List<MemberMap> interfaceMaps = | 4976 List<Map<String, ExecutableElement>> interfaceMaps = |
| 4975 _gatherInterfaceLookupMaps(classElt, new HashSet<ClassElement>()); | 4977 _gatherInterfaceLookupMaps(classElt, new HashSet<ClassElement>()); |
| 4976 if (interfaceMaps != null) { | 4978 if (interfaceMaps != null) { |
| 4977 for (MemberMap interfaceMap in interfaceMaps) { | 4979 for (Map<String, ExecutableElement> interfaceMap in interfaceMaps) { |
| 4978 ExecutableElement overriddenElement = interfaceMap.get(memberName); | 4980 ExecutableElement overriddenElement = interfaceMap[memberName]; |
| 4979 if (overriddenElement != null) { | 4981 if (overriddenElement != null) { |
| 4980 if (overriddenElement is MultiplyInheritedExecutableElement) { | 4982 if (overriddenElement is MultiplyInheritedExecutableElement) { |
| 4981 MultiplyInheritedExecutableElement multiplyInheritedElement = | 4983 MultiplyInheritedExecutableElement multiplyInheritedElement = |
| 4982 overriddenElement; | 4984 overriddenElement; |
| 4983 for (ExecutableElement element | 4985 for (ExecutableElement element |
| 4984 in multiplyInheritedElement.inheritedElements) { | 4986 in multiplyInheritedElement.inheritedElements) { |
| 4985 result.add(element); | 4987 result.add(element); |
| 4986 } | 4988 } |
| 4987 } else { | 4989 } else { |
| 4988 result.add(overriddenElement); | 4990 result.add(overriddenElement); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5039 * Compute and return a mapping between the set of all string names of the mem
bers inherited from | 5041 * Compute and return a mapping between the set of all string names of the mem
bers inherited from |
| 5040 * the passed [ClassElement] superclass hierarchy, and the associated | 5042 * the passed [ClassElement] superclass hierarchy, and the associated |
| 5041 * [ExecutableElement]. | 5043 * [ExecutableElement]. |
| 5042 * | 5044 * |
| 5043 * @param classElt the class element to query | 5045 * @param classElt the class element to query |
| 5044 * @param visitedClasses a set of visited classes passed back into this method
when it calls | 5046 * @param visitedClasses a set of visited classes passed back into this method
when it calls |
| 5045 * itself recursively | 5047 * itself recursively |
| 5046 * @return a mapping between the set of all string names of the members inheri
ted from the passed | 5048 * @return a mapping between the set of all string names of the members inheri
ted from the passed |
| 5047 * [ClassElement] superclass hierarchy, and the associated [Executable
Element] | 5049 * [ClassElement] superclass hierarchy, and the associated [Executable
Element] |
| 5048 */ | 5050 */ |
| 5049 MemberMap _computeClassChainLookupMap( | 5051 Map<String, ExecutableElement> _computeClassChainLookupMap( |
| 5050 ClassElement classElt, HashSet<ClassElement> visitedClasses) { | 5052 ClassElement classElt, HashSet<ClassElement> visitedClasses) { |
| 5051 MemberMap resultMap = _classLookup[classElt]; | 5053 Map<String, ExecutableElement> resultMap = _classLookup[classElt]; |
| 5052 if (resultMap != null) { | 5054 if (resultMap != null) { |
| 5053 return resultMap; | 5055 return resultMap; |
| 5054 } else { | 5056 } else { |
| 5055 resultMap = new MemberMap(); | 5057 resultMap = new HashMap<String, ExecutableElement>(); |
| 5056 } | 5058 } |
| 5057 ClassElement superclassElt = null; | 5059 ClassElement superclassElt = null; |
| 5058 InterfaceType supertype = classElt.supertype; | 5060 InterfaceType supertype = classElt.supertype; |
| 5059 if (supertype != null) { | 5061 if (supertype != null) { |
| 5060 superclassElt = supertype.element; | 5062 superclassElt = supertype.element; |
| 5061 } else { | 5063 } else { |
| 5062 // classElt is Object | 5064 // classElt is Object |
| 5063 _classLookup[classElt] = resultMap; | 5065 _classLookup[classElt] = resultMap; |
| 5064 return resultMap; | 5066 return resultMap; |
| 5065 } | 5067 } |
| 5066 if (superclassElt != null) { | 5068 if (superclassElt != null) { |
| 5067 if (!visitedClasses.contains(superclassElt)) { | 5069 if (!visitedClasses.contains(superclassElt)) { |
| 5068 visitedClasses.add(superclassElt); | 5070 visitedClasses.add(superclassElt); |
| 5069 try { | 5071 try { |
| 5070 resultMap = new MemberMap.from( | 5072 resultMap = new HashMap<String, ExecutableElement>.from( |
| 5071 _computeClassChainLookupMap(superclassElt, visitedClasses)); | 5073 _computeClassChainLookupMap(superclassElt, visitedClasses)); |
| 5072 // | 5074 // |
| 5073 // Substitute the super types down the hierarchy. | 5075 // Substitute the super types down the hierarchy. |
| 5074 // | 5076 // |
| 5075 _substituteTypeParametersDownHierarchy(supertype, resultMap); | 5077 _substituteTypeParametersDownHierarchy(supertype, resultMap); |
| 5076 // | 5078 // |
| 5077 // Include the members from the superclass in the resultMap. | 5079 // Include the members from the superclass in the resultMap. |
| 5078 // | 5080 // |
| 5079 _recordMapWithClassMembers(resultMap, supertype, false); | 5081 _recordMapWithClassMembers(resultMap, supertype, false); |
| 5080 } finally { | 5082 } finally { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5093 // multiple mixins, visit them in the order listed so that methods in later | 5095 // multiple mixins, visit them in the order listed so that methods in later |
| 5094 // mixins will overwrite identically-named methods in earlier mixins. | 5096 // mixins will overwrite identically-named methods in earlier mixins. |
| 5095 // | 5097 // |
| 5096 List<InterfaceType> mixins = classElt.mixins; | 5098 List<InterfaceType> mixins = classElt.mixins; |
| 5097 for (InterfaceType mixin in mixins) { | 5099 for (InterfaceType mixin in mixins) { |
| 5098 ClassElement mixinElement = mixin.element; | 5100 ClassElement mixinElement = mixin.element; |
| 5099 if (mixinElement != null) { | 5101 if (mixinElement != null) { |
| 5100 if (!visitedClasses.contains(mixinElement)) { | 5102 if (!visitedClasses.contains(mixinElement)) { |
| 5101 visitedClasses.add(mixinElement); | 5103 visitedClasses.add(mixinElement); |
| 5102 try { | 5104 try { |
| 5103 MemberMap map = new MemberMap.from( | 5105 Map<String, ExecutableElement> map = |
| 5104 _computeClassChainLookupMap(mixinElement, visitedClasses)); | 5106 new HashMap<String, ExecutableElement>.from( |
| 5107 _computeClassChainLookupMap(mixinElement, visitedClasses)); |
| 5105 // | 5108 // |
| 5106 // Substitute the super types down the hierarchy. | 5109 // Substitute the super types down the hierarchy. |
| 5107 // | 5110 // |
| 5108 _substituteTypeParametersDownHierarchy(mixin, map); | 5111 _substituteTypeParametersDownHierarchy(mixin, map); |
| 5109 // | 5112 // |
| 5110 // Include the members from the superclass in the resultMap. | 5113 // Include the members from the superclass in the resultMap. |
| 5111 // | 5114 // |
| 5112 _recordMapWithClassMembers(map, mixin, false); | 5115 _recordMapWithClassMembers(map, mixin, false); |
| 5113 // | 5116 // |
| 5114 // Add the members from map into result map. | 5117 // Add the members from map into result map. |
| 5115 // | 5118 // |
| 5116 for (int j = 0; j < map.size; j++) { | 5119 for (String memberName in map.keys) { |
| 5117 String key = map.getKey(j); | 5120 ExecutableElement value = map[memberName]; |
| 5118 ExecutableElement value = map.getValue(j); | 5121 ClassElement definingClass = value |
| 5119 if (key != null) { | 5122 .getAncestor((Element element) => element is ClassElement); |
| 5120 ClassElement definingClass = value | 5123 if (!definingClass.type.isObject) { |
| 5121 .getAncestor((Element element) => element is ClassElement); | 5124 ExecutableElement existingValue = resultMap[memberName]; |
| 5122 if (!definingClass.type.isObject) { | 5125 if (existingValue == null || |
| 5123 ExecutableElement existingValue = resultMap.get(key); | 5126 (existingValue != null && !_isAbstract(value))) { |
| 5124 if (existingValue == null || | 5127 resultMap[memberName] = value; |
| 5125 (existingValue != null && !_isAbstract(value))) { | |
| 5126 resultMap.put(key, value); | |
| 5127 } | |
| 5128 } | 5128 } |
| 5129 } | 5129 } |
| 5130 } | 5130 } |
| 5131 } finally { | 5131 } finally { |
| 5132 visitedClasses.remove(mixinElement); | 5132 visitedClasses.remove(mixinElement); |
| 5133 } | 5133 } |
| 5134 } else { | 5134 } else { |
| 5135 // This case happens only when the superclass was previously visited | 5135 // This case happens only when the superclass was previously visited |
| 5136 // and not in the lookup, meaning this is meant to shorten the compute | 5136 // and not in the lookup, meaning this is meant to shorten the compute |
| 5137 // for recursive cases. | 5137 // for recursive cases. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5212 * Compute and return a mapping between the set of all string names of the mem
bers inherited from | 5212 * Compute and return a mapping between the set of all string names of the mem
bers inherited from |
| 5213 * the passed [ClassElement] interface hierarchy, and the associated | 5213 * the passed [ClassElement] interface hierarchy, and the associated |
| 5214 * [ExecutableElement]. | 5214 * [ExecutableElement]. |
| 5215 * | 5215 * |
| 5216 * @param classElt the class element to query | 5216 * @param classElt the class element to query |
| 5217 * @param visitedInterfaces a set of visited classes passed back into this met
hod when it calls | 5217 * @param visitedInterfaces a set of visited classes passed back into this met
hod when it calls |
| 5218 * itself recursively | 5218 * itself recursively |
| 5219 * @return a mapping between the set of all string names of the members inheri
ted from the passed | 5219 * @return a mapping between the set of all string names of the members inheri
ted from the passed |
| 5220 * [ClassElement] interface hierarchy, and the associated [ExecutableE
lement] | 5220 * [ClassElement] interface hierarchy, and the associated [ExecutableE
lement] |
| 5221 */ | 5221 */ |
| 5222 MemberMap _computeInterfaceLookupMap( | 5222 Map<String, ExecutableElement> _computeInterfaceLookupMap( |
| 5223 ClassElement classElt, HashSet<ClassElement> visitedInterfaces) { | 5223 ClassElement classElt, HashSet<ClassElement> visitedInterfaces) { |
| 5224 MemberMap resultMap = _interfaceLookup[classElt]; | 5224 Map<String, ExecutableElement> resultMap = _interfaceLookup[classElt]; |
| 5225 if (resultMap != null) { | 5225 if (resultMap != null) { |
| 5226 return resultMap; | 5226 return resultMap; |
| 5227 } | 5227 } |
| 5228 List<MemberMap> lookupMaps = | 5228 List<Map<String, ExecutableElement>> lookupMaps = |
| 5229 _gatherInterfaceLookupMaps(classElt, visitedInterfaces); | 5229 _gatherInterfaceLookupMaps(classElt, visitedInterfaces); |
| 5230 if (lookupMaps == null) { | 5230 if (lookupMaps == null) { |
| 5231 resultMap = new MemberMap(); | 5231 resultMap = new HashMap<String, ExecutableElement>(); |
| 5232 } else { | 5232 } else { |
| 5233 HashMap<String, List<ExecutableElement>> unionMap = | 5233 Map<String, List<ExecutableElement>> unionMap = |
| 5234 _unionInterfaceLookupMaps(lookupMaps); | 5234 _unionInterfaceLookupMaps(lookupMaps); |
| 5235 resultMap = _resolveInheritanceLookup(classElt, unionMap); | 5235 resultMap = _resolveInheritanceLookup(classElt, unionMap); |
| 5236 } | 5236 } |
| 5237 _interfaceLookup[classElt] = resultMap; | 5237 _interfaceLookup[classElt] = resultMap; |
| 5238 return resultMap; | 5238 return resultMap; |
| 5239 } | 5239 } |
| 5240 | 5240 |
| 5241 /** | 5241 /** |
| 5242 * Collect a list of interface lookup maps whose elements correspond to all of
the classes | 5242 * Collect a list of interface lookup maps whose elements correspond to all of
the classes |
| 5243 * directly above [classElt] in the class hierarchy (the direct superclass if
any, all | 5243 * directly above [classElt] in the class hierarchy (the direct superclass if
any, all |
| 5244 * mixins, and all direct superinterfaces). Each item in the list is the inter
face lookup map | 5244 * mixins, and all direct superinterfaces). Each item in the list is the inter
face lookup map |
| 5245 * returned by [computeInterfaceLookupMap] for the corresponding super, except
with type | 5245 * returned by [computeInterfaceLookupMap] for the corresponding super, except
with type |
| 5246 * parameters appropriately substituted. | 5246 * parameters appropriately substituted. |
| 5247 * | 5247 * |
| 5248 * @param classElt the class element to query | 5248 * @param classElt the class element to query |
| 5249 * @param visitedInterfaces a set of visited classes passed back into this met
hod when it calls | 5249 * @param visitedInterfaces a set of visited classes passed back into this met
hod when it calls |
| 5250 * itself recursively | 5250 * itself recursively |
| 5251 * @return `null` if there was a problem (such as a loop in the class hierarch
y) or if there | 5251 * @return `null` if there was a problem (such as a loop in the class hierarch
y) or if there |
| 5252 * are no classes above this one in the class hierarchy. Otherwise, a
list of interface | 5252 * are no classes above this one in the class hierarchy. Otherwise, a
list of interface |
| 5253 * lookup maps. | 5253 * lookup maps. |
| 5254 */ | 5254 */ |
| 5255 List<MemberMap> _gatherInterfaceLookupMaps( | 5255 List<Map<String, ExecutableElement>> _gatherInterfaceLookupMaps( |
| 5256 ClassElement classElt, HashSet<ClassElement> visitedInterfaces) { | 5256 ClassElement classElt, HashSet<ClassElement> visitedInterfaces) { |
| 5257 InterfaceType supertype = classElt.supertype; | 5257 InterfaceType supertype = classElt.supertype; |
| 5258 ClassElement superclassElement = | 5258 ClassElement superclassElement = |
| 5259 supertype != null ? supertype.element : null; | 5259 supertype != null ? supertype.element : null; |
| 5260 List<InterfaceType> mixins = classElt.mixins; | 5260 List<InterfaceType> mixins = classElt.mixins; |
| 5261 List<InterfaceType> interfaces = classElt.interfaces; | 5261 List<InterfaceType> interfaces = classElt.interfaces; |
| 5262 // Recursively collect the list of mappings from all of the interface types | 5262 // Recursively collect the list of mappings from all of the interface types |
| 5263 List<MemberMap> lookupMaps = new List<MemberMap>(); | 5263 List<Map<String, ExecutableElement>> lookupMaps = |
| 5264 new List<Map<String, ExecutableElement>>(); |
| 5264 // | 5265 // |
| 5265 // Superclass element | 5266 // Superclass element |
| 5266 // | 5267 // |
| 5267 if (superclassElement != null) { | 5268 if (superclassElement != null) { |
| 5268 if (!visitedInterfaces.contains(superclassElement)) { | 5269 if (!visitedInterfaces.contains(superclassElement)) { |
| 5269 try { | 5270 try { |
| 5270 visitedInterfaces.add(superclassElement); | 5271 visitedInterfaces.add(superclassElement); |
| 5271 // | 5272 // |
| 5272 // Recursively compute the map for the super type. | 5273 // Recursively compute the map for the super type. |
| 5273 // | 5274 // |
| 5274 MemberMap map = | 5275 Map<String, ExecutableElement> map = |
| 5275 _computeInterfaceLookupMap(superclassElement, visitedInterfaces); | 5276 _computeInterfaceLookupMap(superclassElement, visitedInterfaces); |
| 5276 map = new MemberMap.from(map); | 5277 map = new HashMap<String, ExecutableElement>.from(map); |
| 5277 // | 5278 // |
| 5278 // Substitute the super type down the hierarchy. | 5279 // Substitute the super type down the hierarchy. |
| 5279 // | 5280 // |
| 5280 _substituteTypeParametersDownHierarchy(supertype, map); | 5281 _substituteTypeParametersDownHierarchy(supertype, map); |
| 5281 // | 5282 // |
| 5282 // Add any members from the super type into the map as well. | 5283 // Add any members from the super type into the map as well. |
| 5283 // | 5284 // |
| 5284 _recordMapWithClassMembers(map, supertype, true); | 5285 _recordMapWithClassMembers(map, supertype, true); |
| 5285 lookupMaps.add(map); | 5286 lookupMaps.add(map); |
| 5286 } finally { | 5287 } finally { |
| 5287 visitedInterfaces.remove(superclassElement); | 5288 visitedInterfaces.remove(superclassElement); |
| 5288 } | 5289 } |
| 5289 } else { | 5290 } else { |
| 5290 return null; | 5291 return null; |
| 5291 } | 5292 } |
| 5292 } | 5293 } |
| 5293 // | 5294 // |
| 5294 // Mixin elements | 5295 // Mixin elements |
| 5295 // | 5296 // |
| 5296 for (int i = mixins.length - 1; i >= 0; i--) { | 5297 for (int i = mixins.length - 1; i >= 0; i--) { |
| 5297 InterfaceType mixinType = mixins[i]; | 5298 InterfaceType mixinType = mixins[i]; |
| 5298 ClassElement mixinElement = mixinType.element; | 5299 ClassElement mixinElement = mixinType.element; |
| 5299 if (mixinElement != null) { | 5300 if (mixinElement != null) { |
| 5300 if (!visitedInterfaces.contains(mixinElement)) { | 5301 if (!visitedInterfaces.contains(mixinElement)) { |
| 5301 try { | 5302 try { |
| 5302 visitedInterfaces.add(mixinElement); | 5303 visitedInterfaces.add(mixinElement); |
| 5303 // | 5304 // |
| 5304 // Recursively compute the map for the mixin. | 5305 // Recursively compute the map for the mixin. |
| 5305 // | 5306 // |
| 5306 MemberMap map = | 5307 Map<String, ExecutableElement> map = |
| 5307 _computeInterfaceLookupMap(mixinElement, visitedInterfaces); | 5308 _computeInterfaceLookupMap(mixinElement, visitedInterfaces); |
| 5308 map = new MemberMap.from(map); | 5309 map = new HashMap<String, ExecutableElement>.from(map); |
| 5309 // | 5310 // |
| 5310 // Substitute the mixin type down the hierarchy. | 5311 // Substitute the mixin type down the hierarchy. |
| 5311 // | 5312 // |
| 5312 _substituteTypeParametersDownHierarchy(mixinType, map); | 5313 _substituteTypeParametersDownHierarchy(mixinType, map); |
| 5313 // | 5314 // |
| 5314 // Add any members from the mixin type into the map as well. | 5315 // Add any members from the mixin type into the map as well. |
| 5315 // | 5316 // |
| 5316 _recordMapWithClassMembers(map, mixinType, true); | 5317 _recordMapWithClassMembers(map, mixinType, true); |
| 5317 lookupMaps.add(map); | 5318 lookupMaps.add(map); |
| 5318 } finally { | 5319 } finally { |
| 5319 visitedInterfaces.remove(mixinElement); | 5320 visitedInterfaces.remove(mixinElement); |
| 5320 } | 5321 } |
| 5321 } else { | 5322 } else { |
| 5322 return null; | 5323 return null; |
| 5323 } | 5324 } |
| 5324 } | 5325 } |
| 5325 } | 5326 } |
| 5326 // | 5327 // |
| 5327 // Interface elements | 5328 // Interface elements |
| 5328 // | 5329 // |
| 5329 for (InterfaceType interfaceType in interfaces) { | 5330 for (InterfaceType interfaceType in interfaces) { |
| 5330 ClassElement interfaceElement = interfaceType.element; | 5331 ClassElement interfaceElement = interfaceType.element; |
| 5331 if (interfaceElement != null) { | 5332 if (interfaceElement != null) { |
| 5332 if (!visitedInterfaces.contains(interfaceElement)) { | 5333 if (!visitedInterfaces.contains(interfaceElement)) { |
| 5333 try { | 5334 try { |
| 5334 visitedInterfaces.add(interfaceElement); | 5335 visitedInterfaces.add(interfaceElement); |
| 5335 // | 5336 // |
| 5336 // Recursively compute the map for the interfaces. | 5337 // Recursively compute the map for the interfaces. |
| 5337 // | 5338 // |
| 5338 MemberMap map = | 5339 Map<String, ExecutableElement> map = |
| 5339 _computeInterfaceLookupMap(interfaceElement, visitedInterfaces); | 5340 _computeInterfaceLookupMap(interfaceElement, visitedInterfaces); |
| 5340 map = new MemberMap.from(map); | 5341 map = new HashMap<String, ExecutableElement>.from(map); |
| 5341 // | 5342 // |
| 5342 // Substitute the supertypes down the hierarchy | 5343 // Substitute the supertypes down the hierarchy |
| 5343 // | 5344 // |
| 5344 _substituteTypeParametersDownHierarchy(interfaceType, map); | 5345 _substituteTypeParametersDownHierarchy(interfaceType, map); |
| 5345 // | 5346 // |
| 5346 // And add any members from the interface into the map as well. | 5347 // And add any members from the interface into the map as well. |
| 5347 // | 5348 // |
| 5348 _recordMapWithClassMembers(map, interfaceType, true); | 5349 _recordMapWithClassMembers(map, interfaceType, true); |
| 5349 lookupMaps.add(map); | 5350 lookupMaps.add(map); |
| 5350 } finally { | 5351 } finally { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5393 | 5394 |
| 5394 /** | 5395 /** |
| 5395 * Record the passed map with the set of all members (methods, getters and set
ters) in the type | 5396 * Record the passed map with the set of all members (methods, getters and set
ters) in the type |
| 5396 * into the passed map. | 5397 * into the passed map. |
| 5397 * | 5398 * |
| 5398 * @param map some non-`null` map to put the methods and accessors from the pa
ssed | 5399 * @param map some non-`null` map to put the methods and accessors from the pa
ssed |
| 5399 * [ClassElement] into | 5400 * [ClassElement] into |
| 5400 * @param type the type that will be recorded into the passed map | 5401 * @param type the type that will be recorded into the passed map |
| 5401 * @param doIncludeAbstract `true` if abstract members will be put into the ma
p | 5402 * @param doIncludeAbstract `true` if abstract members will be put into the ma
p |
| 5402 */ | 5403 */ |
| 5403 void _recordMapWithClassMembers( | 5404 void _recordMapWithClassMembers(Map<String, ExecutableElement> map, |
| 5404 MemberMap map, InterfaceType type, bool doIncludeAbstract) { | 5405 InterfaceType type, bool doIncludeAbstract) { |
| 5405 List<MethodElement> methods = type.methods; | 5406 List<MethodElement> methods = type.methods; |
| 5406 for (MethodElement method in methods) { | 5407 for (MethodElement method in methods) { |
| 5407 if (method.isAccessibleIn(_library) && | 5408 if (method.isAccessibleIn(_library) && |
| 5408 !method.isStatic && | 5409 !method.isStatic && |
| 5409 (doIncludeAbstract || !method.isAbstract)) { | 5410 (doIncludeAbstract || !method.isAbstract)) { |
| 5410 map.put(method.name, method); | 5411 map[method.name] = method; |
| 5411 } | 5412 } |
| 5412 } | 5413 } |
| 5413 List<PropertyAccessorElement> accessors = type.accessors; | 5414 List<PropertyAccessorElement> accessors = type.accessors; |
| 5414 for (PropertyAccessorElement accessor in accessors) { | 5415 for (PropertyAccessorElement accessor in accessors) { |
| 5415 if (accessor.isAccessibleIn(_library) && | 5416 if (accessor.isAccessibleIn(_library) && |
| 5416 !accessor.isStatic && | 5417 !accessor.isStatic && |
| 5417 (doIncludeAbstract || !accessor.isAbstract)) { | 5418 (doIncludeAbstract || !accessor.isAbstract)) { |
| 5418 map.put(accessor.name, accessor); | 5419 map[accessor.name] = accessor; |
| 5419 } | 5420 } |
| 5420 } | 5421 } |
| 5421 } | 5422 } |
| 5422 | 5423 |
| 5423 /** | 5424 /** |
| 5424 * This method is used to report errors on when they are found computing inher
itance information. | 5425 * This method is used to report errors on when they are found computing inher
itance information. |
| 5425 * See [ErrorVerifier.checkForInconsistentMethodInheritance] to see where thes
e generated | 5426 * See [ErrorVerifier.checkForInconsistentMethodInheritance] to see where thes
e generated |
| 5426 * error codes are reported back into the analysis engine. | 5427 * error codes are reported back into the analysis engine. |
| 5427 * | 5428 * |
| 5428 * @param classElt the location of the source for which the exception occurred | 5429 * @param classElt the location of the source for which the exception occurred |
| (...skipping 18 matching lines...) Expand all Loading... |
| 5447 * apply the appropriate inheritance rules to determine those methods inherite
d by or overridden | 5448 * apply the appropriate inheritance rules to determine those methods inherite
d by or overridden |
| 5448 * by [classElt]. Also report static warnings | 5449 * by [classElt]. Also report static warnings |
| 5449 * [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE] and | 5450 * [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE] and |
| 5450 * [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD] if ap
propriate. | 5451 * [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD] if ap
propriate. |
| 5451 * | 5452 * |
| 5452 * @param classElt the class element to query. | 5453 * @param classElt the class element to query. |
| 5453 * @param unionMap a mapping from method name to the set of unique (in terms o
f signature) methods | 5454 * @param unionMap a mapping from method name to the set of unique (in terms o
f signature) methods |
| 5454 * defined in superclasses of [classElt]. | 5455 * defined in superclasses of [classElt]. |
| 5455 * @return the inheritance lookup map for [classElt]. | 5456 * @return the inheritance lookup map for [classElt]. |
| 5456 */ | 5457 */ |
| 5457 MemberMap _resolveInheritanceLookup(ClassElement classElt, | 5458 Map<String, ExecutableElement> _resolveInheritanceLookup( |
| 5458 HashMap<String, List<ExecutableElement>> unionMap) { | 5459 ClassElement classElt, Map<String, List<ExecutableElement>> unionMap) { |
| 5459 MemberMap resultMap = new MemberMap(); | 5460 Map<String, ExecutableElement> resultMap = |
| 5461 new HashMap<String, ExecutableElement>(); |
| 5460 unionMap.forEach((String key, List<ExecutableElement> list) { | 5462 unionMap.forEach((String key, List<ExecutableElement> list) { |
| 5461 int numOfEltsWithMatchingNames = list.length; | 5463 int numOfEltsWithMatchingNames = list.length; |
| 5462 if (numOfEltsWithMatchingNames == 1) { | 5464 if (numOfEltsWithMatchingNames == 1) { |
| 5463 // | 5465 // |
| 5464 // Example: class A inherits only 1 method named 'm'. | 5466 // Example: class A inherits only 1 method named 'm'. |
| 5465 // Since it is the only such method, it is inherited. | 5467 // Since it is the only such method, it is inherited. |
| 5466 // Another example: class A inherits 2 methods named 'm' from 2 | 5468 // Another example: class A inherits 2 methods named 'm' from 2 |
| 5467 // different interfaces, but they both have the same signature, so it is | 5469 // different interfaces, but they both have the same signature, so it is |
| 5468 // the method inherited. | 5470 // the method inherited. |
| 5469 // | 5471 // |
| 5470 resultMap.put(key, list[0]); | 5472 resultMap[key] = list[0]; |
| 5471 } else { | 5473 } else { |
| 5472 // | 5474 // |
| 5473 // Then numOfEltsWithMatchingNames > 1, check for the warning cases. | 5475 // Then numOfEltsWithMatchingNames > 1, check for the warning cases. |
| 5474 // | 5476 // |
| 5475 bool allMethods = true; | 5477 bool allMethods = true; |
| 5476 bool allSetters = true; | 5478 bool allSetters = true; |
| 5477 bool allGetters = true; | 5479 bool allGetters = true; |
| 5478 for (ExecutableElement executableElement in list) { | 5480 for (ExecutableElement executableElement in list) { |
| 5479 if (executableElement is PropertyAccessorElement) { | 5481 if (executableElement is PropertyAccessorElement) { |
| 5480 allMethods = false; | 5482 allMethods = false; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5532 // | 5534 // |
| 5533 if (subtypesOfAllOtherTypesIndexes.length == 1) { | 5535 if (subtypesOfAllOtherTypesIndexes.length == 1) { |
| 5534 // | 5536 // |
| 5535 // Example: class A inherited only 2 method named 'm'. | 5537 // Example: class A inherited only 2 method named 'm'. |
| 5536 // One has the function type '() -> dynamic' and one has the | 5538 // One has the function type '() -> dynamic' and one has the |
| 5537 // function type '([int]) -> dynamic'. Since the second method is a | 5539 // function type '([int]) -> dynamic'. Since the second method is a |
| 5538 // subtype of all the others, it is the inherited method. | 5540 // subtype of all the others, it is the inherited method. |
| 5539 // Tests: InheritanceManagerTest. | 5541 // Tests: InheritanceManagerTest. |
| 5540 // test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_* | 5542 // test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_* |
| 5541 // | 5543 // |
| 5542 resultMap.put(key, elements[subtypesOfAllOtherTypesIndexes[0]]); | 5544 resultMap[key] = elements[subtypesOfAllOtherTypesIndexes[0]]; |
| 5543 } else { | 5545 } else { |
| 5544 if (subtypesOfAllOtherTypesIndexes.isEmpty) { | 5546 if (subtypesOfAllOtherTypesIndexes.isEmpty) { |
| 5545 // | 5547 // |
| 5546 // Determine if the current class has a method or accessor with | 5548 // Determine if the current class has a method or accessor with |
| 5547 // the member name, if it does then then this class does not | 5549 // the member name, if it does then then this class does not |
| 5548 // "inherit" from any of the supertypes. See issue 16134. | 5550 // "inherit" from any of the supertypes. See issue 16134. |
| 5549 // | 5551 // |
| 5550 bool classHasMember = false; | 5552 bool classHasMember = false; |
| 5551 if (allMethods) { | 5553 if (allMethods) { |
| 5552 classHasMember = classElt.getMethod(key) != null; | 5554 classHasMember = classElt.getMethod(key) != null; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5586 // | 5588 // |
| 5587 List<ExecutableElement> elementArrayToMerge = | 5589 List<ExecutableElement> elementArrayToMerge = |
| 5588 new List<ExecutableElement>( | 5590 new List<ExecutableElement>( |
| 5589 subtypesOfAllOtherTypesIndexes.length); | 5591 subtypesOfAllOtherTypesIndexes.length); |
| 5590 for (int i = 0; i < elementArrayToMerge.length; i++) { | 5592 for (int i = 0; i < elementArrayToMerge.length; i++) { |
| 5591 elementArrayToMerge[i] = | 5593 elementArrayToMerge[i] = |
| 5592 elements[subtypesOfAllOtherTypesIndexes[i]]; | 5594 elements[subtypesOfAllOtherTypesIndexes[i]]; |
| 5593 } | 5595 } |
| 5594 ExecutableElement mergedExecutableElement = | 5596 ExecutableElement mergedExecutableElement = |
| 5595 _computeMergedExecutableElement(elementArrayToMerge); | 5597 _computeMergedExecutableElement(elementArrayToMerge); |
| 5596 resultMap.put(key, mergedExecutableElement); | 5598 resultMap[key] = mergedExecutableElement; |
| 5597 } | 5599 } |
| 5598 } | 5600 } |
| 5599 } else { | 5601 } else { |
| 5600 _reportError( | 5602 _reportError( |
| 5601 classElt, | 5603 classElt, |
| 5602 classElt.nameOffset, | 5604 classElt.nameOffset, |
| 5603 classElt.nameLength, | 5605 classElt.nameLength, |
| 5604 StaticWarningCode | 5606 StaticWarningCode |
| 5605 .INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD, | 5607 .INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD, |
| 5606 [key]); | 5608 [key]); |
| 5607 } | 5609 } |
| 5608 } | 5610 } |
| 5609 }); | 5611 }); |
| 5610 return resultMap; | 5612 return resultMap; |
| 5611 } | 5613 } |
| 5612 | 5614 |
| 5613 /** | 5615 /** |
| 5614 * Loop through all of the members in some [MemberMap], performing type parame
ter | 5616 * Loop through all of the members in the given [map], and perform type |
| 5615 * substitutions using a passed supertype. | 5617 * parameter substitutions using a passed [supertype]. |
| 5616 * | |
| 5617 * @param superType the supertype to substitute into the members of the [Membe
rMap] | |
| 5618 * @param map the MemberMap to perform the substitutions on | |
| 5619 */ | 5618 */ |
| 5620 void _substituteTypeParametersDownHierarchy( | 5619 void _substituteTypeParametersDownHierarchy( |
| 5621 InterfaceType superType, MemberMap map) { | 5620 InterfaceType superType, Map<String, ExecutableElement> map) { |
| 5622 for (int i = 0; i < map.size; i++) { | 5621 for (String memberName in map.keys) { |
| 5623 ExecutableElement executableElement = map.getValue(i); | 5622 ExecutableElement executableElement = map[memberName]; |
| 5624 if (executableElement is MethodMember) { | 5623 if (executableElement is MethodMember) { |
| 5625 executableElement = | 5624 executableElement = |
| 5626 MethodMember.from(executableElement as MethodMember, superType); | 5625 MethodMember.from(executableElement as MethodMember, superType); |
| 5627 map.setValue(i, executableElement); | 5626 map[memberName] = executableElement; |
| 5628 } else if (executableElement is PropertyAccessorMember) { | 5627 } else if (executableElement is PropertyAccessorMember) { |
| 5629 executableElement = PropertyAccessorMember.from( | 5628 executableElement = PropertyAccessorMember.from( |
| 5630 executableElement as PropertyAccessorMember, superType); | 5629 executableElement as PropertyAccessorMember, superType); |
| 5631 map.setValue(i, executableElement); | 5630 map[memberName] = executableElement; |
| 5632 } | 5631 } |
| 5633 } | 5632 } |
| 5634 } | 5633 } |
| 5635 | 5634 |
| 5636 /** | 5635 /** |
| 5637 * Union all of the [lookupMaps] together into a single map, grouping the Exec
utableElements | 5636 * Union all of the [lookupMaps] together into a single map, grouping the Exec
utableElements |
| 5638 * into a list where none of the elements are equal where equality is determin
ed by having equal | 5637 * into a list where none of the elements are equal where equality is determin
ed by having equal |
| 5639 * function types. (We also take note too of the kind of the element: ()->int
and () -> int may | 5638 * function types. (We also take note too of the kind of the element: ()->int
and () -> int may |
| 5640 * not be equal if one is a getter and the other is a method.) | 5639 * not be equal if one is a getter and the other is a method.) |
| 5641 * | 5640 * |
| 5642 * @param lookupMaps the maps to be unioned together. | 5641 * @param lookupMaps the maps to be unioned together. |
| 5643 * @return the resulting union map. | 5642 * @return the resulting union map. |
| 5644 */ | 5643 */ |
| 5645 HashMap<String, List<ExecutableElement>> _unionInterfaceLookupMaps( | 5644 Map<String, List<ExecutableElement>> _unionInterfaceLookupMaps( |
| 5646 List<MemberMap> lookupMaps) { | 5645 List<Map<String, ExecutableElement>> lookupMaps) { |
| 5647 HashMap<String, List<ExecutableElement>> unionMap = | 5646 Map<String, List<ExecutableElement>> unionMap = |
| 5648 new HashMap<String, List<ExecutableElement>>(); | 5647 new HashMap<String, List<ExecutableElement>>(); |
| 5649 for (MemberMap lookupMap in lookupMaps) { | 5648 for (Map<String, ExecutableElement> lookupMap in lookupMaps) { |
| 5650 int lookupMapSize = lookupMap.size; | 5649 for (String memberName in lookupMap.keys) { |
| 5651 for (int i = 0; i < lookupMapSize; i++) { | |
| 5652 // Get the string key, if null, break. | |
| 5653 String key = lookupMap.getKey(i); | |
| 5654 if (key == null) { | |
| 5655 break; | |
| 5656 } | |
| 5657 // Get the list value out of the unionMap | 5650 // Get the list value out of the unionMap |
| 5658 List<ExecutableElement> list = unionMap[key]; | 5651 List<ExecutableElement> list = unionMap[memberName]; |
| 5659 // If we haven't created such a map for this key yet, do create it and | 5652 // If we haven't created such a map for this key yet, do create it and |
| 5660 // put the list entry into the unionMap. | 5653 // put the list entry into the unionMap. |
| 5661 if (list == null) { | 5654 if (list == null) { |
| 5662 list = new List<ExecutableElement>(); | 5655 list = new List<ExecutableElement>(); |
| 5663 unionMap[key] = list; | 5656 unionMap[memberName] = list; |
| 5664 } | 5657 } |
| 5665 // Fetch the entry out of this lookupMap | 5658 // Fetch the entry out of this lookupMap |
| 5666 ExecutableElement newExecutableElementEntry = lookupMap.getValue(i); | 5659 ExecutableElement newExecutableElementEntry = lookupMap[memberName]; |
| 5667 if (list.isEmpty) { | 5660 if (list.isEmpty) { |
| 5668 // If the list is empty, just the new value | 5661 // If the list is empty, just the new value |
| 5669 list.add(newExecutableElementEntry); | 5662 list.add(newExecutableElementEntry); |
| 5670 } else { | 5663 } else { |
| 5671 // Otherwise, only add the newExecutableElementEntry if it isn't | 5664 // Otherwise, only add the newExecutableElementEntry if it isn't |
| 5672 // already in the list, this covers situation where a class inherits | 5665 // already in the list, this covers situation where a class inherits |
| 5673 // two methods (or two getters) that are identical. | 5666 // two methods (or two getters) that are identical. |
| 5674 bool alreadyInList = false; | 5667 bool alreadyInList = false; |
| 5675 bool isMethod1 = newExecutableElementEntry is MethodElement; | 5668 bool isMethod1 = newExecutableElementEntry is MethodElement; |
| 5676 for (ExecutableElement executableElementInList in list) { | 5669 for (ExecutableElement executableElementInList in list) { |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5885 NOT_INIT, | 5878 NOT_INIT, |
| 5886 INIT_IN_DECLARATION, | 5879 INIT_IN_DECLARATION, |
| 5887 INIT_IN_FIELD_FORMAL, | 5880 INIT_IN_FIELD_FORMAL, |
| 5888 INIT_IN_INITIALIZERS | 5881 INIT_IN_INITIALIZERS |
| 5889 ]; | 5882 ]; |
| 5890 | 5883 |
| 5891 const INIT_STATE(String name, int ordinal) : super(name, ordinal); | 5884 const INIT_STATE(String name, int ordinal) : super(name, ordinal); |
| 5892 } | 5885 } |
| 5893 | 5886 |
| 5894 /** | 5887 /** |
| 5895 * This class is used to replace uses of `HashMap<String, ExecutableElement>` | |
| 5896 * which are not as performant as this class. | |
| 5897 */ | |
| 5898 class MemberMap { | |
| 5899 /** | |
| 5900 * The current size of this map. | |
| 5901 */ | |
| 5902 int _size = 0; | |
| 5903 | |
| 5904 /** | |
| 5905 * The array of keys. | |
| 5906 */ | |
| 5907 List<String> _keys; | |
| 5908 | |
| 5909 /** | |
| 5910 * The array of ExecutableElement values. | |
| 5911 */ | |
| 5912 List<ExecutableElement> _values; | |
| 5913 | |
| 5914 /** | |
| 5915 * Initialize a newly created member map to have the given [initialCapacity]. | |
| 5916 * The map will grow if needed. | |
| 5917 */ | |
| 5918 MemberMap([int initialCapacity = 10]) { | |
| 5919 _initArrays(initialCapacity); | |
| 5920 } | |
| 5921 | |
| 5922 /** | |
| 5923 * Initialize a newly created member map to contain the same members as the | |
| 5924 * given [memberMap]. | |
| 5925 */ | |
| 5926 MemberMap.from(MemberMap memberMap) { | |
| 5927 _initArrays(memberMap._size + 5); | |
| 5928 for (int i = 0; i < memberMap._size; i++) { | |
| 5929 _keys[i] = memberMap._keys[i]; | |
| 5930 _values[i] = memberMap._values[i]; | |
| 5931 } | |
| 5932 _size = memberMap._size; | |
| 5933 } | |
| 5934 | |
| 5935 /** | |
| 5936 * The size of the map. | |
| 5937 * | |
| 5938 * @return the size of the map. | |
| 5939 */ | |
| 5940 int get size => _size; | |
| 5941 | |
| 5942 /** | |
| 5943 * Given some key, return the ExecutableElement value from the map, if the key
does not exist in | |
| 5944 * the map, `null` is returned. | |
| 5945 * | |
| 5946 * @param key some key to look up in the map | |
| 5947 * @return the associated ExecutableElement value from the map, if the key doe
s not exist in the | |
| 5948 * map, `null` is returned | |
| 5949 */ | |
| 5950 ExecutableElement get(String key) { | |
| 5951 for (int i = 0; i < _size; i++) { | |
| 5952 if (_keys[i] != null && _keys[i] == key) { | |
| 5953 return _values[i]; | |
| 5954 } | |
| 5955 } | |
| 5956 return null; | |
| 5957 } | |
| 5958 | |
| 5959 /** | |
| 5960 * Get and return the key at the specified location. If the key/value pair has
been removed from | |
| 5961 * the set, then `null` is returned. | |
| 5962 * | |
| 5963 * @param i some non-zero value less than size | |
| 5964 * @return the key at the passed index | |
| 5965 * @throw ArrayIndexOutOfBoundsException this exception is thrown if the passe
d index is less than | |
| 5966 * zero or greater than or equal to the capacity of the arrays | |
| 5967 */ | |
| 5968 String getKey(int i) => _keys[i]; | |
| 5969 | |
| 5970 /** | |
| 5971 * Get and return the ExecutableElement at the specified location. If the key/
value pair has been | |
| 5972 * removed from the set, then then `null` is returned. | |
| 5973 * | |
| 5974 * @param i some non-zero value less than size | |
| 5975 * @return the key at the passed index | |
| 5976 * @throw ArrayIndexOutOfBoundsException this exception is thrown if the passe
d index is less than | |
| 5977 * zero or greater than or equal to the capacity of the arrays | |
| 5978 */ | |
| 5979 ExecutableElement getValue(int i) => _values[i]; | |
| 5980 | |
| 5981 /** | |
| 5982 * Given some key/value pair, store the pair in the map. If the key exists alr
eady, then the new | |
| 5983 * value overrides the old value. | |
| 5984 * | |
| 5985 * @param key the key to store in the map | |
| 5986 * @param value the ExecutableElement value to store in the map | |
| 5987 */ | |
| 5988 void put(String key, ExecutableElement value) { | |
| 5989 // If we already have a value with this key, override the value | |
| 5990 for (int i = 0; i < _size; i++) { | |
| 5991 if (_keys[i] != null && _keys[i] == key) { | |
| 5992 _values[i] = value; | |
| 5993 return; | |
| 5994 } | |
| 5995 } | |
| 5996 // If needed, double the size of our arrays and copy values over in both | |
| 5997 // arrays | |
| 5998 if (_size == _keys.length) { | |
| 5999 int newArrayLength = _size * 2; | |
| 6000 List<String> keys_new_array = new List<String>(newArrayLength); | |
| 6001 List<ExecutableElement> values_new_array = | |
| 6002 new List<ExecutableElement>(newArrayLength); | |
| 6003 for (int i = 0; i < _size; i++) { | |
| 6004 keys_new_array[i] = _keys[i]; | |
| 6005 } | |
| 6006 for (int i = 0; i < _size; i++) { | |
| 6007 values_new_array[i] = _values[i]; | |
| 6008 } | |
| 6009 _keys = keys_new_array; | |
| 6010 _values = values_new_array; | |
| 6011 } | |
| 6012 // Put new value at end of array | |
| 6013 _keys[_size] = key; | |
| 6014 _values[_size] = value; | |
| 6015 _size++; | |
| 6016 } | |
| 6017 | |
| 6018 /** | |
| 6019 * Given some [String] key, this method replaces the associated key and value
pair with | |
| 6020 * `null`. The size is not decremented with this call, instead it is expected
that the users | |
| 6021 * check for `null`. | |
| 6022 * | |
| 6023 * @param key the key of the key/value pair to remove from the map | |
| 6024 */ | |
| 6025 void remove(String key) { | |
| 6026 for (int i = 0; i < _size; i++) { | |
| 6027 if (_keys[i] == key) { | |
| 6028 _keys[i] = null; | |
| 6029 _values[i] = null; | |
| 6030 return; | |
| 6031 } | |
| 6032 } | |
| 6033 } | |
| 6034 | |
| 6035 /** | |
| 6036 * Sets the ExecutableElement at the specified location. | |
| 6037 * | |
| 6038 * @param i some non-zero value less than size | |
| 6039 * @param value the ExecutableElement value to store in the map | |
| 6040 */ | |
| 6041 void setValue(int i, ExecutableElement value) { | |
| 6042 _values[i] = value; | |
| 6043 } | |
| 6044 | |
| 6045 /** | |
| 6046 * Initializes [keys] and [values]. | |
| 6047 */ | |
| 6048 void _initArrays(int initialCapacity) { | |
| 6049 _keys = new List<String>(initialCapacity); | |
| 6050 _values = new List<ExecutableElement>(initialCapacity); | |
| 6051 } | |
| 6052 } | |
| 6053 | |
| 6054 /** | |
| 6055 * Instances of the class `OverrideVerifier` visit all of the declarations in a
compilation | 5888 * Instances of the class `OverrideVerifier` visit all of the declarations in a
compilation |
| 6056 * unit to verify that if they have an override annotation it is being used corr
ectly. | 5889 * unit to verify that if they have an override annotation it is being used corr
ectly. |
| 6057 */ | 5890 */ |
| 6058 class OverrideVerifier extends RecursiveAstVisitor<Object> { | 5891 class OverrideVerifier extends RecursiveAstVisitor<Object> { |
| 6059 /** | 5892 /** |
| 6060 * The error reporter used to report errors. | 5893 * The error reporter used to report errors. |
| 6061 */ | 5894 */ |
| 6062 final ErrorReporter _errorReporter; | 5895 final ErrorReporter _errorReporter; |
| 6063 | 5896 |
| 6064 /** | 5897 /** |
| (...skipping 5884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11949 nonFields.add(node); | 11782 nonFields.add(node); |
| 11950 return null; | 11783 return null; |
| 11951 } | 11784 } |
| 11952 | 11785 |
| 11953 @override | 11786 @override |
| 11954 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); | 11787 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); |
| 11955 | 11788 |
| 11956 @override | 11789 @override |
| 11957 Object visitWithClause(WithClause node) => null; | 11790 Object visitWithClause(WithClause node) => null; |
| 11958 } | 11791 } |
| OLD | NEW |