| 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/dart/ast/ast.dart'; |
| 11 import 'package:analyzer/dart/element/element.dart'; | 12 import 'package:analyzer/dart/element/element.dart'; |
| 12 import 'package:analyzer/dart/element/type.dart'; | 13 import 'package:analyzer/dart/element/type.dart'; |
| 13 import 'package:analyzer/src/dart/element/type.dart'; | 14 import 'package:analyzer/src/dart/element/type.dart'; |
| 14 import 'package:analyzer/src/generated/ast.dart'; | |
| 15 import 'package:analyzer/src/generated/error.dart'; | 15 import 'package:analyzer/src/generated/error.dart'; |
| 16 import 'package:analyzer/src/generated/type_system.dart'; | 16 import 'package:analyzer/src/generated/type_system.dart'; |
| 17 | 17 |
| 18 // A down cast due to a variable declaration to a ground type. E.g., | 18 // A down cast due to a variable declaration to a ground type. E.g., |
| 19 // T x = expr; | 19 // T x = expr; |
| 20 // where T is ground. We exclude non-ground types as these behave differently | 20 // where T is ground. We exclude non-ground types as these behave differently |
| 21 // compared to standard Dart. | 21 // compared to standard Dart. |
| 22 class AssignmentCast extends DownCast { | 22 class AssignmentCast extends DownCast { |
| 23 AssignmentCast(TypeSystem rules, Expression expression, Cast cast) | 23 AssignmentCast(TypeSystem rules, Expression expression, Cast cast) |
| 24 : super._internal(rules, expression, cast); | 24 : super._internal(rules, expression, cast); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 DownCast._internal(TypeSystem rules, Expression expression, this._cast) | 88 DownCast._internal(TypeSystem rules, Expression expression, this._cast) |
| 89 : super(rules, expression) { | 89 : super(rules, expression) { |
| 90 assert(_cast.toType != baseType && | 90 assert(_cast.toType != baseType && |
| 91 _cast.fromType == baseType && | 91 _cast.fromType == baseType && |
| 92 (baseType.isDynamic || | 92 (baseType.isDynamic || |
| 93 // Call methods make the following non-redundant | 93 // Call methods make the following non-redundant |
| 94 _cast.toType.isSubtypeOf(baseType) || | 94 _cast.toType.isSubtypeOf(baseType) || |
| 95 baseType.isAssignableTo(_cast.toType))); | 95 baseType.isAssignableTo(_cast.toType))); |
| 96 } | 96 } |
| 97 | 97 |
| 98 @override List<Object> get arguments => [node, baseType, convertedType]; | 98 @override |
| 99 List<Object> get arguments => [node, baseType, convertedType]; |
| 99 | 100 |
| 100 Cast get cast => _cast; | 101 Cast get cast => _cast; |
| 101 | 102 |
| 102 DartType get convertedType => _cast.toType; | 103 DartType get convertedType => _cast.toType; |
| 103 @override String get message => '{0} ({1}) will need runtime check ' | 104 @override |
| 105 String get message => '{0} ({1}) will need runtime check ' |
| 104 'to cast to type {2}'; | 106 'to cast to type {2}'; |
| 105 | 107 |
| 106 // Factory to create correct DownCast variant. | 108 // Factory to create correct DownCast variant. |
| 107 static StaticInfo create( | 109 static StaticInfo create( |
| 108 StrongTypeSystemImpl rules, Expression expression, Cast cast, | 110 StrongTypeSystemImpl rules, Expression expression, Cast cast, |
| 109 {String reason}) { | 111 {String reason}) { |
| 110 final fromT = cast.fromType; | 112 final fromT = cast.fromType; |
| 111 final toT = cast.toType; | 113 final toT = cast.toType; |
| 112 | 114 |
| 113 // toT <:_R fromT => to <: fromT | 115 // toT <:_R fromT => to <: fromT |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 | 290 |
| 289 // An inferred type for the wrapped expression, which may need to be | 291 // An inferred type for the wrapped expression, which may need to be |
| 290 // reified into the term | 292 // reified into the term |
| 291 abstract class InferredTypeBase extends CoercionInfo { | 293 abstract class InferredTypeBase extends CoercionInfo { |
| 292 final DartType _type; | 294 final DartType _type; |
| 293 | 295 |
| 294 InferredTypeBase._internal( | 296 InferredTypeBase._internal( |
| 295 TypeSystem rules, Expression expression, this._type) | 297 TypeSystem rules, Expression expression, this._type) |
| 296 : super(rules, expression); | 298 : super(rules, expression); |
| 297 | 299 |
| 298 @override List get arguments => [node, type]; | 300 @override |
| 301 List get arguments => [node, type]; |
| 299 DartType get convertedType => type; | 302 DartType get convertedType => type; |
| 300 @override String get message => '{0} has inferred type {1}'; | 303 @override |
| 304 String get message => '{0} has inferred type {1}'; |
| 301 DartType get type => _type; | 305 DartType get type => _type; |
| 302 | 306 |
| 303 toErrorCode() => new HintCode(name, message); | 307 toErrorCode() => new HintCode(name, message); |
| 304 } | 308 } |
| 305 | 309 |
| 306 // An inferred type for a closure expression | 310 // An inferred type for a closure expression |
| 307 class InferredTypeClosure extends InferredTypeBase { | 311 class InferredTypeClosure extends InferredTypeBase { |
| 308 InferredTypeClosure(TypeSystem rules, Expression expression, DartType type) | 312 InferredTypeClosure(TypeSystem rules, Expression expression, DartType type) |
| 309 : super._internal(rules, expression, type); | 313 : super._internal(rules, expression, type); |
| 310 | 314 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 /// Whether the error comes from a mixin (either overriding a base class or an | 370 /// Whether the error comes from a mixin (either overriding a base class or an |
| 367 /// interface declaration). | 371 /// interface declaration). |
| 368 final bool fromMixin; | 372 final bool fromMixin; |
| 369 | 373 |
| 370 InvalidOverride( | 374 InvalidOverride( |
| 371 AstNode node, this.element, this.base, this.subType, this.baseType) | 375 AstNode node, this.element, this.base, this.subType, this.baseType) |
| 372 : fromBaseClass = node is ExtendsClause, | 376 : fromBaseClass = node is ExtendsClause, |
| 373 fromMixin = node.parent is WithClause, | 377 fromMixin = node.parent is WithClause, |
| 374 super(node); | 378 super(node); |
| 375 | 379 |
| 376 @override List<Object> get arguments => | 380 @override |
| 381 List<Object> get arguments => |
| 377 [parent.name, element.name, subType, base, baseType]; | 382 [parent.name, element.name, subType, base, baseType]; |
| 378 | 383 |
| 379 ClassElement get parent => element.enclosingElement; | 384 ClassElement get parent => element.enclosingElement; |
| 380 | 385 |
| 381 String _messageHelper(String errorName) { | 386 String _messageHelper(String errorName) { |
| 382 var lcErrorName = errorName.toLowerCase(); | 387 var lcErrorName = errorName.toLowerCase(); |
| 383 var intro = fromBaseClass | 388 var intro = fromBaseClass |
| 384 ? 'Base class introduces an $lcErrorName' | 389 ? 'Base class introduces an $lcErrorName' |
| 385 : (fromMixin ? 'Mixin introduces an $lcErrorName' : errorName); | 390 : (fromMixin ? 'Mixin introduces an $lcErrorName' : errorName); |
| 386 return '$intro. The type of {0}.{1} ({2}) is not a ' | 391 return '$intro. The type of {0}.{1} ({2}) is not a ' |
| 387 'subtype of {3}.{1} ({4}).'; | 392 'subtype of {3}.{1} ({4}).'; |
| 388 } | 393 } |
| 389 } | 394 } |
| 390 | 395 |
| 391 class InvalidParameterDeclaration extends StaticError { | 396 class InvalidParameterDeclaration extends StaticError { |
| 392 final DartType expectedType; | 397 final DartType expectedType; |
| 393 | 398 |
| 394 InvalidParameterDeclaration( | 399 InvalidParameterDeclaration( |
| 395 TypeSystem rules, FormalParameter declaration, this.expectedType) | 400 TypeSystem rules, FormalParameter declaration, this.expectedType) |
| 396 : super(declaration); | 401 : super(declaration); |
| 397 | 402 |
| 398 @override List<Object> get arguments => [node, expectedType]; | 403 @override |
| 399 @override String get message => 'Type check failed: {0} is not of type {1}'; | 404 List<Object> get arguments => [node, expectedType]; |
| 405 @override |
| 406 String get message => 'Type check failed: {0} is not of type {1}'; |
| 400 @override | 407 @override |
| 401 String get name => 'STRONG_MODE_INVALID_PARAMETER_DECLARATION'; | 408 String get name => 'STRONG_MODE_INVALID_PARAMETER_DECLARATION'; |
| 402 } | 409 } |
| 403 | 410 |
| 404 /// Dart constructors have one weird quirk, illustrated with this example: | 411 /// Dart constructors have one weird quirk, illustrated with this example: |
| 405 /// | 412 /// |
| 406 /// class Base { | 413 /// class Base { |
| 407 /// var x; | 414 /// var x; |
| 408 /// Base() : x = print('Base.1') { | 415 /// Base() : x = print('Base.1') { |
| 409 /// print('Base.2'); | 416 /// print('Base.2'); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 426 /// immediately after super initializers. Normally this isn't observable, but it | 433 /// immediately after super initializers. Normally this isn't observable, but it |
| 427 /// could be if initializers have side effects. | 434 /// could be if initializers have side effects. |
| 428 /// | 435 /// |
| 429 /// Better to have `super` at the end, as required by the Dart style guide: | 436 /// Better to have `super` at the end, as required by the Dart style guide: |
| 430 /// <http://goo.gl/q1T4BB> | 437 /// <http://goo.gl/q1T4BB> |
| 431 /// | 438 /// |
| 432 /// For now this is the only pattern we support. | 439 /// For now this is the only pattern we support. |
| 433 class InvalidSuperInvocation extends StaticError { | 440 class InvalidSuperInvocation extends StaticError { |
| 434 InvalidSuperInvocation(SuperConstructorInvocation node) : super(node); | 441 InvalidSuperInvocation(SuperConstructorInvocation node) : super(node); |
| 435 | 442 |
| 436 @override String get message => "super call must be last in an initializer " | 443 @override |
| 444 String get message => "super call must be last in an initializer " |
| 437 "list (see http://goo.gl/q1T4BB): {0}"; | 445 "list (see http://goo.gl/q1T4BB): {0}"; |
| 438 | 446 |
| 439 @override | 447 @override |
| 440 String get name => 'STRONG_MODE_INVALID_SUPER_INVOCATION'; | 448 String get name => 'STRONG_MODE_INVALID_SUPER_INVOCATION'; |
| 441 } | 449 } |
| 442 | 450 |
| 443 class InvalidVariableDeclaration extends StaticError { | 451 class InvalidVariableDeclaration extends StaticError { |
| 444 final DartType expectedType; | 452 final DartType expectedType; |
| 445 | 453 |
| 446 InvalidVariableDeclaration( | 454 InvalidVariableDeclaration( |
| 447 TypeSystem rules, AstNode declaration, this.expectedType) | 455 TypeSystem rules, AstNode declaration, this.expectedType) |
| 448 : super(declaration); | 456 : super(declaration); |
| 449 | 457 |
| 450 @override List<Object> get arguments => [expectedType]; | 458 @override |
| 451 @override String get message => 'Type check failed: null is not of type {0}'; | 459 List<Object> get arguments => [expectedType]; |
| 460 @override |
| 461 String get message => 'Type check failed: null is not of type {0}'; |
| 452 | 462 |
| 453 @override | 463 @override |
| 454 String get name => 'STRONG_MODE_INVALID_VARIABLE_DECLARATION'; | 464 String get name => 'STRONG_MODE_INVALID_VARIABLE_DECLARATION'; |
| 455 } | 465 } |
| 456 | 466 |
| 457 class NonGroundTypeCheckInfo extends StaticInfo { | 467 class NonGroundTypeCheckInfo extends StaticInfo { |
| 458 final DartType type; | 468 final DartType type; |
| 459 final AstNode node; | 469 final AstNode node; |
| 460 | 470 |
| 461 NonGroundTypeCheckInfo(this.node, this.type) { | 471 NonGroundTypeCheckInfo(this.node, this.type) { |
| 462 assert(node is IsExpression || node is AsExpression); | 472 assert(node is IsExpression || node is AsExpression); |
| 463 } | 473 } |
| 464 | 474 |
| 465 @override List<Object> get arguments => [type]; | 475 @override |
| 476 List<Object> get arguments => [type]; |
| 466 String get message => | 477 String get message => |
| 467 "Runtime check on non-ground type {0} may throw StrongModeError"; | 478 "Runtime check on non-ground type {0} may throw StrongModeError"; |
| 468 | 479 |
| 469 @override | 480 @override |
| 470 String get name => 'STRONG_MODE_NON_GROUND_TYPE_CHECK_INFO'; | 481 String get name => 'STRONG_MODE_NON_GROUND_TYPE_CHECK_INFO'; |
| 471 | 482 |
| 472 toErrorCode() => new HintCode(name, message); | 483 toErrorCode() => new HintCode(name, message); |
| 473 } | 484 } |
| 474 | 485 |
| 475 abstract class StaticError extends StaticInfo { | 486 abstract class StaticError extends StaticInfo { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 class StaticTypeError extends StaticError { | 548 class StaticTypeError extends StaticError { |
| 538 final DartType baseType; | 549 final DartType baseType; |
| 539 final DartType expectedType; | 550 final DartType expectedType; |
| 540 String reason = null; | 551 String reason = null; |
| 541 | 552 |
| 542 StaticTypeError(TypeSystem rules, Expression expression, this.expectedType, | 553 StaticTypeError(TypeSystem rules, Expression expression, this.expectedType, |
| 543 {this.reason}) | 554 {this.reason}) |
| 544 : baseType = expression.staticType ?? DynamicTypeImpl.instance, | 555 : baseType = expression.staticType ?? DynamicTypeImpl.instance, |
| 545 super(expression); | 556 super(expression); |
| 546 | 557 |
| 547 @override List<Object> get arguments => [node, baseType, expectedType]; | 558 @override |
| 548 @override String get message => | 559 List<Object> get arguments => [node, baseType, expectedType]; |
| 560 @override |
| 561 String get message => |
| 549 'Type check failed: {0} ({1}) is not of type {2}' + | 562 'Type check failed: {0} ({1}) is not of type {2}' + |
| 550 ((reason == null) ? '' : ' because $reason'); | 563 ((reason == null) ? '' : ' because $reason'); |
| 551 | 564 |
| 552 @override | 565 @override |
| 553 String get name => 'STRONG_MODE_STATIC_TYPE_ERROR'; | 566 String get name => 'STRONG_MODE_STATIC_TYPE_ERROR'; |
| 554 } | 567 } |
| 555 | 568 |
| 556 // | 569 // |
| 557 // Temporary "casts" of allocation sites - literals, constructor invocations, | 570 // Temporary "casts" of allocation sites - literals, constructor invocations, |
| 558 // and closures. These should be handled by contextual inference. In most | 571 // and closures. These should be handled by contextual inference. In most |
| 559 // cases, inference will be sufficient, though in some it may unmask an actual | 572 // cases, inference will be sufficient, though in some it may unmask an actual |
| 560 // error: e.g., | 573 // error: e.g., |
| 561 // List<int> l = [1, 2, 3]; // Inference succeeds | 574 // List<int> l = [1, 2, 3]; // Inference succeeds |
| 562 // List<String> l = [1, 2, 3]; // Inference reveals static type error | 575 // List<String> l = [1, 2, 3]; // Inference reveals static type error |
| 563 // We're marking all as warnings for now. | 576 // We're marking all as warnings for now. |
| 564 // | 577 // |
| 565 // TODO(vsm,leafp): Remove this. | 578 // TODO(vsm,leafp): Remove this. |
| 566 class UninferredClosure extends DownCast { | 579 class UninferredClosure extends DownCast { |
| 567 UninferredClosure(TypeSystem rules, FunctionExpression expression, Cast cast) | 580 UninferredClosure(TypeSystem rules, FunctionExpression expression, Cast cast) |
| 568 : super._internal(rules, expression, cast); | 581 : super._internal(rules, expression, cast); |
| 569 | 582 |
| 570 @override | 583 @override |
| 571 String get name => 'STRONG_MODE_UNINFERRED_CLOSURE'; | 584 String get name => 'STRONG_MODE_UNINFERRED_CLOSURE'; |
| 572 | 585 |
| 573 toErrorCode() => new StaticTypeWarningCode(name, message); | 586 toErrorCode() => new StaticTypeWarningCode(name, message); |
| 574 } | 587 } |
| OLD | NEW |