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 /// Defines static information collected by the type checker and used later by | 5 /// Defines static information collected by the type checker and used later by |
| 6 /// emitters to generate code. | 6 /// emitters to generate code. |
| 7 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be | 7 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be |
| 8 // refactored to fit into analyzer. | 8 // refactored to fit into analyzer. |
| 9 library analyzer.src.task.strong.info; | 9 library analyzer.src.task.strong.info; |
| 10 | 10 |
| 11 import 'package:analyzer/src/generated/ast.dart'; | 11 import 'package:analyzer/src/generated/ast.dart'; |
| 12 import 'package:analyzer/src/generated/element.dart'; | 12 import 'package:analyzer/src/generated/element.dart'; |
| 13 import 'package:analyzer/src/generated/error.dart'; | 13 import 'package:analyzer/src/generated/error.dart'; |
| 14 | 14 |
| 15 import 'rules.dart'; | 15 import 'rules.dart'; |
| 16 | 16 |
| 17 // The abstract type of coercions mapping one type to another. | 17 // The abstract type of coercions mapping one type to another. |
| 18 // This class also exposes static builder functions which | 18 // This class also exposes static builder functions which |
| 19 // check for errors and reduce redundant coercions to the identity. | 19 // check for errors and reduce redundant coercions to the identity. |
|
Leaf
2015/12/04 19:01:11
I think something went very wrong with the sorting
pquitslund
2015/12/04 19:13:33
Yep. In this case, I think doc comments make sens
| |
| 20 abstract class Coercion { | 20 class AssignmentCast extends DownCast { |
| 21 final DartType fromType; | 21 AssignmentCast(TypeRules rules, Expression expression, Cast cast) |
| 22 final DartType toType; | 22 : super._internal(rules, expression, cast); |
| 23 Coercion(this.fromType, this.toType); | 23 |
| 24 static Coercion cast(DartType fromT, DartType toT) => new Cast(fromT, toT); | 24 @override |
| 25 static Coercion identity(DartType type) => new Identity(type); | 25 String get name => 'STRONG_MODE_ASSIGNMENT_CAST'; |
| 26 static Coercion error() => new CoercionError(); | 26 |
| 27 toErrorCode() => new HintCode(name, message); | |
| 27 } | 28 } |
| 28 | 29 |
| 29 // Coercion which casts one type to another | 30 // Coercion which casts one type to another |
| 30 class Cast extends Coercion { | 31 class Cast extends Coercion { |
| 31 Cast(DartType fromType, DartType toType) : super(fromType, toType); | 32 Cast(DartType fromType, DartType toType) : super(fromType, toType); |
| 32 } | 33 } |
| 33 | 34 |
| 34 // The identity coercion | 35 // The identity coercion |
|
Leaf
2015/12/04 19:01:11
Comment out of place.
pquitslund
2015/12/04 19:13:33
Done.
| |
| 35 class Identity extends Coercion { | 36 abstract class Coercion { |
| 36 Identity(DartType fromType) : super(fromType, fromType); | 37 final DartType fromType; |
| 38 final DartType toType; | |
| 39 Coercion(this.fromType, this.toType); | |
| 40 static Coercion cast(DartType fromT, DartType toT) => new Cast(fromT, toT); | |
| 41 static Coercion error() => new CoercionError(); | |
| 42 static Coercion identity(DartType type) => new Identity(type); | |
| 37 } | 43 } |
| 38 | 44 |
| 39 // The error coercion. This coercion signals that a coercion | 45 // The error coercion. This coercion signals that a coercion |
| 40 // could not be generated. The code generator should not see | 46 // could not be generated. The code generator should not see |
| 41 // these. | 47 // these. |
| 42 class CoercionError extends Coercion { | 48 class CoercionError extends Coercion { |
| 43 CoercionError() : super(null, null); | 49 CoercionError() : super(null, null); |
| 44 } | 50 } |
| 45 | 51 |
| 46 // TODO(jmesserly): this could use some refactoring. These are essentially | 52 // TODO(jmesserly): this could use some refactoring. These are essentially |
| 47 // like ErrorCodes in analyzer, but we're including some details in our message. | 53 // like ErrorCodes in analyzer, but we're including some details in our message. |
| 48 // Analyzer instead has template strings, and replaces '{0}' with the first | 54 // Analyzer instead has template strings, and replaces '{0}' with the first |
| 49 // argument. | 55 // argument. |
|
Leaf
2015/12/04 19:01:11
ditto.
pquitslund
2015/12/04 19:13:33
Done.
| |
| 50 abstract class StaticInfo { | |
| 51 /// AST Node this info is attached to. | |
| 52 AstNode get node; | |
| 53 | |
| 54 // TODO(jmesserly): review the usage of error codes. We probably want our own, | |
| 55 // as well as some DDC specific [ErrorType]s. | |
| 56 ErrorCode toErrorCode(); | |
| 57 | |
| 58 // TODO(jmesserly): what convention to use here? | |
| 59 String get name => 'dev_compiler.$runtimeType'; | |
| 60 | |
| 61 List<Object> get arguments => [node]; | |
| 62 | |
| 63 AnalysisError toAnalysisError() { | |
| 64 int begin = node is AnnotatedNode | |
| 65 ? (node as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset | |
| 66 : node.offset; | |
| 67 int length = node.end - begin; | |
| 68 var source = (node.root as CompilationUnit).element.source; | |
| 69 return new AnalysisError(source, begin, length, toErrorCode(), arguments); | |
| 70 } | |
| 71 } | |
| 72 | |
| 73 /// Implicitly injected expression conversion. | 56 /// Implicitly injected expression conversion. |
| 74 abstract class CoercionInfo extends StaticInfo { | 57 abstract class CoercionInfo extends StaticInfo { |
| 58 static const String _propertyName = 'dev_compiler.src.info.CoercionInfo'; | |
| 59 | |
| 75 final TypeRules rules; | 60 final TypeRules rules; |
| 76 | 61 |
| 77 final Expression node; | 62 final Expression node; |
| 78 | 63 |
| 79 DartType get convertedType; | |
| 80 | |
| 81 CoercionInfo(this.rules, this.node); | 64 CoercionInfo(this.rules, this.node); |
| 82 | 65 |
| 83 DartType get baseType => rules.getStaticType(node); | 66 DartType get baseType => rules.getStaticType(node); |
| 67 DartType get convertedType; | |
| 68 | |
| 69 String get message; | |
| 84 DartType get staticType => convertedType; | 70 DartType get staticType => convertedType; |
| 85 | 71 |
| 86 String get message; | |
| 87 toErrorCode() => new HintCode(name, message); | 72 toErrorCode() => new HintCode(name, message); |
| 88 | 73 |
| 89 static const String _propertyName = 'dev_compiler.src.info.CoercionInfo'; | |
| 90 | |
| 91 /// Gets the coercion info associated with this node. | 74 /// Gets the coercion info associated with this node. |
| 92 static CoercionInfo get(AstNode node) => node.getProperty(_propertyName); | 75 static CoercionInfo get(AstNode node) => node.getProperty(_propertyName); |
| 93 | 76 |
| 94 /// Sets the coercion info associated with this node. | 77 /// Sets the coercion info associated with this node. |
| 95 static CoercionInfo set(AstNode node, CoercionInfo info) { | 78 static CoercionInfo set(AstNode node, CoercionInfo info) { |
| 96 node.setProperty(_propertyName, info); | 79 node.setProperty(_propertyName, info); |
| 97 return info; | 80 return info; |
| 98 } | 81 } |
| 99 } | 82 } |
| 100 | 83 |
| 101 // Base class for all casts from base type to sub type. | |
| 102 abstract class DownCast extends CoercionInfo { | 84 abstract class DownCast extends CoercionInfo { |
| 103 Cast _cast; | 85 Cast _cast; |
| 104 | 86 |
| 105 DownCast._internal(TypeRules rules, Expression expression, this._cast) | 87 DownCast._internal(TypeRules rules, Expression expression, this._cast) |
| 106 : super(rules, expression) { | 88 : super(rules, expression) { |
| 107 assert(_cast.toType != baseType && | 89 assert(_cast.toType != baseType && |
| 108 _cast.fromType == baseType && | 90 _cast.fromType == baseType && |
| 109 (baseType.isDynamic || | 91 (baseType.isDynamic || |
| 110 // Call methods make the following non-redundant | 92 // Call methods make the following non-redundant |
| 111 _cast.toType.isSubtypeOf(baseType) || | 93 _cast.toType.isSubtypeOf(baseType) || |
| 112 baseType.isAssignableTo(_cast.toType))); | 94 baseType.isAssignableTo(_cast.toType))); |
| 113 } | 95 } |
| 114 | 96 |
| 97 @override List<Object> get arguments => [node, baseType, convertedType]; | |
| 98 | |
| 115 Cast get cast => _cast; | 99 Cast get cast => _cast; |
| 116 | 100 |
| 117 DartType get convertedType => _cast.toType; | 101 DartType get convertedType => _cast.toType; |
| 118 | |
| 119 @override List<Object> get arguments => [node, baseType, convertedType]; | |
| 120 @override String get message => '{0} ({1}) will need runtime check ' | 102 @override String get message => '{0} ({1}) will need runtime check ' |
| 121 'to cast to type {2}'; | 103 'to cast to type {2}'; |
| 122 | 104 |
| 123 // Factory to create correct DownCast variant. | 105 // Factory to create correct DownCast variant. |
| 124 static StaticInfo create(TypeRules rules, Expression expression, Cast cast, | 106 static StaticInfo create(TypeRules rules, Expression expression, Cast cast, |
| 125 {String reason}) { | 107 {String reason}) { |
| 126 final fromT = cast.fromType; | 108 final fromT = cast.fromType; |
| 127 final toT = cast.toType; | 109 final toT = cast.toType; |
| 128 | 110 |
| 129 // toT <:_R fromT => to <: fromT | 111 // toT <:_R fromT => to <: fromT |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 var parent = expression.parent; | 169 var parent = expression.parent; |
| 188 if (parent is VariableDeclaration && (parent.initializer == expression)) { | 170 if (parent is VariableDeclaration && (parent.initializer == expression)) { |
| 189 return new AssignmentCast(rules, expression, cast); | 171 return new AssignmentCast(rules, expression, cast); |
| 190 } | 172 } |
| 191 | 173 |
| 192 // Other casts | 174 // Other casts |
| 193 return new DownCastImplicit(rules, expression, cast); | 175 return new DownCastImplicit(rules, expression, cast); |
| 194 } | 176 } |
| 195 } | 177 } |
| 196 | 178 |
| 179 // Base class for all casts from base type to sub type. | |
|
Leaf
2015/12/04 19:01:11
I don't understand how this comment got here at al
pquitslund
2015/12/04 19:13:33
Done.
| |
| 180 class DownCastComposite extends DownCast { | |
| 181 DownCastComposite(TypeRules rules, Expression expression, Cast cast) | |
| 182 : super._internal(rules, expression, cast); | |
| 183 | |
| 184 @override | |
| 185 String get name => 'STRONG_MODE_DOWN_CAST_COMPOSITE'; | |
| 186 | |
| 187 toErrorCode() => new StaticTypeWarningCode(name, message); | |
| 188 } | |
| 189 | |
| 197 // | 190 // |
| 198 // Standard down casts. These casts are implicitly injected by the compiler. | 191 // Standard down casts. These casts are implicitly injected by the compiler. |
| 199 // | 192 // |
| 200 | 193 |
| 201 // A down cast from dynamic to T. | 194 // A down cast from dynamic to T. |
| 202 class DynamicCast extends DownCast { | 195 class DownCastImplicit extends DownCast { |
| 203 DynamicCast(TypeRules rules, Expression expression, Cast cast) | 196 DownCastImplicit(TypeRules rules, Expression expression, Cast cast) |
| 204 : super._internal(rules, expression, cast); | 197 : super._internal(rules, expression, cast); |
| 205 | 198 |
| 199 @override | |
| 200 String get name => 'STRONG_MODE_DOWN_CAST_IMPLICIT'; | |
| 201 | |
| 206 toErrorCode() => new HintCode(name, message); | 202 toErrorCode() => new HintCode(name, message); |
| 207 } | 203 } |
| 208 | 204 |
| 209 // A down cast due to a variable declaration to a ground type. E.g., | 205 // A down cast due to a variable declaration to a ground type. E.g., |
| 210 // T x = expr; | 206 // T x = expr; |
| 211 // where T is ground. We exclude non-ground types as these behave differently | 207 // where T is ground. We exclude non-ground types as these behave differently |
| 212 // compared to standard Dart. | 208 // compared to standard Dart. |
| 213 class AssignmentCast extends DownCast { | 209 class DynamicCast extends DownCast { |
| 214 AssignmentCast(TypeRules rules, Expression expression, Cast cast) | 210 DynamicCast(TypeRules rules, Expression expression, Cast cast) |
| 215 : super._internal(rules, expression, cast); | 211 : super._internal(rules, expression, cast); |
| 216 | 212 |
| 213 @override | |
| 214 String get name => 'STRONG_MODE_DYNAMIC_CAST'; | |
| 215 | |
| 217 toErrorCode() => new HintCode(name, message); | 216 toErrorCode() => new HintCode(name, message); |
| 218 } | 217 } |
| 219 | 218 |
| 220 // | 219 // |
| 221 // Temporary "casts" of allocation sites - literals, constructor invocations, | 220 // Temporary "casts" of allocation sites - literals, constructor invocations, |
| 222 // and closures. These should be handled by contextual inference. In most | 221 // and closures. These should be handled by contextual inference. In most |
| 223 // cases, inference will be sufficient, though in some it may unmask an actual | 222 // cases, inference will be sufficient, though in some it may unmask an actual |
| 224 // error: e.g., | 223 // error: e.g., |
| 225 // List<int> l = [1, 2, 3]; // Inference succeeds | 224 // List<int> l = [1, 2, 3]; // Inference succeeds |
| 226 // List<String> l = [1, 2, 3]; // Inference reveals static type error | 225 // List<String> l = [1, 2, 3]; // Inference reveals static type error |
| 227 // We're marking all as warnings for now. | 226 // We're marking all as warnings for now. |
| 228 // | 227 // |
| 229 // TODO(vsm,leafp): Remove this. | 228 // TODO(vsm,leafp): Remove this. |
| 230 class UninferredClosure extends DownCast { | 229 class DynamicInvoke extends CoercionInfo { |
| 231 UninferredClosure(TypeRules rules, FunctionExpression expression, Cast cast) | 230 static const String _propertyName = 'dev_compiler.src.info.DynamicInvoke'; |
| 232 : super._internal(rules, expression, cast); | |
| 233 | 231 |
| 234 toErrorCode() => new StaticTypeWarningCode(name, message); | 232 DynamicInvoke(TypeRules rules, Expression expression) |
| 233 : super(rules, expression); | |
| 234 DartType get convertedType => rules.provider.dynamicType; | |
| 235 String get message => '{0} requires dynamic invoke'; | |
| 236 | |
| 237 @override | |
| 238 String get name => 'STRONG_MODE_DYNAMIC_INVOKE'; | |
| 239 | |
| 240 toErrorCode() => new HintCode(name, message); | |
| 241 | |
| 242 /// Whether this [node] is the target of a dynamic operation. | |
| 243 static bool get(AstNode node) { | |
| 244 var value = node.getProperty(_propertyName); | |
| 245 return value != null ? value : false; | |
| 246 } | |
| 247 | |
| 248 /// Sets whether this node is the target of a dynamic operation. | |
| 249 static bool set(AstNode node, bool value) { | |
| 250 // Free the storage for things that aren't dynamic. | |
| 251 if (value == false) value = null; | |
| 252 node.setProperty(_propertyName, value); | |
| 253 return value; | |
| 254 } | |
| 235 } | 255 } |
| 236 | 256 |
| 237 // | 257 // |
| 238 // Implicit down casts. These are only injected by the compiler by flag. | 258 // Implicit down casts. These are only injected by the compiler by flag. |
| 239 // | 259 // |
| 240 | 260 |
| 241 // A down cast to a non-ground type. These behave differently from standard | 261 // A down cast to a non-ground type. These behave differently from standard |
| 242 // Dart and may be more likely to fail at runtime. | 262 // Dart and may be more likely to fail at runtime. |
| 243 class DownCastComposite extends DownCast { | 263 class Identity extends Coercion { |
| 244 DownCastComposite(TypeRules rules, Expression expression, Cast cast) | 264 Identity(DartType fromType) : super(fromType, fromType); |
| 245 : super._internal(rules, expression, cast); | |
| 246 | |
| 247 toErrorCode() => new StaticTypeWarningCode(name, message); | |
| 248 } | 265 } |
| 249 | 266 |
| 250 // A down cast to a non-ground type. These behave differently from standard | 267 // A down cast to a non-ground type. These behave differently from standard |
| 251 // Dart and may be more likely to fail at runtime. | 268 // Dart and may be more likely to fail at runtime. |
| 252 class DownCastImplicit extends DownCast { | |
| 253 DownCastImplicit(TypeRules rules, Expression expression, Cast cast) | |
| 254 : super._internal(rules, expression, cast); | |
| 255 | |
| 256 toErrorCode() => new HintCode(name, message); | |
| 257 } | |
| 258 | |
| 259 // An inferred type for the wrapped expression, which may need to be | |
| 260 // reified into the term | |
| 261 abstract class InferredTypeBase extends CoercionInfo { | |
| 262 final DartType _type; | |
| 263 | |
| 264 InferredTypeBase._internal(TypeRules rules, Expression expression, this._type) | |
| 265 : super(rules, expression); | |
| 266 | |
| 267 DartType get type => _type; | |
| 268 DartType get convertedType => type; | |
| 269 @override String get message => '{0} has inferred type {1}'; | |
| 270 @override List get arguments => [node, type]; | |
| 271 | |
| 272 toErrorCode() => new HintCode(name, message); | |
| 273 } | |
| 274 | |
| 275 // Standard / unspecialized inferred type | |
| 276 class InferredType extends InferredTypeBase { | 269 class InferredType extends InferredTypeBase { |
| 277 InferredType(TypeRules rules, Expression expression, DartType type) | 270 InferredType(TypeRules rules, Expression expression, DartType type) |
| 278 : super._internal(rules, expression, type); | 271 : super._internal(rules, expression, type); |
| 279 | 272 |
| 280 // Factory to create correct InferredType variant. | 273 // Factory to create correct InferredType variant. |
| 274 @override | |
| 275 String get name => 'STRONG_MODE_INFERRED_TYPE'; | |
| 276 | |
| 281 static InferredTypeBase create( | 277 static InferredTypeBase create( |
| 282 TypeRules rules, Expression expression, DartType type) { | 278 TypeRules rules, Expression expression, DartType type) { |
| 283 // Specialized inference: | 279 // Specialized inference: |
| 284 if (expression is Literal) { | 280 if (expression is Literal) { |
| 285 return new InferredTypeLiteral(rules, expression, type); | 281 return new InferredTypeLiteral(rules, expression, type); |
| 286 } | 282 } |
| 287 if (expression is InstanceCreationExpression) { | 283 if (expression is InstanceCreationExpression) { |
| 288 return new InferredTypeAllocation(rules, expression, type); | 284 return new InferredTypeAllocation(rules, expression, type); |
| 289 } | 285 } |
| 290 if (expression is FunctionExpression) { | 286 if (expression is FunctionExpression) { |
| 291 return new InferredTypeClosure(rules, expression, type); | 287 return new InferredTypeClosure(rules, expression, type); |
| 292 } | 288 } |
| 293 return new InferredType(rules, expression, type); | 289 return new InferredType(rules, expression, type); |
| 294 } | 290 } |
| 295 } | 291 } |
| 296 | 292 |
| 297 // An infered type for a literal expression. | 293 // An inferred type for the wrapped expression, which may need to be |
| 298 class InferredTypeLiteral extends InferredTypeBase { | 294 // reified into the term |
| 299 InferredTypeLiteral(TypeRules rules, Expression expression, DartType type) | |
| 300 : super._internal(rules, expression, type); | |
| 301 } | |
| 302 | |
| 303 // An inferred type for a non-literal allocation site. | |
| 304 class InferredTypeAllocation extends InferredTypeBase { | 295 class InferredTypeAllocation extends InferredTypeBase { |
| 305 InferredTypeAllocation(TypeRules rules, Expression expression, DartType type) | 296 InferredTypeAllocation(TypeRules rules, Expression expression, DartType type) |
| 306 : super._internal(rules, expression, type); | 297 : super._internal(rules, expression, type); |
| 298 | |
| 299 @override | |
| 300 String get name => 'STRONG_MODE_INFERRED_TYPE_ALLOCATION'; | |
| 307 } | 301 } |
| 308 | 302 |
| 309 // An inferred type for a closure expression | 303 // Standard / unspecialized inferred type |
| 310 class InferredTypeClosure extends InferredTypeBase { | 304 abstract class InferredTypeBase extends CoercionInfo { |
| 311 InferredTypeClosure(TypeRules rules, Expression expression, DartType type) | 305 final DartType _type; |
| 312 : super._internal(rules, expression, type); | |
| 313 } | |
| 314 | 306 |
| 315 class DynamicInvoke extends CoercionInfo { | 307 InferredTypeBase._internal(TypeRules rules, Expression expression, this._type) |
| 316 DynamicInvoke(TypeRules rules, Expression expression) | |
| 317 : super(rules, expression); | 308 : super(rules, expression); |
| 318 | 309 |
| 319 DartType get convertedType => rules.provider.dynamicType; | 310 @override List get arguments => [node, type]; |
| 320 String get message => '{0} requires dynamic invoke'; | 311 DartType get convertedType => type; |
| 321 toErrorCode() => new HintCode(name, message); | 312 @override String get message => '{0} has inferred type {1}'; |
| 322 | 313 DartType get type => _type; |
| 323 static const String _propertyName = 'dev_compiler.src.info.DynamicInvoke'; | |
| 324 | |
| 325 /// Whether this [node] is the target of a dynamic operation. | |
| 326 static bool get(AstNode node) { | |
| 327 var value = node.getProperty(_propertyName); | |
| 328 return value != null ? value : false; | |
| 329 } | |
| 330 | |
| 331 /// Sets whether this node is the target of a dynamic operation. | |
| 332 static bool set(AstNode node, bool value) { | |
| 333 // Free the storage for things that aren't dynamic. | |
| 334 if (value == false) value = null; | |
| 335 node.setProperty(_propertyName, value); | |
| 336 return value; | |
| 337 } | |
| 338 } | |
| 339 | |
| 340 abstract class StaticError extends StaticInfo { | |
| 341 final AstNode node; | |
| 342 | |
| 343 StaticError(this.node); | |
| 344 | |
| 345 String get message; | |
| 346 | |
| 347 toErrorCode() => new CompileTimeErrorCode(name, message); | |
| 348 } | |
| 349 | |
| 350 class StaticTypeError extends StaticError { | |
| 351 final DartType baseType; | |
| 352 final DartType expectedType; | |
| 353 String reason = null; | |
| 354 | |
| 355 StaticTypeError(TypeRules rules, Expression expression, this.expectedType, | |
| 356 {this.reason}) | |
| 357 : baseType = rules.getStaticType(expression), | |
| 358 super(expression); | |
| 359 | |
| 360 @override List<Object> get arguments => [node, baseType, expectedType]; | |
| 361 @override String get message => | |
| 362 'Type check failed: {0} ({1}) is not of type {2}' + | |
| 363 ((reason == null) ? '' : ' because $reason'); | |
| 364 } | |
| 365 | |
| 366 class InvalidVariableDeclaration extends StaticError { | |
| 367 final DartType expectedType; | |
| 368 | |
| 369 InvalidVariableDeclaration( | |
| 370 TypeRules rules, AstNode declaration, this.expectedType) | |
| 371 : super(declaration); | |
| 372 | |
| 373 @override List<Object> get arguments => [expectedType]; | |
| 374 @override String get message => 'Type check failed: null is not of type {0}'; | |
| 375 } | |
| 376 | |
| 377 class InvalidParameterDeclaration extends StaticError { | |
| 378 final DartType expectedType; | |
| 379 | |
| 380 InvalidParameterDeclaration( | |
| 381 TypeRules rules, FormalParameter declaration, this.expectedType) | |
| 382 : super(declaration); | |
| 383 | |
| 384 @override List<Object> get arguments => [node, expectedType]; | |
| 385 @override String get message => 'Type check failed: {0} is not of type {1}'; | |
| 386 } | |
| 387 | |
| 388 class NonGroundTypeCheckInfo extends StaticInfo { | |
| 389 final DartType type; | |
| 390 final AstNode node; | |
| 391 | |
| 392 NonGroundTypeCheckInfo(this.node, this.type) { | |
| 393 assert(node is IsExpression || node is AsExpression); | |
| 394 } | |
| 395 | |
| 396 @override List<Object> get arguments => [type]; | |
| 397 String get message => | |
| 398 "Runtime check on non-ground type {0} may throw StrongModeError"; | |
| 399 | 314 |
| 400 toErrorCode() => new HintCode(name, message); | 315 toErrorCode() => new HintCode(name, message); |
| 401 } | 316 } |
| 402 | 317 |
| 403 // Invalid override of an instance member of a class. | 318 // An inferred type for a literal expression. |
| 319 class InferredTypeClosure extends InferredTypeBase { | |
| 320 InferredTypeClosure(TypeRules rules, Expression expression, DartType type) | |
| 321 : super._internal(rules, expression, type); | |
| 322 | |
| 323 @override | |
| 324 String get name => 'STRONG_MODE_INFERRED_TYPE_CLOSURE'; | |
| 325 } | |
| 326 | |
| 327 // An inferred type for a non-literal allocation site. | |
| 328 class InferredTypeLiteral extends InferredTypeBase { | |
| 329 InferredTypeLiteral(TypeRules rules, Expression expression, DartType type) | |
| 330 : super._internal(rules, expression, type); | |
| 331 | |
| 332 @override | |
| 333 String get name => 'STRONG_MODE_INFERRED_TYPE_LITERAL'; | |
| 334 } | |
| 335 | |
| 336 // An inferred type for a closure expression | |
| 337 class InvalidFieldOverride extends InvalidOverride { | |
| 338 InvalidFieldOverride(AstNode node, ExecutableElement element, | |
| 339 InterfaceType base, DartType subType, DartType baseType) | |
| 340 : super(node, element, base, subType, baseType); | |
| 341 | |
| 342 String get message => 'Field declaration {3}.{1} cannot be ' | |
| 343 'overridden in {0}.'; | |
| 344 | |
| 345 @override | |
| 346 String get name => 'STRONG_MODE_INVALID_FIELD_OVERRIDE'; | |
| 347 } | |
| 348 | |
| 349 class InvalidMethodOverride extends InvalidOverride { | |
| 350 InvalidMethodOverride(AstNode node, ExecutableElement element, | |
| 351 InterfaceType base, FunctionType subType, FunctionType baseType) | |
| 352 : super(node, element, base, subType, baseType); | |
| 353 | |
| 354 String get message => _messageHelper('Invalid override'); | |
| 355 | |
| 356 @override | |
| 357 String get name => 'STRONG_MODE_INVALID_METHOD_OVERRIDE'; | |
| 358 } | |
| 359 | |
| 404 abstract class InvalidOverride extends StaticError { | 360 abstract class InvalidOverride extends StaticError { |
| 405 /// Member declaration with the invalid override. | 361 /// Member declaration with the invalid override. |
| 406 final ExecutableElement element; | 362 final ExecutableElement element; |
| 407 | 363 |
| 408 /// Type (class or interface) that provides the base declaration. | 364 /// Type (class or interface) that provides the base declaration. |
| 409 final InterfaceType base; | 365 final InterfaceType base; |
| 410 | 366 |
| 411 /// Actual type of the overridden member. | 367 /// Actual type of the overridden member. |
| 412 final DartType subType; | 368 final DartType subType; |
| 413 | 369 |
| 414 /// Actual type of the base member. | 370 /// Actual type of the base member. |
| 415 final DartType baseType; | 371 final DartType baseType; |
| 416 | 372 |
| 417 /// Whether the error comes from combining a base class and an interface | 373 /// Whether the error comes from combining a base class and an interface |
| 418 final bool fromBaseClass; | 374 final bool fromBaseClass; |
| 419 | 375 |
| 420 /// Whether the error comes from a mixin (either overriding a base class or an | 376 /// Whether the error comes from a mixin (either overriding a base class or an |
| 421 /// interface declaration). | 377 /// interface declaration). |
| 422 final bool fromMixin; | 378 final bool fromMixin; |
| 423 | 379 |
| 424 InvalidOverride( | 380 InvalidOverride( |
| 425 AstNode node, this.element, this.base, this.subType, this.baseType) | 381 AstNode node, this.element, this.base, this.subType, this.baseType) |
| 426 : fromBaseClass = node is ExtendsClause, | 382 : fromBaseClass = node is ExtendsClause, |
| 427 fromMixin = node.parent is WithClause, | 383 fromMixin = node.parent is WithClause, |
| 428 super(node); | 384 super(node); |
| 429 | 385 |
| 430 ClassElement get parent => element.enclosingElement; | |
| 431 | |
| 432 @override List<Object> get arguments => | 386 @override List<Object> get arguments => |
| 433 [parent.name, element.name, subType, base, baseType]; | 387 [parent.name, element.name, subType, base, baseType]; |
| 434 | 388 |
| 389 ClassElement get parent => element.enclosingElement; | |
| 390 | |
| 435 String _messageHelper(String errorName) { | 391 String _messageHelper(String errorName) { |
| 436 var lcErrorName = errorName.toLowerCase(); | 392 var lcErrorName = errorName.toLowerCase(); |
| 437 var intro = fromBaseClass | 393 var intro = fromBaseClass |
| 438 ? 'Base class introduces an $lcErrorName' | 394 ? 'Base class introduces an $lcErrorName' |
| 439 : (fromMixin ? 'Mixin introduces an $lcErrorName' : errorName); | 395 : (fromMixin ? 'Mixin introduces an $lcErrorName' : errorName); |
| 440 return '$intro. The type of {0}.{1} ({2}) is not a ' | 396 return '$intro. The type of {0}.{1} ({2}) is not a ' |
| 441 'subtype of {3}.{1} ({4}).'; | 397 'subtype of {3}.{1} ({4}).'; |
| 442 } | 398 } |
| 443 } | 399 } |
| 444 | 400 |
| 445 // Invalid override due to incompatible type. I.e., the overridden signature | 401 class InvalidParameterDeclaration extends StaticError { |
| 446 // is not compatible with the original. | 402 final DartType expectedType; |
| 447 class InvalidMethodOverride extends InvalidOverride { | |
| 448 InvalidMethodOverride(AstNode node, ExecutableElement element, | |
| 449 InterfaceType base, FunctionType subType, FunctionType baseType) | |
| 450 : super(node, element, base, subType, baseType); | |
| 451 | 403 |
| 452 String get message => _messageHelper('Invalid override'); | 404 InvalidParameterDeclaration( |
| 453 } | 405 TypeRules rules, FormalParameter declaration, this.expectedType) |
| 406 : super(declaration); | |
| 454 | 407 |
| 455 class InvalidFieldOverride extends InvalidOverride { | 408 @override List<Object> get arguments => [node, expectedType]; |
| 456 InvalidFieldOverride(AstNode node, ExecutableElement element, | 409 @override String get message => 'Type check failed: {0} is not of type {1}'; |
| 457 InterfaceType base, DartType subType, DartType baseType) | 410 @override |
| 458 : super(node, element, base, subType, baseType); | 411 String get name => 'STRONG_MODE_INVALID_PARAMETER_DECLARATION'; |
| 459 | |
| 460 String get message => 'Field declaration {3}.{1} cannot be ' | |
| 461 'overridden in {0}.'; | |
| 462 } | 412 } |
| 463 | 413 |
| 464 /// Dart constructors have one weird quirk, illustrated with this example: | 414 /// Dart constructors have one weird quirk, illustrated with this example: |
| 465 /// | 415 /// |
| 466 /// class Base { | 416 /// class Base { |
| 467 /// var x; | 417 /// var x; |
| 468 /// Base() : x = print('Base.1') { | 418 /// Base() : x = print('Base.1') { |
| 469 /// print('Base.2'); | 419 /// print('Base.2'); |
| 470 /// } | 420 /// } |
| 471 /// } | 421 /// } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 488 /// | 438 /// |
| 489 /// Better to have `super` at the end, as required by the Dart style guide: | 439 /// Better to have `super` at the end, as required by the Dart style guide: |
| 490 /// <http://goo.gl/q1T4BB> | 440 /// <http://goo.gl/q1T4BB> |
| 491 /// | 441 /// |
| 492 /// For now this is the only pattern we support. | 442 /// For now this is the only pattern we support. |
| 493 class InvalidSuperInvocation extends StaticError { | 443 class InvalidSuperInvocation extends StaticError { |
| 494 InvalidSuperInvocation(SuperConstructorInvocation node) : super(node); | 444 InvalidSuperInvocation(SuperConstructorInvocation node) : super(node); |
| 495 | 445 |
| 496 @override String get message => "super call must be last in an initializer " | 446 @override String get message => "super call must be last in an initializer " |
| 497 "list (see http://goo.gl/q1T4BB): {0}"; | 447 "list (see http://goo.gl/q1T4BB): {0}"; |
| 448 | |
| 449 @override | |
| 450 String get name => 'STRONG_MODE_INVALID_SUPER_INVOCATION'; | |
| 498 } | 451 } |
| 452 | |
| 453 class InvalidVariableDeclaration extends StaticError { | |
| 454 final DartType expectedType; | |
| 455 | |
| 456 InvalidVariableDeclaration( | |
| 457 TypeRules rules, AstNode declaration, this.expectedType) | |
| 458 : super(declaration); | |
| 459 | |
| 460 @override List<Object> get arguments => [expectedType]; | |
| 461 @override String get message => 'Type check failed: null is not of type {0}'; | |
| 462 | |
| 463 @override | |
| 464 String get name => 'STRONG_MODE_INVALID_VARIABLE_DECLARATION'; | |
| 465 } | |
| 466 | |
| 467 class NonGroundTypeCheckInfo extends StaticInfo { | |
| 468 final DartType type; | |
| 469 final AstNode node; | |
| 470 | |
| 471 NonGroundTypeCheckInfo(this.node, this.type) { | |
| 472 assert(node is IsExpression || node is AsExpression); | |
| 473 } | |
| 474 | |
| 475 @override List<Object> get arguments => [type]; | |
| 476 String get message => | |
| 477 "Runtime check on non-ground type {0} may throw StrongModeError"; | |
| 478 | |
| 479 @override | |
| 480 String get name => 'STRONG_MODE_NON_GROUND_TYPE_CHECK_INFO'; | |
| 481 | |
| 482 toErrorCode() => new HintCode(name, message); | |
| 483 } | |
| 484 | |
| 485 // Invalid override of an instance member of a class. | |
| 486 abstract class StaticError extends StaticInfo { | |
| 487 final AstNode node; | |
| 488 | |
| 489 StaticError(this.node); | |
| 490 | |
| 491 String get message; | |
| 492 | |
| 493 toErrorCode() => new CompileTimeErrorCode(name, message); | |
| 494 } | |
| 495 | |
| 496 // Invalid override due to incompatible type. I.e., the overridden signature | |
| 497 // is not compatible with the original. | |
| 498 abstract class StaticInfo { | |
| 499 List<Object> get arguments => [node]; | |
| 500 | |
| 501 // TODO(jmesserly): review the usage of error codes. We probably want our own, | |
| 502 // as well as some DDC specific [ErrorType]s. | |
| 503 String get name; | |
| 504 | |
| 505 /// AST Node this info is attached to. | |
| 506 AstNode get node; | |
| 507 | |
| 508 AnalysisError toAnalysisError() { | |
| 509 int begin = node is AnnotatedNode | |
| 510 ? (node as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset | |
| 511 : node.offset; | |
| 512 int length = node.end - begin; | |
| 513 var source = (node.root as CompilationUnit).element.source; | |
| 514 return new AnalysisError(source, begin, length, toErrorCode(), arguments); | |
| 515 } | |
| 516 | |
| 517 ErrorCode toErrorCode(); | |
| 518 } | |
| 519 | |
| 520 class StaticTypeError extends StaticError { | |
| 521 final DartType baseType; | |
| 522 final DartType expectedType; | |
| 523 String reason = null; | |
| 524 | |
| 525 StaticTypeError(TypeRules rules, Expression expression, this.expectedType, | |
| 526 {this.reason}) | |
| 527 : baseType = rules.getStaticType(expression), | |
| 528 super(expression); | |
| 529 | |
| 530 @override List<Object> get arguments => [node, baseType, expectedType]; | |
| 531 @override String get message => | |
| 532 'Type check failed: {0} ({1}) is not of type {2}' + | |
| 533 ((reason == null) ? '' : ' because $reason'); | |
| 534 | |
| 535 @override | |
| 536 String get name => 'STRONG_MODE_STATIC_TYPE_ERROR'; | |
| 537 } | |
| 538 | |
| 539 class UninferredClosure extends DownCast { | |
| 540 UninferredClosure(TypeRules rules, FunctionExpression expression, Cast cast) | |
| 541 : super._internal(rules, expression, cast); | |
| 542 | |
| 543 @override | |
| 544 String get name => 'STRONG_MODE_UNINFERRED_CLOSURE'; | |
| 545 | |
| 546 toErrorCode() => new StaticTypeWarningCode(name, message); | |
| 547 } | |
| OLD | NEW |