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