| 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 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be | 5 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be |
| 6 // refactored to fit into analyzer. | 6 // refactored to fit into analyzer. |
| 7 library analyzer.src.task.strong.checker; | 7 library analyzer.src.task.strong.checker; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart'; | 9 import 'package:analyzer/analyzer.dart'; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| 11 import 'package:analyzer/dart/ast/token.dart' show TokenType; | 11 import 'package:analyzer/dart/ast/token.dart' show TokenType; |
| 12 import 'package:analyzer/dart/ast/token.dart'; | 12 import 'package:analyzer/dart/ast/token.dart'; |
| 13 import 'package:analyzer/dart/ast/visitor.dart'; | 13 import 'package:analyzer/dart/ast/visitor.dart'; |
| 14 import 'package:analyzer/dart/element/element.dart'; | 14 import 'package:analyzer/dart/element/element.dart'; |
| 15 import 'package:analyzer/dart/element/type.dart'; | 15 import 'package:analyzer/dart/element/type.dart'; |
| 16 import 'package:analyzer/src/dart/element/type.dart'; | 16 import 'package:analyzer/src/dart/element/type.dart'; |
| 17 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl; | 17 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl; |
| 18 import 'package:analyzer/src/generated/error.dart' show StrongModeCode; | 18 import 'package:analyzer/src/generated/error.dart' show StrongModeCode; |
| 19 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; | 19 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; |
| 20 import 'package:analyzer/src/generated/type_system.dart'; | 20 import 'package:analyzer/src/generated/type_system.dart'; |
| 21 | 21 |
| 22 import 'ast_properties.dart'; | 22 import 'ast_properties.dart'; |
| 23 | 23 |
| 24 bool isKnownFunction(Expression expression, {bool instanceMethods: false}) { | 24 bool isKnownFunction(Expression expression) { |
| 25 Element element = null; | 25 Element element = null; |
| 26 if (expression is ParenthesizedExpression) { | 26 if (expression is ParenthesizedExpression) { |
| 27 expression = (expression as ParenthesizedExpression).expression; | 27 expression = (expression as ParenthesizedExpression).expression; |
| 28 } | 28 } |
| 29 if (expression is FunctionExpression) { | 29 if (expression is FunctionExpression) { |
| 30 return true; | 30 return true; |
| 31 } else if (expression is PropertyAccess) { | 31 } else if (expression is PropertyAccess) { |
| 32 element = expression.propertyName.staticElement; | 32 element = expression.propertyName.staticElement; |
| 33 } else if (expression is Identifier) { | 33 } else if (expression is Identifier) { |
| 34 element = expression.staticElement; | 34 element = expression.staticElement; |
| 35 } | 35 } |
| 36 // First class functions and static methods, where we know the original | 36 // First class functions and static methods, where we know the original |
| 37 // declaration, will have an exact type, so we know a downcast will fail. | 37 // declaration, will have an exact type, so we know a downcast will fail. |
| 38 return element is FunctionElement || | 38 return element is FunctionElement || |
| 39 element is MethodElement && (instanceMethods || element.isStatic); | 39 element is MethodElement; |
| 40 } | 40 } |
| 41 | 41 |
| 42 DartType _elementType(Element e) { | 42 DartType _elementType(Element e) { |
| 43 if (e == null) { | 43 if (e == null) { |
| 44 // Malformed code - just return dynamic. | 44 // Malformed code - just return dynamic. |
| 45 return DynamicTypeImpl.instance; | 45 return DynamicTypeImpl.instance; |
| 46 } | 46 } |
| 47 return (e as dynamic).type; | 47 return (e as dynamic).type; |
| 48 } | 48 } |
| 49 | 49 |
| (...skipping 947 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 997 var ft = _getTypeAsCaller(call); | 997 var ft = _getTypeAsCaller(call); |
| 998 // TODO(leafp): This will currently return true if t is Function | 998 // TODO(leafp): This will currently return true if t is Function |
| 999 // This is probably the most correct thing to do for now, since | 999 // This is probably the most correct thing to do for now, since |
| 1000 // this code is also used by the back end. Maybe revisit at some | 1000 // this code is also used by the back end. Maybe revisit at some |
| 1001 // point? | 1001 // point? |
| 1002 if (ft == null) return true; | 1002 if (ft == null) return true; |
| 1003 // Dynamic as the parameter type is treated as bottom. A function with | 1003 // Dynamic as the parameter type is treated as bottom. A function with |
| 1004 // a dynamic parameter type requires a dynamic call in general. | 1004 // a dynamic parameter type requires a dynamic call in general. |
| 1005 // However, as an optimization, if we have an original definition, we know | 1005 // However, as an optimization, if we have an original definition, we know |
| 1006 // dynamic is reified as Object - in this case a regular call is fine. | 1006 // dynamic is reified as Object - in this case a regular call is fine. |
| 1007 if (isKnownFunction(call, instanceMethods: true)) { | 1007 if (isKnownFunction(call)) { |
| 1008 return false; | 1008 return false; |
| 1009 } | 1009 } |
| 1010 return rules.anyParameterType(ft, (pt) => pt.isDynamic); | 1010 return rules.anyParameterType(ft, (pt) => pt.isDynamic); |
| 1011 } | 1011 } |
| 1012 | 1012 |
| 1013 /// Returns `true` if the target expression is dynamic. | 1013 /// Returns `true` if the target expression is dynamic. |
| 1014 bool _isDynamicTarget(Expression node) { | 1014 bool _isDynamicTarget(Expression node) { |
| 1015 if (node == null) return false; | 1015 if (node == null) return false; |
| 1016 | 1016 |
| 1017 if (_isLibraryPrefix(node)) return false; | 1017 if (_isLibraryPrefix(node)) return false; |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1503 var visited = new Set<InterfaceType>(); | 1503 var visited = new Set<InterfaceType>(); |
| 1504 do { | 1504 do { |
| 1505 visited.add(current); | 1505 visited.add(current); |
| 1506 current.mixins.reversed.forEach( | 1506 current.mixins.reversed.forEach( |
| 1507 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); | 1507 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); |
| 1508 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); | 1508 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); |
| 1509 current = current.superclass; | 1509 current = current.superclass; |
| 1510 } while (!current.isObject && !visited.contains(current)); | 1510 } while (!current.isObject && !visited.contains(current)); |
| 1511 } | 1511 } |
| 1512 } | 1512 } |
| OLD | NEW |