Chromium Code Reviews| 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 14 matching lines...) Expand all Loading... | |
| 25 bool isSubTypeOf(DartType t1, DartType t2); | 25 bool isSubTypeOf(DartType t1, DartType t2); |
| 26 bool isAssignable(DartType t1, DartType t2); | 26 bool isAssignable(DartType t1, DartType t2); |
| 27 | 27 |
| 28 bool isGroundType(DartType t) => true; | 28 bool isGroundType(DartType t) => true; |
| 29 // TODO(vsm): The default implementation is not ignoring the return type, | 29 // TODO(vsm): The default implementation is not ignoring the return type, |
| 30 // only the restricted override is. | 30 // only the restricted override is. |
| 31 bool isFunctionSubTypeOf(FunctionType f1, FunctionType f2, | 31 bool isFunctionSubTypeOf(FunctionType f1, FunctionType f2, |
| 32 {bool fuzzyArrows: true, bool ignoreReturn: false}) => | 32 {bool fuzzyArrows: true, bool ignoreReturn: false}) => |
| 33 isSubTypeOf(f1, f2); | 33 isSubTypeOf(f1, f2); |
| 34 | 34 |
| 35 bool isNonNullableType(DartType t) => false; | |
| 36 bool maybeNonNullableType(DartType t) => false; | |
| 37 | |
| 38 StaticInfo checkAssignment(Expression expr, DartType t); | 35 StaticInfo checkAssignment(Expression expr, DartType t); |
| 39 | 36 |
| 40 DartType getStaticType(Expression expr) => expr.staticType; | 37 DartType getStaticType(Expression expr) => expr.staticType; |
| 41 | 38 |
| 42 /// Given a type t, if t is an interface type with a call method | 39 /// Given a type t, if t is an interface type with a call method |
| 43 /// defined, return the function type for the call method, otherwise | 40 /// defined, return the function type for the call method, otherwise |
| 44 /// return null. | 41 /// return null. |
| 45 FunctionType getCallMethodType(DartType t) { | 42 FunctionType getCallMethodType(DartType t) { |
| 46 if (t is InterfaceType) { | 43 if (t is InterfaceType) { |
| 47 ClassElement element = t.element; | 44 ClassElement element = t.element; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 121 // Malformed type - fallback on analyzer error. | 118 // Malformed type - fallback on analyzer error. |
| 122 return null; | 119 return null; |
| 123 } | 120 } |
| 124 } | 121 } |
| 125 } | 122 } |
| 126 | 123 |
| 127 typedef void MissingTypeReporter(Expression expr); | 124 typedef void MissingTypeReporter(Expression expr); |
| 128 | 125 |
| 129 class RestrictedRules extends TypeRules { | 126 class RestrictedRules extends TypeRules { |
| 130 final StrongModeOptions options; | 127 final StrongModeOptions options; |
| 131 final List<DartType> _nonnullableTypes; | |
| 132 DownwardsInference inferrer; | 128 DownwardsInference inferrer; |
| 133 | 129 |
| 134 DartType _typeFromName(String name) { | 130 RestrictedRules(TypeProvider provider, {this.options}) : super(provider) { |
| 135 switch (name) { | |
| 136 case 'int': | |
| 137 return provider.intType; | |
| 138 case 'double': | |
| 139 return provider.doubleType; | |
| 140 case 'num': | |
| 141 return provider.numType; | |
| 142 case 'bool': | |
| 143 return provider.boolType; | |
| 144 case 'String': | |
| 145 return provider.stringType; | |
| 146 default: | |
| 147 throw new UnsupportedError('Unsupported non-nullable type $name'); | |
| 148 } | |
| 149 } | |
| 150 | |
| 151 RestrictedRules(TypeProvider provider, {this.options}) | |
| 152 : _nonnullableTypes = <DartType>[], | |
| 153 super(provider) { | |
| 154 var types = options.nonnullableTypes; | |
| 155 _nonnullableTypes.addAll(types.map(_typeFromName)); | |
| 156 inferrer = new DownwardsInference(this); | 131 inferrer = new DownwardsInference(this); |
| 157 } | 132 } |
| 158 | 133 |
| 159 DartType getStaticType(Expression expr) { | 134 DartType getStaticType(Expression expr) { |
| 160 var type = expr.staticType; | 135 var type = expr.staticType; |
| 161 if (type != null) return type; | 136 if (type != null) return type; |
| 162 return provider.dynamicType; | 137 return provider.dynamicType; |
| 163 } | 138 } |
| 164 | 139 |
| 165 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) { | 140 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) { |
| 166 if (t.isDynamic && dynamicIsBottom) return true; | 141 if (t.isDynamic && dynamicIsBottom) return true; |
| 167 // TODO(vsm): We need direct support for non-nullability in DartType. | 142 // TODO(vsm): We need direct support for non-nullability in DartType. |
| 168 // This should check on "true/nonnullable" Bottom | 143 // This should check on "true/nonnullable" Bottom |
| 169 if (t.isBottom && _nonnullableTypes.isEmpty) return true; | 144 if (t.isBottom) return true; |
| 170 return false; | 145 return false; |
| 171 } | 146 } |
| 172 | 147 |
| 173 bool _isTop(DartType t, {bool dynamicIsBottom: false}) { | 148 bool _isTop(DartType t, {bool dynamicIsBottom: false}) { |
| 174 if (t.isDynamic && !dynamicIsBottom) return true; | 149 if (t.isDynamic && !dynamicIsBottom) return true; |
| 175 if (t.isObject) return true; | 150 if (t.isObject) return true; |
| 176 return false; | 151 return false; |
| 177 } | 152 } |
| 178 | 153 |
| 179 bool isNonNullableType(DartType t) => _nonnullableTypes.contains(t); | |
| 180 | |
| 181 bool maybeNonNullableType(DartType t) { | |
| 182 // Return true iff t *may* be a primitive type. | |
| 183 // If t is a generic type parameter, return true if it may be | |
| 184 // instantiated as a primitive. | |
| 185 if (isNonNullableType(t)) { | |
| 186 return true; | |
| 187 } else if (t is TypeParameterType) { | |
| 188 var bound = t.element.bound; | |
| 189 if (bound == null) { | |
| 190 bound = provider.dynamicType; | |
| 191 } | |
| 192 return _nonnullableTypes.any((DartType p) => isSubTypeOf(p, bound)); | |
| 193 } else { | |
| 194 return false; | |
| 195 } | |
| 196 } | |
| 197 | |
| 198 bool _anyParameterType(FunctionType ft, bool predicate(DartType t)) { | 154 bool _anyParameterType(FunctionType ft, bool predicate(DartType t)) { |
| 199 return ft.normalParameterTypes.any(predicate) || | 155 return ft.normalParameterTypes.any(predicate) || |
| 200 ft.optionalParameterTypes.any(predicate) || | 156 ft.optionalParameterTypes.any(predicate) || |
| 201 ft.namedParameterTypes.values.any(predicate); | 157 ft.namedParameterTypes.values.any(predicate); |
| 202 } | 158 } |
| 203 | 159 |
| 204 // TODO(leafp): Revisit this. | 160 // TODO(leafp): Revisit this. |
| 205 bool isGroundType(DartType t) { | 161 bool isGroundType(DartType t) { |
| 206 if (t is TypeParameterType) return false; | 162 if (t is TypeParameterType) return false; |
| 207 if (_isTop(t)) return true; | 163 if (_isTop(t)) return true; |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 340 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) { | 296 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) { |
| 341 return true; | 297 return true; |
| 342 } | 298 } |
| 343 | 299 |
| 344 // Trivially false. | 300 // Trivially false. |
| 345 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) || | 301 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) || |
| 346 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) { | 302 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) { |
| 347 return false; | 303 return false; |
| 348 } | 304 } |
| 349 | 305 |
| 350 // The null type is a subtype of any nonnullable type. | 306 // The null type is a subtype of any nullable type, which is all Dart types. |
|
vsm
2015/10/09 15:29:38
doh!
| |
| 351 // TODO(vsm): Note, t1.isBottom still allows for null confusingly. | 307 // TODO(vsm): Note, t1.isBottom still allows for null confusingly. |
| 352 // _isBottom(t1) does not necessarily imply t1.isBottom if there are | 308 // _isBottom(t1) does not necessarily imply t1.isBottom if there are |
| 353 // nonnullable types in the system. | 309 // nonnullable types in the system. |
| 354 if (t1.isBottom) { | 310 if (t1.isBottom) { |
| 355 // Return false iff t2 *may* be a primitive type. | 311 return true; |
| 356 return !maybeNonNullableType(t2); | |
| 357 } | 312 } |
| 358 | 313 |
| 359 // S <: T where S is a type variable | 314 // S <: T where S is a type variable |
| 360 // T is not dynamic or object (handled above) | 315 // T is not dynamic or object (handled above) |
| 361 // S != T (handled above) | 316 // S != T (handled above) |
| 362 // So only true if bound of S is S' and | 317 // So only true if bound of S is S' and |
| 363 // S' <: T | 318 // S' <: T |
| 364 if (t1 is TypeParameterType) { | 319 if (t1 is TypeParameterType) { |
| 365 DartType bound = t1.element.bound; | 320 DartType bound = t1.element.bound; |
| 366 if (bound == null) return false; | 321 if (bound == null) return false; |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 797 var entries = e.entries; | 752 var entries = e.entries; |
| 798 bool inferEntry(MapLiteralEntry entry) { | 753 bool inferEntry(MapLiteralEntry entry) { |
| 799 return _inferExpression(entry.key, kType, errors) && | 754 return _inferExpression(entry.key, kType, errors) && |
| 800 _inferExpression(entry.value, vType, errors); | 755 _inferExpression(entry.value, vType, errors); |
| 801 } | 756 } |
| 802 var b = entries.every(inferEntry); | 757 var b = entries.every(inferEntry); |
| 803 if (b) annotateMapLiteral(e, targs); | 758 if (b) annotateMapLiteral(e, targs); |
| 804 return b; | 759 return b; |
| 805 } | 760 } |
| 806 } | 761 } |
| OLD | NEW |