| 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 library linter.src.util.dart_type_utilities; | 5 library linter.src.util.dart_type_utilities; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 8 import 'package:analyzer/dart/element/element.dart'; | 10 import 'package:analyzer/dart/element/element.dart'; |
| 9 import 'package:analyzer/dart/element/type.dart'; | 11 import 'package:analyzer/dart/element/type.dart'; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | |
| 11 | 12 |
| 12 typedef bool AstNodePredicate(AstNode node); | 13 typedef bool AstNodePredicate(AstNode node); |
| 13 | 14 |
| 14 class DartTypeUtilities { | 15 class DartTypeUtilities { |
| 15 static bool unrelatedTypes(DartType leftType, DartType rightType) { | 16 static bool extendsClass(DartType type, String className, String library) => |
| 16 if (leftType == null || | 17 type != null && |
| 17 leftType.isBottom || | 18 type.name == className && |
| 18 leftType.isDynamic || | 19 type.element.library.name == library || |
| 19 rightType == null || | 20 (type is InterfaceType && |
| 20 rightType.isBottom || | 21 extendsClass(type.superclass, className, library)); |
| 21 rightType.isDynamic) { | 22 |
| 23 static bool implementsAnyInterface( |
| 24 DartType type, Iterable<InterfaceTypeDefinition> definitions) { |
| 25 if (type is! InterfaceType) { |
| 22 return false; | 26 return false; |
| 23 } | 27 } |
| 24 if (leftType == rightType || | 28 bool predicate(InterfaceType i) => definitions |
| 25 leftType.isMoreSpecificThan(rightType) || | 29 .any((d) => i.name == d.name && i.element.library.name == d.library); |
| 26 rightType.isMoreSpecificThan(leftType)) { | |
| 27 return false; | |
| 28 } | |
| 29 Element leftElement = leftType.element; | |
| 30 Element rightElement = rightType.element; | |
| 31 if (leftElement is ClassElement && rightElement is ClassElement) { | |
| 32 return leftElement.supertype.isObject || | |
| 33 leftElement.supertype != rightElement.supertype; | |
| 34 } | |
| 35 return false; | |
| 36 } | |
| 37 | |
| 38 static bool implementsInterface( | |
| 39 DartType type, String interface, String library) { | |
| 40 bool predicate(InterfaceType i) => | |
| 41 i.name == interface && i.element.library.name == library; | |
| 42 ClassElement element = type.element; | 30 ClassElement element = type.element; |
| 43 return predicate(type) || | 31 return predicate(type) || |
| 44 !element.isSynthetic && | 32 !element.isSynthetic && |
| 45 type is InterfaceType && | 33 type is InterfaceType && |
| 46 element.allSupertypes.any(predicate); | 34 element.allSupertypes.any(predicate); |
| 47 } | 35 } |
| 48 | 36 |
| 49 static bool implementsAnyInterface( | 37 static bool implementsInterface( |
| 50 DartType type, Iterable<InterfaceTypeDefinition> definitions) { | 38 DartType type, String interface, String library) { |
| 51 bool predicate(InterfaceType i) => definitions | 39 if (type is! InterfaceType) { |
| 52 .any((d) => i.name == d.name && i.element.library.name == d.library); | 40 return false; |
| 41 } |
| 42 bool predicate(InterfaceType i) => |
| 43 i.name == interface && i.element.library.name == library; |
| 53 ClassElement element = type.element; | 44 ClassElement element = type.element; |
| 54 return predicate(type) || | 45 return predicate(type) || |
| 55 !element.isSynthetic && | 46 !element.isSynthetic && |
| 56 type is InterfaceType && | 47 type is InterfaceType && |
| 57 element.allSupertypes.any(predicate); | 48 element.allSupertypes.any(predicate); |
| 58 } | 49 } |
| 59 | 50 |
| 60 static bool extendsClass(DartType type, String className, String library) => | |
| 61 type != null && | |
| 62 type.name == className && | |
| 63 type.element.library.name == library || | |
| 64 (type is InterfaceType && | |
| 65 extendsClass(type.superclass, className, library)); | |
| 66 | |
| 67 /// Builds the list resulting from traversing the node in DFS and does not | 51 /// Builds the list resulting from traversing the node in DFS and does not |
| 68 /// include the node itself. | 52 /// include the node itself. |
| 69 static Iterable<AstNode> traverseNodesInDFS(AstNode node) { | 53 static Iterable<AstNode> traverseNodesInDFS(AstNode node) { |
| 70 LinkedHashSet<AstNode> nodes = new LinkedHashSet(); | 54 LinkedHashSet<AstNode> nodes = new LinkedHashSet(); |
| 71 node.childEntities.where((c) => c is AstNode).forEach((c) { | 55 node.childEntities.where((c) => c is AstNode).forEach((c) { |
| 72 nodes.add(c); | 56 nodes.add(c); |
| 73 nodes.addAll(traverseNodesInDFS(c)); | 57 nodes.addAll(traverseNodesInDFS(c)); |
| 74 }); | 58 }); |
| 75 return nodes; | 59 return nodes; |
| 76 } | 60 } |
| 61 |
| 62 static bool unrelatedTypes(DartType leftType, DartType rightType) { |
| 63 if (leftType == null || |
| 64 leftType.isBottom || |
| 65 leftType.isDynamic || |
| 66 rightType == null || |
| 67 rightType.isBottom || |
| 68 rightType.isDynamic) { |
| 69 return false; |
| 70 } |
| 71 if (leftType == rightType || |
| 72 leftType.isMoreSpecificThan(rightType) || |
| 73 rightType.isMoreSpecificThan(leftType)) { |
| 74 return false; |
| 75 } |
| 76 Element leftElement = leftType.element; |
| 77 Element rightElement = rightType.element; |
| 78 if (leftElement is ClassElement && rightElement is ClassElement) { |
| 79 return leftElement.supertype.isObject || |
| 80 leftElement.supertype != rightElement.supertype; |
| 81 } |
| 82 return false; |
| 83 } |
| 77 } | 84 } |
| 78 | 85 |
| 79 class InterfaceTypeDefinition { | 86 class InterfaceTypeDefinition { |
| 80 final String name; | 87 final String name; |
| 81 final String library; | 88 final String library; |
| 82 | 89 |
| 83 InterfaceTypeDefinition(this.name, this.library); | 90 InterfaceTypeDefinition(this.name, this.library); |
| 84 | 91 |
| 85 @override | 92 @override |
| 93 int get hashCode { |
| 94 return name.hashCode ^ library.hashCode; |
| 95 } |
| 96 |
| 97 @override |
| 86 bool operator ==(Object other) { | 98 bool operator ==(Object other) { |
| 87 if (identical(this, other)) { | 99 if (identical(this, other)) { |
| 88 return true; | 100 return true; |
| 89 } | 101 } |
| 90 return other is InterfaceTypeDefinition && | 102 return other is InterfaceTypeDefinition && |
| 91 this.name == other.name && | 103 this.name == other.name && |
| 92 this.library == other.library; | 104 this.library == other.library; |
| 93 } | 105 } |
| 94 | |
| 95 @override | |
| 96 int get hashCode { | |
| 97 return name.hashCode ^ library.hashCode; | |
| 98 } | |
| 99 } | 106 } |
| OLD | NEW |