| Index: pkg/analyzer/lib/src/task/strong/checker.dart
|
| diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
|
| index 19e1c8c02bbc57e12372d140195c568a86a416b5..ab1922fc1604c446e1b3d70e5ee81c142ff7044f 100644
|
| --- a/pkg/analyzer/lib/src/task/strong/checker.dart
|
| +++ b/pkg/analyzer/lib/src/task/strong/checker.dart
|
| @@ -236,14 +236,14 @@ class CodeChecker extends RecursiveAstVisitor {
|
| void visitBinaryExpression(BinaryExpression node) {
|
| var op = node.operator;
|
| if (op.isUserDefinableOperator) {
|
| - if (_isDynamicTarget(node.leftOperand)) {
|
| + var element = node.staticElement;
|
| + if (element == null) {
|
| // Dynamic invocation
|
| // TODO(vsm): Move this logic to the resolver?
|
| if (op.type != TokenType.EQ_EQ && op.type != TokenType.BANG_EQ) {
|
| _recordDynamicInvoke(node, node.leftOperand);
|
| }
|
| } else {
|
| - var element = node.staticElement;
|
| // Method invocation.
|
| if (element is MethodElement) {
|
| var type = element.type;
|
| @@ -436,20 +436,18 @@ class CodeChecker extends RecursiveAstVisitor {
|
| @override
|
| void visitIndexExpression(IndexExpression node) {
|
| var target = node.realTarget;
|
| - if (_isDynamicTarget(target)) {
|
| + var element = node.staticElement;
|
| + if (element == null) {
|
| _recordDynamicInvoke(node, target);
|
| - } else {
|
| - var element = node.staticElement;
|
| - if (element is MethodElement) {
|
| - var type = element.type;
|
| - // Analyzer should enforce number of parameter types, but check in
|
| - // case we have erroneous input.
|
| - if (type.normalParameterTypes.isNotEmpty) {
|
| - checkArgument(node.index, type.normalParameterTypes[0]);
|
| - }
|
| - } else {
|
| - // TODO(vsm): Assert that the analyzer found an error here?
|
| + } else if (element is MethodElement) {
|
| + var type = element.type;
|
| + // Analyzer should enforce number of parameter types, but check in
|
| + // case we have erroneous input.
|
| + if (type.normalParameterTypes.isNotEmpty) {
|
| + checkArgument(node.index, type.normalParameterTypes[0]);
|
| }
|
| + } else {
|
| + // TODO(vsm): Assert that the analyzer found an error here?
|
| }
|
| node.visitChildren(this);
|
| }
|
| @@ -533,7 +531,8 @@ class CodeChecker extends RecursiveAstVisitor {
|
| @override
|
| visitMethodInvocation(MethodInvocation node) {
|
| var target = node.realTarget;
|
| - if (_isDynamicTarget(target) && !_isObjectMethod(node, node.methodName)) {
|
| + var element = node.methodName.staticElement;
|
| + if (element == null && !_isObjectMethod(node, node.methodName)) {
|
| _recordDynamicInvoke(node, target);
|
|
|
| // Mark the tear-off as being dynamic, too. This lets us distinguish
|
| @@ -558,7 +557,7 @@ class CodeChecker extends RecursiveAstVisitor {
|
|
|
| @override
|
| void visitPostfixExpression(PostfixExpression node) {
|
| - _checkUnary(node);
|
| + _checkUnary(node, node.staticElement);
|
| node.visitChildren(this);
|
| }
|
|
|
| @@ -572,7 +571,7 @@ class CodeChecker extends RecursiveAstVisitor {
|
| if (node.operator.type == TokenType.BANG) {
|
| checkBoolean(node.operand);
|
| } else {
|
| - _checkUnary(node);
|
| + _checkUnary(node, node.staticElement);
|
| }
|
| node.visitChildren(this);
|
| }
|
| @@ -761,8 +760,7 @@ class CodeChecker extends RecursiveAstVisitor {
|
| }
|
|
|
| void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) {
|
| - if ((_isDynamicTarget(target) || field.staticElement == null) &&
|
| - !_isObjectProperty(target, field)) {
|
| + if (field.staticElement == null && !_isObjectProperty(target, field)) {
|
| _recordDynamicInvoke(node, target);
|
| }
|
| node.visitChildren(this);
|
| @@ -901,12 +899,13 @@ class CodeChecker extends RecursiveAstVisitor {
|
| }
|
| }
|
|
|
| - void _checkUnary(/*PrefixExpression|PostfixExpression*/ node) {
|
| + void _checkUnary(
|
| + /*PrefixExpression|PostfixExpression*/ node, Element element) {
|
| var op = node.operator;
|
| if (op.isUserDefinableOperator ||
|
| op.type == TokenType.PLUS_PLUS ||
|
| op.type == TokenType.MINUS_MINUS) {
|
| - if (_isDynamicTarget(node.operand)) {
|
| + if (element == null) {
|
| _recordDynamicInvoke(node, node.operand);
|
| }
|
| // For ++ and --, even if it is not dynamic, we still need to check
|
| @@ -1020,21 +1019,6 @@ class CodeChecker extends RecursiveAstVisitor {
|
| return rules.anyParameterType(ft, (pt) => pt.isDynamic);
|
| }
|
|
|
| - /// Returns `true` if the target expression is dynamic.
|
| - bool _isDynamicTarget(Expression node) {
|
| - if (node == null) return false;
|
| -
|
| - if (_isLibraryPrefix(node)) return false;
|
| -
|
| - // Null type happens when we have unknown identifiers, like a dart: import
|
| - // that doesn't resolve.
|
| - var type = node.staticType;
|
| - return type == null || type.isDynamic;
|
| - }
|
| -
|
| - bool _isLibraryPrefix(Expression node) =>
|
| - node is SimpleIdentifier && node.staticElement is PrefixElement;
|
| -
|
| bool _isObjectGetter(Expression target, SimpleIdentifier id) {
|
| PropertyAccessorElement element =
|
| typeProvider.objectType.element.getGetter(id.name);
|
| @@ -1055,7 +1039,7 @@ class CodeChecker extends RecursiveAstVisitor {
|
| // TODO(jmesserly): we may eventually want to record if the whole operation
|
| // (node) was dynamic, rather than the target, but this is an easier fit
|
| // with what we used to do.
|
| - setIsDynamicInvoke(target, true);
|
| + if (target != null) setIsDynamicInvoke(target, true);
|
| }
|
|
|
| /// Records an implicit cast for the [expression] from [fromType] to [toType].
|
|
|