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 library dev_compiler.src.checker.rules; | 5 library dev_compiler.src.checker.rules; |
6 | 6 |
7 import 'package:analyzer/src/generated/ast.dart'; | 7 import 'package:analyzer/src/generated/ast.dart'; |
8 import 'package:analyzer/src/generated/element.dart'; | 8 import 'package:analyzer/src/generated/element.dart'; |
9 import 'package:analyzer/src/generated/resolver.dart'; | 9 import 'package:analyzer/src/generated/resolver.dart'; |
10 | 10 |
(...skipping 25 matching lines...) Expand all Loading... | |
36 bool maybeNonNullableType(DartType t) => false; | 36 bool maybeNonNullableType(DartType t) => false; |
37 | 37 |
38 StaticInfo checkAssignment(Expression expr, DartType t, bool constContext); | 38 StaticInfo checkAssignment(Expression expr, DartType t, bool constContext); |
39 | 39 |
40 DartType getStaticType(Expression expr) => expr.staticType; | 40 DartType getStaticType(Expression expr) => expr.staticType; |
41 | 41 |
42 DartType elementType(Element e); | 42 DartType elementType(Element e); |
43 | 43 |
44 bool isDynamic(DartType t); | 44 bool isDynamic(DartType t); |
45 bool isDynamicTarget(Expression expr); | 45 bool isDynamicTarget(Expression expr); |
46 bool isDynamicGet(Expression expr); | 46 bool isDynamicGet(Expression expr, String name); |
47 bool isDynamicCall(Expression call); | 47 bool isDynamicCall(Expression call); |
48 } | 48 } |
49 | 49 |
50 class DartRules extends TypeRules { | 50 class DartRules extends TypeRules { |
51 DartRules(TypeProvider provider) : super(provider); | 51 DartRules(TypeProvider provider) : super(provider); |
52 | 52 |
53 bool isSubTypeOf(DartType t1, DartType t2) { | 53 bool isSubTypeOf(DartType t1, DartType t2) { |
54 return t1.isSubtypeOf(t2); | 54 return t1.isSubtypeOf(t2); |
55 } | 55 } |
56 | 56 |
(...skipping 10 matching lines...) Expand all Loading... | |
67 return null; | 67 return null; |
68 } | 68 } |
69 | 69 |
70 DartType elementType(Element e) { | 70 DartType elementType(Element e) { |
71 return (e as dynamic).type; | 71 return (e as dynamic).type; |
72 } | 72 } |
73 | 73 |
74 /// By default, all invocations are dynamic in Dart. | 74 /// By default, all invocations are dynamic in Dart. |
75 bool isDynamic(DartType t) => true; | 75 bool isDynamic(DartType t) => true; |
76 bool isDynamicTarget(Expression expr) => true; | 76 bool isDynamicTarget(Expression expr) => true; |
77 bool isDynamicGet(Expression expr) => true; | 77 bool isDynamicGet(Expression expr, String name) => true; |
78 bool isDynamicCall(Expression call) => true; | 78 bool isDynamicCall(Expression call) => true; |
79 } | 79 } |
80 | 80 |
81 class RestrictedRules extends TypeRules { | 81 class RestrictedRules extends TypeRules { |
82 final CheckerReporter _reporter; | 82 final CheckerReporter _reporter; |
83 final RulesOptions options; | 83 final RulesOptions options; |
84 final List<DartType> _nonnullableTypes; | 84 final List<DartType> _nonnullableTypes; |
85 DownwardsInference inferrer; | 85 DownwardsInference inferrer; |
86 | 86 |
87 DartType _typeFromName(String name) { | 87 DartType _typeFromName(String name) { |
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
510 } | 510 } |
511 | 511 |
512 bool isDynamic(DartType t) => options.ignoreTypes || t.isDynamic; | 512 bool isDynamic(DartType t) => options.ignoreTypes || t.isDynamic; |
513 | 513 |
514 /// Returns `true` if the target expression is dynamic. | 514 /// Returns `true` if the target expression is dynamic. |
515 bool isDynamicTarget(Expression expr) => | 515 bool isDynamicTarget(Expression expr) => |
516 options.ignoreTypes || getStaticType(expr).isDynamic; | 516 options.ignoreTypes || getStaticType(expr).isDynamic; |
517 | 517 |
518 /// Returns `true` if the expression is a dynamic property access or prefixed | 518 /// Returns `true` if the expression is a dynamic property access or prefixed |
519 /// identifier. | 519 /// identifier. |
520 bool isDynamicGet(Expression expr) { | 520 bool isDynamicGet(Expression expr, String name) { |
521 // Check if this is a library-level (top-level access) | |
521 if (options.ignoreTypes) return true; | 522 if (options.ignoreTypes) return true; |
522 var t = getStaticType(expr); | 523 var t = getStaticType(expr); |
523 // TODO(jmesserly): we should not allow all property gets on `Function` | 524 // TODO(jmesserly): we should not allow all property gets on `Function` |
524 return t.isDynamic || t.isDartCoreFunction; | 525 return (t.isDynamic || t.isDartCoreFunction) && |
526 name != 'hashCode' && | |
Jacob
2015/04/02 18:29:49
Add TODO: get all object properties from the AST.
| |
527 name != 'runtimeType'; | |
525 } | 528 } |
526 | 529 |
527 /// Returns `true` if the expression is a dynamic function call or method | 530 /// Returns `true` if the expression is a dynamic function call or method |
528 /// invocation. | 531 /// invocation. |
529 bool isDynamicCall(Expression call) { | 532 bool isDynamicCall(Expression call) { |
530 if (options.ignoreTypes) return true; | 533 if (options.ignoreTypes) return true; |
531 var t = getStaticType(call); | 534 var t = getStaticType(call); |
535 | |
532 // TODO(jmesserly): fix handling of types with `call` methods. These are not | 536 // TODO(jmesserly): fix handling of types with `call` methods. These are not |
533 // FunctionType, but they also aren't dynamic calls. | 537 // FunctionType, but they also aren't dynamic calls. |
538 | |
534 if (t.isDynamic || t.isDartCoreFunction || t is! FunctionType) { | 539 if (t.isDynamic || t.isDartCoreFunction || t is! FunctionType) { |
540 // Special case Object.toString(). This is always safe to invoke. | |
Jacob
2015/04/02 18:29:49
add a TODO to lookup all methods on Object instead
Jennifer Messerly
2015/04/02 18:56:53
Agreed. It's not too hard to look up the methodele
vsm
2015/04/02 19:21:56
Good point. I'll add the lookup.
| |
541 if (call is SimpleIdentifier && call.name == 'toString') { | |
Jennifer Messerly
2015/04/02 18:56:53
also, what about noSuchMethod? :)
vsm
2015/04/02 19:21:56
We need the dinvoke to verify the type of the argu
| |
542 var parent = call.parent; | |
543 // Verify this is a method invocation with no arguments. | |
544 if (parent is MethodInvocation && | |
Jennifer Messerly
2015/04/02 18:56:53
getting the parent here feels a bit odd. we have t
vsm
2015/04/02 19:21:56
Interesting thought.
If we infer that f is ()->*,
| |
545 parent.methodName == call && | |
546 parent.argumentList.arguments.isEmpty) { | |
547 // Verify that the target is an object (and not a library prefix). | |
Jennifer Messerly
2015/04/02 18:56:53
this can't happen right? calls to library prefixes
vsm
2015/04/02 19:21:56
It can ... see toString in my test.
| |
548 var target = parent.realTarget; | |
549 if (target != null && | |
550 (target is! SimpleIdentifier || | |
551 target.staticElement is! PrefixElement)) { | |
552 return false; | |
553 } | |
554 } | |
555 } | |
535 return true; | 556 return true; |
536 } | 557 } |
537 // Dynamic as the parameter type is treated as bottom. A function with | 558 // Dynamic as the parameter type is treated as bottom. A function with |
538 // a dynamic parameter type requires a dynamic call in general. | 559 // a dynamic parameter type requires a dynamic call in general. |
539 // However, as an optimization, if we have an original definition, we know | 560 // However, as an optimization, if we have an original definition, we know |
540 // dynamic is reified as Object - in this case a regular call is fine. | 561 // dynamic is reified as Object - in this case a regular call is fine. |
541 if (call is SimpleIdentifier) { | 562 if (call is SimpleIdentifier) { |
542 var element = call.staticElement; | 563 var element = call.staticElement; |
543 if (element is FunctionElement || element is MethodElement) { | 564 if (element is FunctionElement || element is MethodElement) { |
544 // An original declaration. | 565 // An original declaration. |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
759 var entries = e.entries; | 780 var entries = e.entries; |
760 bool inferEntry(MapLiteralEntry entry) { | 781 bool inferEntry(MapLiteralEntry entry) { |
761 return inferExpression(entry.key, kType) && | 782 return inferExpression(entry.key, kType) && |
762 inferExpression(entry.value, vType); | 783 inferExpression(entry.value, vType); |
763 } | 784 } |
764 var b = entries.every(inferEntry); | 785 var b = entries.every(inferEntry); |
765 if (b) annotateMapLiteral(e, targs); | 786 if (b) annotateMapLiteral(e, targs); |
766 return b; | 787 return b; |
767 } | 788 } |
768 } | 789 } |
OLD | NEW |