Chromium Code Reviews| Index: lib/src/checker/rules.dart |
| diff --git a/lib/src/checker/rules.dart b/lib/src/checker/rules.dart |
| index 5fe33e6f811ca1fba3e9cb48f4be27fde31d851c..e6e0569b5d0537c128f67a8263457a57e003f47f 100644 |
| --- a/lib/src/checker/rules.dart |
| +++ b/lib/src/checker/rules.dart |
| @@ -43,7 +43,7 @@ abstract class TypeRules { |
| bool isDynamic(DartType t); |
| bool isDynamicTarget(Expression expr); |
| - bool isDynamicGet(Expression expr); |
| + bool isDynamicGet(Expression expr, String name); |
| bool isDynamicCall(Expression call); |
| } |
| @@ -74,7 +74,7 @@ class DartRules extends TypeRules { |
| /// By default, all invocations are dynamic in Dart. |
| bool isDynamic(DartType t) => true; |
| bool isDynamicTarget(Expression expr) => true; |
| - bool isDynamicGet(Expression expr) => true; |
| + bool isDynamicGet(Expression expr, String name) => true; |
| bool isDynamicCall(Expression call) => true; |
| } |
| @@ -517,11 +517,14 @@ class RestrictedRules extends TypeRules { |
| /// Returns `true` if the expression is a dynamic property access or prefixed |
| /// identifier. |
| - bool isDynamicGet(Expression expr) { |
| + bool isDynamicGet(Expression expr, String name) { |
| + // Check if this is a library-level (top-level access) |
| if (options.ignoreTypes) return true; |
| var t = getStaticType(expr); |
| // TODO(jmesserly): we should not allow all property gets on `Function` |
| - return t.isDynamic || t.isDartCoreFunction; |
| + return (t.isDynamic || t.isDartCoreFunction) && |
| + name != 'hashCode' && |
|
Jacob
2015/04/02 18:29:49
Add TODO: get all object properties from the AST.
|
| + name != 'runtimeType'; |
| } |
| /// Returns `true` if the expression is a dynamic function call or method |
| @@ -529,9 +532,27 @@ class RestrictedRules extends TypeRules { |
| bool isDynamicCall(Expression call) { |
| if (options.ignoreTypes) return true; |
| var t = getStaticType(call); |
| + |
| // TODO(jmesserly): fix handling of types with `call` methods. These are not |
| // FunctionType, but they also aren't dynamic calls. |
| + |
| if (t.isDynamic || t.isDartCoreFunction || t is! FunctionType) { |
| + // 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.
|
| + 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
|
| + var parent = call.parent; |
| + // Verify this is a method invocation with no arguments. |
| + 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 ()->*,
|
| + parent.methodName == call && |
| + parent.argumentList.arguments.isEmpty) { |
| + // 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.
|
| + var target = parent.realTarget; |
| + if (target != null && |
| + (target is! SimpleIdentifier || |
| + target.staticElement is! PrefixElement)) { |
| + return false; |
| + } |
| + } |
| + } |
| return true; |
| } |
| // Dynamic as the parameter type is treated as bottom. A function with |