| 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 | 
|---|