Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(583)

Side by Side Diff: pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart

Issue 1951363003: Report when members indirectly inherited through a mixin are not implemented (issue 26411) (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Fixed test failures Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/summary/link.dart » ('j') | pkg/analyzer/test/generated/inheritance_manager_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698