| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 engine.resolver; | 5 library engine.resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import '../task/strong/info.dart' show InferredType, StaticInfo; | 9 import '../task/strong/info.dart' show InferredType, StaticInfo; |
| 10 import '../task/strong/rules.dart' show TypeRules; | 10 import '../task/strong/rules.dart' show TypeRules; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 Object visitIsExpression(IsExpression node) { | 207 Object visitIsExpression(IsExpression node) { |
| 208 _checkAllTypeChecks(node); | 208 _checkAllTypeChecks(node); |
| 209 return super.visitIsExpression(node); | 209 return super.visitIsExpression(node); |
| 210 } | 210 } |
| 211 | 211 |
| 212 @override | 212 @override |
| 213 Object visitMethodDeclaration(MethodDeclaration node) { | 213 Object visitMethodDeclaration(MethodDeclaration node) { |
| 214 // This was determined to not be a good hint, see: dartbug.com/16029 | 214 // This was determined to not be a good hint, see: dartbug.com/16029 |
| 215 //checkForOverridingPrivateMember(node); | 215 //checkForOverridingPrivateMember(node); |
| 216 _checkForMissingReturn(node.returnType, node.body); | 216 _checkForMissingReturn(node.returnType, node.body); |
| 217 _checkForUnnecessaryNoSuchMethod(node); |
| 217 return super.visitMethodDeclaration(node); | 218 return super.visitMethodDeclaration(node); |
| 218 } | 219 } |
| 219 | 220 |
| 220 @override | 221 @override |
| 221 Object visitMethodInvocation(MethodInvocation node) { | 222 Object visitMethodInvocation(MethodInvocation node) { |
| 222 _checkForCanBeNullAfterNullAware(node.realTarget, node.operator); | 223 _checkForCanBeNullAfterNullAware(node.realTarget, node.operator); |
| 223 return super.visitMethodInvocation(node); | 224 return super.visitMethodInvocation(node); |
| 224 } | 225 } |
| 225 | 226 |
| 226 @override | 227 @override |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 } else if (condition is PropertyAccess) { | 747 } else if (condition is PropertyAccess) { |
| 747 Token operator = condition.operator; | 748 Token operator = condition.operator; |
| 748 if (operator != null && operator.type == TokenType.QUESTION_PERIOD) { | 749 if (operator != null && operator.type == TokenType.QUESTION_PERIOD) { |
| 749 _errorReporter.reportErrorForNode( | 750 _errorReporter.reportErrorForNode( |
| 750 HintCode.NULL_AWARE_IN_CONDITION, condition); | 751 HintCode.NULL_AWARE_IN_CONDITION, condition); |
| 751 } | 752 } |
| 752 } | 753 } |
| 753 } | 754 } |
| 754 | 755 |
| 755 /** | 756 /** |
| 756 * Check for the passed class declaration for the | |
| 757 * [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE] hint code. | |
| 758 * | |
| 759 * @param node the class declaration to check | |
| 760 * @return `true` if and only if a hint code is generated on the passed node | |
| 761 * See [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE]. | |
| 762 */ | |
| 763 // bool _checkForOverrideEqualsButNotHashCode(ClassDeclaration node) { | |
| 764 // ClassElement classElement = node.element; | |
| 765 // if (classElement == null) { | |
| 766 // return false; | |
| 767 // } | |
| 768 // MethodElement equalsOperatorMethodElement = | |
| 769 // classElement.getMethod(sc.TokenType.EQ_EQ.lexeme); | |
| 770 // if (equalsOperatorMethodElement != null) { | |
| 771 // PropertyAccessorElement hashCodeElement = | |
| 772 // classElement.getGetter(_HASHCODE_GETTER_NAME); | |
| 773 // if (hashCodeElement == null) { | |
| 774 // _errorReporter.reportErrorForNode( | |
| 775 // HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE, | |
| 776 // node.name, | |
| 777 // [classElement.displayName]); | |
| 778 // return true; | |
| 779 // } | |
| 780 // } | |
| 781 // return false; | |
| 782 // } | |
| 783 | |
| 784 /** | |
| 785 * Check for the passed as expression for the [HintCode.UNNECESSARY_CAST] hint
code. | 757 * Check for the passed as expression for the [HintCode.UNNECESSARY_CAST] hint
code. |
| 786 * | 758 * |
| 787 * @param node the as expression to check | 759 * @param node the as expression to check |
| 788 * @return `true` if and only if a hint code is generated on the passed node | 760 * @return `true` if and only if a hint code is generated on the passed node |
| 789 * See [HintCode.UNNECESSARY_CAST]. | 761 * See [HintCode.UNNECESSARY_CAST]. |
| 790 */ | 762 */ |
| 791 bool _checkForUnnecessaryCast(AsExpression node) { | 763 bool _checkForUnnecessaryCast(AsExpression node) { |
| 792 // TODO(jwren) After dartbug.com/13732, revisit this, we should be able to | 764 // TODO(jwren) After dartbug.com/13732, revisit this, we should be able to |
| 793 // remove the (x is! TypeParameterType) checks. | 765 // remove the (x is! TypeParameterType) checks. |
| 794 AstNode parent = node.parent; | 766 AstNode parent = node.parent; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 824 !lhsType.isDynamic && | 796 !lhsType.isDynamic && |
| 825 !rhsType.isDynamic && | 797 !rhsType.isDynamic && |
| 826 lhsType.isMoreSpecificThan(rhsType)) { | 798 lhsType.isMoreSpecificThan(rhsType)) { |
| 827 _errorReporter.reportErrorForNode(HintCode.UNNECESSARY_CAST, node); | 799 _errorReporter.reportErrorForNode(HintCode.UNNECESSARY_CAST, node); |
| 828 return true; | 800 return true; |
| 829 } | 801 } |
| 830 return false; | 802 return false; |
| 831 } | 803 } |
| 832 | 804 |
| 833 /** | 805 /** |
| 806 * Check for the passed class declaration for the |
| 807 * [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE] hint code. |
| 808 * |
| 809 * @param node the class declaration to check |
| 810 * @return `true` if and only if a hint code is generated on the passed node |
| 811 * See [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE]. |
| 812 */ |
| 813 // bool _checkForOverrideEqualsButNotHashCode(ClassDeclaration node) { |
| 814 // ClassElement classElement = node.element; |
| 815 // if (classElement == null) { |
| 816 // return false; |
| 817 // } |
| 818 // MethodElement equalsOperatorMethodElement = |
| 819 // classElement.getMethod(sc.TokenType.EQ_EQ.lexeme); |
| 820 // if (equalsOperatorMethodElement != null) { |
| 821 // PropertyAccessorElement hashCodeElement = |
| 822 // classElement.getGetter(_HASHCODE_GETTER_NAME); |
| 823 // if (hashCodeElement == null) { |
| 824 // _errorReporter.reportErrorForNode( |
| 825 // HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE, |
| 826 // node.name, |
| 827 // [classElement.displayName]); |
| 828 // return true; |
| 829 // } |
| 830 // } |
| 831 // return false; |
| 832 // } |
| 833 |
| 834 /** |
| 835 * Generate a hint for `noSuchMethod` methods that do nothing except of |
| 836 * calling another `noSuchMethod` that is not defined by `Object`. |
| 837 * |
| 838 * @return `true` if and only if a hint code is generated on the passed node |
| 839 * See [HintCode.UNNECESSARY_NO_SUCH_METHOD]. |
| 840 */ |
| 841 bool _checkForUnnecessaryNoSuchMethod(MethodDeclaration node) { |
| 842 if (node.name.name != FunctionElement.NO_SUCH_METHOD_METHOD_NAME) { |
| 843 return false; |
| 844 } |
| 845 bool isNonObjectNoSuchMethodInvocation(Expression invocation) { |
| 846 if (invocation is MethodInvocation && |
| 847 invocation.target is SuperExpression && |
| 848 invocation.argumentList.arguments.length == 1) { |
| 849 SimpleIdentifier name = invocation.methodName; |
| 850 if (name.name == FunctionElement.NO_SUCH_METHOD_METHOD_NAME) { |
| 851 Element methodElement = name.staticElement; |
| 852 Element classElement = methodElement?.enclosingElement; |
| 853 return methodElement is MethodElement && |
| 854 classElement is ClassElement && |
| 855 !classElement.type.isObject; |
| 856 } |
| 857 } |
| 858 return false; |
| 859 } |
| 860 FunctionBody body = node.body; |
| 861 if (body is ExpressionFunctionBody) { |
| 862 if (isNonObjectNoSuchMethodInvocation(body.expression)) { |
| 863 _errorReporter.reportErrorForNode( |
| 864 HintCode.UNNECESSARY_NO_SUCH_METHOD, node); |
| 865 return true; |
| 866 } |
| 867 } else if (body is BlockFunctionBody) { |
| 868 List<Statement> statements = body.block.statements; |
| 869 if (statements.length == 1) { |
| 870 Statement returnStatement = statements.first; |
| 871 if (returnStatement is ReturnStatement && |
| 872 isNonObjectNoSuchMethodInvocation(returnStatement.expression)) { |
| 873 _errorReporter.reportErrorForNode( |
| 874 HintCode.UNNECESSARY_NO_SUCH_METHOD, node); |
| 875 return true; |
| 876 } |
| 877 } |
| 878 } |
| 879 return false; |
| 880 } |
| 881 |
| 882 /** |
| 834 * Check for situations where the result of a method or function is used, when
it returns 'void'. | 883 * Check for situations where the result of a method or function is used, when
it returns 'void'. |
| 835 * | 884 * |
| 836 * TODO(jwren) Many other situations of use could be covered. We currently cov
er the cases var x = | 885 * TODO(jwren) Many other situations of use could be covered. We currently cov
er the cases var x = |
| 837 * m() and x = m(), but we could also cover cases such as m().x, m()[k], a + m
(), f(m()), return | 886 * m() and x = m(), but we could also cover cases such as m().x, m()[k], a + m
(), f(m()), return |
| 838 * m(). | 887 * m(). |
| 839 * | 888 * |
| 840 * @param node expression on the RHS of some assignment | 889 * @param node expression on the RHS of some assignment |
| 841 * @return `true` if and only if a hint code is generated on the passed node | 890 * @return `true` if and only if a hint code is generated on the passed node |
| 842 * See [HintCode.USE_OF_VOID_RESULT]. | 891 * See [HintCode.USE_OF_VOID_RESULT]. |
| 843 */ | 892 */ |
| (...skipping 15227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16071 nonFields.add(node); | 16120 nonFields.add(node); |
| 16072 return null; | 16121 return null; |
| 16073 } | 16122 } |
| 16074 | 16123 |
| 16075 @override | 16124 @override |
| 16076 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); | 16125 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); |
| 16077 | 16126 |
| 16078 @override | 16127 @override |
| 16079 Object visitWithClause(WithClause node) => null; | 16128 Object visitWithClause(WithClause node) => null; |
| 16080 } | 16129 } |
| OLD | NEW |