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 |