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