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 |