| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 dev_compiler.src.checker.rules; | 5 library dev_compiler.src.checker.rules; |
| 6 | 6 |
| 7 import 'package:analyzer/src/generated/ast.dart'; | 7 import 'package:analyzer/src/generated/ast.dart'; |
| 8 import 'package:analyzer/src/generated/element.dart'; | 8 import 'package:analyzer/src/generated/element.dart'; |
| 9 import 'package:analyzer/src/generated/resolver.dart'; | 9 import 'package:analyzer/src/generated/resolver.dart'; |
| 10 | 10 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 _nonnullableTypes.addAll(types.map(_typeFromName)); | 107 _nonnullableTypes.addAll(types.map(_typeFromName)); |
| 108 } | 108 } |
| 109 | 109 |
| 110 DartType getStaticType(Expression expr) { | 110 DartType getStaticType(Expression expr) { |
| 111 var type = expr.staticType; | 111 var type = expr.staticType; |
| 112 if (type != null) return type; | 112 if (type != null) return type; |
| 113 _reporter.log(new MissingTypeError(expr)); | 113 _reporter.log(new MissingTypeError(expr)); |
| 114 return provider.dynamicType; | 114 return provider.dynamicType; |
| 115 } | 115 } |
| 116 | 116 |
| 117 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) { |
| 118 if (t.isDynamic && dynamicIsBottom) return true; |
| 119 // TODO(vsm): We need direct support for non-nullability in DartType. |
| 120 // This should check on "true/nonnullable" Bottom |
| 121 if (t.isBottom && _nonnullableTypes.isEmpty) return true; |
| 122 return false; |
| 123 } |
| 124 |
| 125 bool _isTop(DartType t, {bool dynamicIsBottom: false}) { |
| 126 if (t.isDynamic && !dynamicIsBottom) return true; |
| 127 if (t.isObject) return true; |
| 128 return false; |
| 129 } |
| 130 |
| 117 bool isNonNullableType(DartType t) => _nonnullableTypes.contains(t); | 131 bool isNonNullableType(DartType t) => _nonnullableTypes.contains(t); |
| 118 | 132 |
| 119 bool maybeNonNullableType(DartType t) { | 133 bool maybeNonNullableType(DartType t) { |
| 120 // Return true iff t *may* be a primitive type. | 134 // Return true iff t *may* be a primitive type. |
| 121 // If t is a generic type parameter, return true if it may be | 135 // If t is a generic type parameter, return true if it may be |
| 122 // instantiated as a primitive. | 136 // instantiated as a primitive. |
| 123 if (isNonNullableType(t)) { | 137 if (isNonNullableType(t)) { |
| 124 return true; | 138 return true; |
| 125 } else if (t is TypeParameterType) { | 139 } else if (t is TypeParameterType) { |
| 126 var bound = t.element.bound; | 140 var bound = t.element.bound; |
| 127 if (bound == null) { | 141 if (bound == null) { |
| 128 bound = provider.dynamicType; | 142 bound = provider.dynamicType; |
| 129 } | 143 } |
| 130 return _nonnullableTypes.any((DartType p) => isSubTypeOf(p, bound)); | 144 return _nonnullableTypes.any((DartType p) => isSubTypeOf(p, bound)); |
| 131 } else { | 145 } else { |
| 132 return false; | 146 return false; |
| 133 } | 147 } |
| 134 } | 148 } |
| 135 | 149 |
| 136 bool _anyParameterType(FunctionType ft, bool predicate(DartType t)) { | 150 bool _anyParameterType(FunctionType ft, bool predicate(DartType t)) { |
| 137 return ft.normalParameterTypes.any(predicate) || | 151 return ft.normalParameterTypes.any(predicate) || |
| 138 ft.optionalParameterTypes.any(predicate) || | 152 ft.optionalParameterTypes.any(predicate) || |
| 139 ft.namedParameterTypes.values.any(predicate); | 153 ft.namedParameterTypes.values.any(predicate); |
| 140 } | 154 } |
| 141 | 155 |
| 142 // TODO(leafp): Revisit this. | 156 // TODO(leafp): Revisit this. |
| 143 bool isGroundType(DartType t) { | 157 bool isGroundType(DartType t) { |
| 144 if (t is TypeParameterType) return false; | 158 if (t is TypeParameterType) return false; |
| 145 if (t.isDynamic) return true; | 159 if (_isTop(t)) return true; |
| 146 | 160 |
| 147 if (t is FunctionType) { | 161 if (t is FunctionType) { |
| 148 if (!t.returnType.isDynamic || | 162 if (!_isTop(t.returnType) || |
| 149 _anyParameterType(t, (pt) => !pt.isDynamic)) { | 163 _anyParameterType(t, (pt) => !_isBottom(pt, dynamicIsBottom: true))) { |
| 150 return false; | 164 return false; |
| 151 } else { | 165 } else { |
| 152 return true; | 166 return true; |
| 153 } | 167 } |
| 154 } | 168 } |
| 155 | 169 |
| 156 if (t is InterfaceType) { | 170 if (t is InterfaceType) { |
| 157 var typeArguments = t.typeArguments; | 171 var typeArguments = t.typeArguments; |
| 158 for (var typeArgument in typeArguments) { | 172 for (var typeArgument in typeArguments) { |
| 159 if (!typeArgument.isDynamic && !typeArgument.isObject) return false; | 173 if (!_isTop(typeArgument)) return false; |
| 160 } | 174 } |
| 161 return true; | 175 return true; |
| 162 } | 176 } |
| 163 | 177 |
| 164 throw new StateError("Unexpected type"); | 178 throw new StateError("Unexpected type"); |
| 165 } | 179 } |
| 166 | 180 |
| 167 FunctionType getCallMethodType(DartType t) { | 181 FunctionType getCallMethodType(DartType t) { |
| 168 if (t is InterfaceType) { | 182 if (t is InterfaceType) { |
| 169 ClassElement element = t.element; | 183 ClassElement element = t.element; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 for (final parent in i1.mixins) { | 286 for (final parent in i1.mixins) { |
| 273 if (_isInterfaceSubTypeOf(parent, i2)) return true; | 287 if (_isInterfaceSubTypeOf(parent, i2)) return true; |
| 274 } | 288 } |
| 275 | 289 |
| 276 return false; | 290 return false; |
| 277 } | 291 } |
| 278 | 292 |
| 279 bool isSubTypeOf(DartType t1, DartType t2, {bool dynamicIsBottom: false}) { | 293 bool isSubTypeOf(DartType t1, DartType t2, {bool dynamicIsBottom: false}) { |
| 280 if (t1 == t2) return true; | 294 if (t1 == t2) return true; |
| 281 | 295 |
| 282 if (t2.isDynamic) return !dynamicIsBottom; | 296 // Trivially true. |
| 283 if (t1.isDynamic) return dynamicIsBottom; | 297 if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) || |
| 298 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) { |
| 299 return true; |
| 300 } |
| 284 | 301 |
| 285 // Null can be assigned to anything non-primitive. | 302 // Trivially false. |
| 286 // FIXME: Can this be anything besides null? | 303 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) || |
| 304 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) { |
| 305 return false; |
| 306 } |
| 307 |
| 308 // The null type is a subtype of any nonnullable type. |
| 309 // TODO(vsm): Note, t1.isBottom still allows for null confusingly. |
| 310 // _isBottom(t1) does not necessarily imply t1.isBottom if there are |
| 311 // nonnullable types in the system. |
| 287 if (t1.isBottom) { | 312 if (t1.isBottom) { |
| 288 // Return false iff t2 *may* be a primitive type. | 313 // Return false iff t2 *may* be a primitive type. |
| 289 return !maybeNonNullableType(t2); | 314 return !maybeNonNullableType(t2); |
| 290 } | 315 } |
| 291 if (t2.isBottom) return false; | |
| 292 | |
| 293 // Trivially true for non-primitives. | |
| 294 if (t2 == provider.objectType) return true; | |
| 295 if (t1 == provider.objectType) return false; | |
| 296 | 316 |
| 297 // S <: T where S is a type variable | 317 // S <: T where S is a type variable |
| 298 // T is not dynamic or object (handled above) | 318 // T is not dynamic or object (handled above) |
| 299 // S != T (handled above) | 319 // S != T (handled above) |
| 300 // So only true if bound of S is S' and | 320 // So only true if bound of S is S' and |
| 301 // S' <: T | 321 // S' <: T |
| 302 if (t1 is TypeParameterType) { | 322 if (t1 is TypeParameterType) { |
| 303 DartType bound = t1.element.bound; | 323 DartType bound = t1.element.bound; |
| 304 if (bound == null) return false; | 324 if (bound == null) return false; |
| 305 return isSubTypeOf(bound, t2); | 325 return isSubTypeOf(bound, t2); |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 if (element is FunctionElement || element is MethodElement) { | 544 if (element is FunctionElement || element is MethodElement) { |
| 525 // An original declaration. | 545 // An original declaration. |
| 526 return false; | 546 return false; |
| 527 } | 547 } |
| 528 } | 548 } |
| 529 | 549 |
| 530 var ft = t as FunctionType; | 550 var ft = t as FunctionType; |
| 531 return _anyParameterType(ft, (pt) => pt.isDynamic); | 551 return _anyParameterType(ft, (pt) => pt.isDynamic); |
| 532 } | 552 } |
| 533 } | 553 } |
| OLD | NEW |